diff --git a/modules/cms/classes/AutoDatasource.php b/modules/cms/classes/AutoDatasource.php index bb7c2ad13..7c94b5356 100644 --- a/modules/cms/classes/AutoDatasource.php +++ b/modules/cms/classes/AutoDatasource.php @@ -2,6 +2,7 @@ use Cache; use Exception; +use ApplicationException; use October\Rain\Halcyon\Model; use October\Rain\Halcyon\Processors\Processor; use October\Rain\Halcyon\Datasource\Datasource; @@ -36,6 +37,11 @@ class AutoDatasource extends Datasource implements DatasourceInterface */ public $activeDatasourceKey = ''; + /** + * @var bool Flag to indicate that we're in "single datasource mode" + */ + protected $singleDatasourceMode = false; + /** * Create a new datasource instance. * @@ -131,6 +137,34 @@ class AutoDatasource extends Datasource implements DatasourceInterface return $result; } + /** + * Forces all operations in a provided closure to run within a selected datasource. + * + * @param string $source + * @param \Closure $closure + * @return mixed + */ + public function usingSource(string $source, \Closure $closure) + { + if (!array_key_exists($source, $this->datasources)) { + throw new ApplicationException('Invalid datasource specified.'); + } + + // Setup the datasource for single source mode + $previousSource = $this->activeDatasourceKey; + $this->activeDatasourceKey = $source; + $this->singleDatasourceMode = true; + + // Execute the callback + $return = $closure->call($this); + + // Restore the datasource to auto mode + $this->singleDatasourceMode = false; + $this->activeDatasourceKey = $previousSource; + + return $return; + } + /** * Push the provided model to the specified datasource * @@ -140,23 +174,19 @@ class AutoDatasource extends Datasource implements DatasourceInterface */ public function pushToSource(Model $model, string $source) { - // Set the active datasource to the provided source and retrieve it - $originalActiveKey = $this->activeDatasourceKey; - $this->activeDatasourceKey = $source; - $datasource = $this->getActiveDatasource(); + $this->usingSource($source, function () use ($model) { + $datasource = $this->getActiveDatasource(); - // Get the path parts - $dirName = $model->getObjectTypeDirName(); - list($fileName, $extension) = $model->getFileNameParts(); + // Get the path parts + $dirName = $model->getObjectTypeDirName(); + list($fileName, $extension) = $model->getFileNameParts(); - // Get the file content - $content = $datasource->getPostProcessor()->processUpdate($model->newQuery(), []); + // Get the file content + $content = $datasource->getPostProcessor()->processUpdate($model->newQuery(), []); - // Perform an update on the selected datasource (will insert if it doesn't exist) - $this->update($dirName, $fileName, $extension, $content); - - // Restore the original active datasource - $this->activeDatasourceKey = $originalActiveKey; + // Perform an update on the selected datasource (will insert if it doesn't exist) + $this->update($dirName, $fileName, $extension, $content); + }); } /** @@ -168,20 +198,16 @@ class AutoDatasource extends Datasource implements DatasourceInterface */ public function removeFromSource(Model $model, string $source) { - // Set the active datasource to the provided source and retrieve it - $originalActiveKey = $this->activeDatasourceKey; - $this->activeDatasourceKey = $source; - $datasource = $this->getActiveDatasource(); + $this->usingSource($source, function () use ($model) { + $datasource = $this->getActiveDatasource(); - // Get the path parts - $dirName = $model->getObjectTypeDirName(); - list($fileName, $extension) = $model->getFileNameParts(); + // Get the path parts + $dirName = $model->getObjectTypeDirName(); + list($fileName, $extension) = $model->getFileNameParts(); - // Perform a forced delete on the selected datasource to ensure it's removed - $this->forceDelete($dirName, $fileName, $extension); - - // Restore the original active datasource - $this->activeDatasourceKey = $originalActiveKey; + // Perform a forced delete on the selected datasource to ensure it's removed + $this->forceDelete($dirName, $fileName, $extension); + }); } /** @@ -192,6 +218,11 @@ class AutoDatasource extends Datasource implements DatasourceInterface */ protected function getDatasourceForPath(string $path) { + // Always return the active datasource when singleDatasourceMode is enabled + if ($this->singleDatasourceMode) { + return $this->getActiveDatasource(); + } + // Default to the last datasource provided $datasourceIndex = count($this->datasources) - 1; @@ -238,7 +269,12 @@ class AutoDatasource extends Datasource implements DatasourceInterface $pathsCache = array_reverse($this->pathCache); // Get paths available in the provided dirName, allowing proper prioritization of earlier datasources - foreach ($pathsCache as $sourcePaths) { + foreach ($pathsCache as $datasourceKey => $sourcePaths) { + // Only look at the active datasource if singleDatasourceMode is enabled + if ($this->singleDatasourceMode && $datasourceKey !== $this->activeDatasourceKey) { + continue; + } + $paths = array_merge($paths, array_filter($sourcePaths, function ($path) use ($dirName, $options) { $basePath = $dirName . '/'; diff --git a/modules/system/console/ThemeSync.php b/modules/system/console/ThemeSync.php index 3ace3cc15..9bdeacfe2 100644 --- a/modules/system/console/ThemeSync.php +++ b/modules/system/console/ThemeSync.php @@ -211,21 +211,20 @@ class ThemeSync extends Command */ protected function getModelForPath($path, $modelClass, $theme) { - $originalSource = $this->datasource->activeDatasourceKey; - $this->datasource->activeDatasourceKey = $this->source; + return $this->datasource->usingSource($this->source, function () use ($path, $modelClass, $theme) { + $modelObj = new $modelClass; - $modelObj = new $modelClass; + $entity = $modelClass::load( + $theme, + str_replace($modelObj->getObjectTypeDirName() . '/', '', $path) + ); - $entity = $modelClass::load( - $theme, - str_replace($modelObj->getObjectTypeDirName() . '/', '', $path) - ); + if (!isset($entity)) { + return null; + } - if (!isset($entity)) { - return null; - } - - $this->datasource->activeDatasourceKey = $originalSource; + return $entity; + }); return $entity; }