Add usingSource method to active datasource (#5017)

This allows the `theme:sync` command to properly sync to specified targets.

Fixes #4887. Replaces #4935. Credit to @bennothommo for the initial implementation.
This commit is contained in:
Luke Towers 2020-04-01 04:12:50 -06:00 committed by GitHub
parent 2b22c0e49a
commit e4571c3dd4
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 74 additions and 39 deletions

View File

@ -2,6 +2,7 @@
use Cache; use Cache;
use Exception; use Exception;
use ApplicationException;
use October\Rain\Halcyon\Model; use October\Rain\Halcyon\Model;
use October\Rain\Halcyon\Processors\Processor; use October\Rain\Halcyon\Processors\Processor;
use October\Rain\Halcyon\Datasource\Datasource; use October\Rain\Halcyon\Datasource\Datasource;
@ -36,6 +37,11 @@ class AutoDatasource extends Datasource implements DatasourceInterface
*/ */
public $activeDatasourceKey = ''; public $activeDatasourceKey = '';
/**
* @var bool Flag to indicate that we're in "single datasource mode"
*/
protected $singleDatasourceMode = false;
/** /**
* Create a new datasource instance. * Create a new datasource instance.
* *
@ -131,6 +137,34 @@ class AutoDatasource extends Datasource implements DatasourceInterface
return $result; 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 * 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) public function pushToSource(Model $model, string $source)
{ {
// Set the active datasource to the provided source and retrieve it $this->usingSource($source, function () use ($model) {
$originalActiveKey = $this->activeDatasourceKey; $datasource = $this->getActiveDatasource();
$this->activeDatasourceKey = $source;
$datasource = $this->getActiveDatasource();
// Get the path parts // Get the path parts
$dirName = $model->getObjectTypeDirName(); $dirName = $model->getObjectTypeDirName();
list($fileName, $extension) = $model->getFileNameParts(); list($fileName, $extension) = $model->getFileNameParts();
// Get the file content // Get the file content
$content = $datasource->getPostProcessor()->processUpdate($model->newQuery(), []); $content = $datasource->getPostProcessor()->processUpdate($model->newQuery(), []);
// Perform an update on the selected datasource (will insert if it doesn't exist) // Perform an update on the selected datasource (will insert if it doesn't exist)
$this->update($dirName, $fileName, $extension, $content); $this->update($dirName, $fileName, $extension, $content);
});
// Restore the original active datasource
$this->activeDatasourceKey = $originalActiveKey;
} }
/** /**
@ -168,20 +198,16 @@ class AutoDatasource extends Datasource implements DatasourceInterface
*/ */
public function removeFromSource(Model $model, string $source) public function removeFromSource(Model $model, string $source)
{ {
// Set the active datasource to the provided source and retrieve it $this->usingSource($source, function () use ($model) {
$originalActiveKey = $this->activeDatasourceKey; $datasource = $this->getActiveDatasource();
$this->activeDatasourceKey = $source;
$datasource = $this->getActiveDatasource();
// Get the path parts // Get the path parts
$dirName = $model->getObjectTypeDirName(); $dirName = $model->getObjectTypeDirName();
list($fileName, $extension) = $model->getFileNameParts(); list($fileName, $extension) = $model->getFileNameParts();
// Perform a forced delete on the selected datasource to ensure it's removed // Perform a forced delete on the selected datasource to ensure it's removed
$this->forceDelete($dirName, $fileName, $extension); $this->forceDelete($dirName, $fileName, $extension);
});
// Restore the original active datasource
$this->activeDatasourceKey = $originalActiveKey;
} }
/** /**
@ -192,6 +218,11 @@ class AutoDatasource extends Datasource implements DatasourceInterface
*/ */
protected function getDatasourceForPath(string $path) 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 // Default to the last datasource provided
$datasourceIndex = count($this->datasources) - 1; $datasourceIndex = count($this->datasources) - 1;
@ -238,7 +269,12 @@ class AutoDatasource extends Datasource implements DatasourceInterface
$pathsCache = array_reverse($this->pathCache); $pathsCache = array_reverse($this->pathCache);
// Get paths available in the provided dirName, allowing proper prioritization of earlier datasources // 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) { $paths = array_merge($paths, array_filter($sourcePaths, function ($path) use ($dirName, $options) {
$basePath = $dirName . '/'; $basePath = $dirName . '/';

View File

@ -211,21 +211,20 @@ class ThemeSync extends Command
*/ */
protected function getModelForPath($path, $modelClass, $theme) protected function getModelForPath($path, $modelClass, $theme)
{ {
$originalSource = $this->datasource->activeDatasourceKey; return $this->datasource->usingSource($this->source, function () use ($path, $modelClass, $theme) {
$this->datasource->activeDatasourceKey = $this->source; $modelObj = new $modelClass;
$modelObj = new $modelClass; $entity = $modelClass::load(
$theme,
str_replace($modelObj->getObjectTypeDirName() . '/', '', $path)
);
$entity = $modelClass::load( if (!isset($entity)) {
$theme, return null;
str_replace($modelObj->getObjectTypeDirName() . '/', '', $path) }
);
if (!isset($entity)) { return $entity;
return null; });
}
$this->datasource->activeDatasourceKey = $originalSource;
return $entity; return $entity;
} }