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 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 . '/';

View File

@ -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;
}