From 117dad5a80b32bc3a18dece45f39e4f05a05dda8 Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Mon, 26 Sep 2022 14:08:14 -0400 Subject: [PATCH 01/14] feat(object): add an ObjectServiceProvider for object package services --- packages/app/composer.json | 1 + .../ServiceProvider/AppServiceProvider.php | 2 ++ .../Charcoal/Object/ObjectServiceProvider.php | 27 +++++++++++++++++++ 3 files changed, 30 insertions(+) create mode 100644 packages/object/src/Charcoal/Object/ObjectServiceProvider.php diff --git a/packages/app/composer.json b/packages/app/composer.json index b5ec134ba..5571589bf 100644 --- a/packages/app/composer.json +++ b/packages/app/composer.json @@ -32,6 +32,7 @@ "charcoal/config": "^4.1", "charcoal/event": "^3.2", "charcoal/factory": "^4.1", + "charcoal/object": "^4.1", "charcoal/translator": "^4.1", "charcoal/view": "^4.1", "monolog/monolog": "^1.17", diff --git a/packages/app/src/Charcoal/App/ServiceProvider/AppServiceProvider.php b/packages/app/src/Charcoal/App/ServiceProvider/AppServiceProvider.php index 3859433ac..b831ad0aa 100644 --- a/packages/app/src/Charcoal/App/ServiceProvider/AppServiceProvider.php +++ b/packages/app/src/Charcoal/App/ServiceProvider/AppServiceProvider.php @@ -38,6 +38,7 @@ use Charcoal\App\Template\TemplateInterface; use Charcoal\App\Template\WidgetInterface; use Charcoal\App\Template\WidgetBuilder; +use Charcoal\Object\ObjectServiceProvider; use Charcoal\View\Twig\DebugHelpers as TwigDebugHelpers; use Charcoal\View\Twig\HelpersInterface as TwigHelpersInterface; use Charcoal\View\Twig\UrlHelpers as TwigUrlHelpers; @@ -78,6 +79,7 @@ public function register(Container $container) $container->register(new ScriptServiceProvider()); $container->register(new TranslatorServiceProvider()); $container->register(new ViewServiceProvider()); + $container->register(new ObjectServiceProvider()); $this->registerKernelServices($container); $this->registerHandlerServices($container); diff --git a/packages/object/src/Charcoal/Object/ObjectServiceProvider.php b/packages/object/src/Charcoal/Object/ObjectServiceProvider.php new file mode 100644 index 000000000..8407cf2cd --- /dev/null +++ b/packages/object/src/Charcoal/Object/ObjectServiceProvider.php @@ -0,0 +1,27 @@ +registerRevisionServices($pimple); + } + + private function registerRevisionServices(Container $pimple) + { + $pimple['revision/service'] = function (Container $pimple): RevisionService { + return new RevisionService([ + 'config' => $pimple['admin/config'], + 'model/factory' => $pimple['model/factory'], + ]); + }; + } +} From b41c7c2998bcb6d1ebafe9269f52138217f10992 Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Mon, 26 Sep 2022 14:11:53 -0400 Subject: [PATCH 02/14] refactor(revision): refactor revision object and interface to use ModelInterface as subject --- .../object/src/Charcoal/Object/ObjectRevision.php | 13 +++++++------ .../Charcoal/Object/ObjectRevisionInterface.php | 14 ++++++++------ 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/packages/object/src/Charcoal/Object/ObjectRevision.php b/packages/object/src/Charcoal/Object/ObjectRevision.php index 4f847c572..7773b74b1 100644 --- a/packages/object/src/Charcoal/Object/ObjectRevision.php +++ b/packages/object/src/Charcoal/Object/ObjectRevision.php @@ -2,6 +2,7 @@ namespace Charcoal\Object; +use Charcoal\Model\ModelInterface; use InvalidArgumentException; use DateTime; use DateTimeInterface; @@ -291,10 +292,10 @@ public function getDataDiff() * 2. Load the current item from DB * 3. Create diff from (1) and (2). * - * @param RevisionableInterface $obj The object to create the revision from. + * @param ModelInterface $obj The object to create the revision from. * @return ObjectRevision Chainable */ - public function createFromObject(RevisionableInterface $obj) + public function createFromObject(ModelInterface $obj) { $prevRev = $this->lastObjectRevision($obj); @@ -382,10 +383,10 @@ public function recursiveDiff(array $array1, array $array2) /** * @todo Should return NULL if source does not exist. * - * @param RevisionableInterface $obj The object to load the last revision of. + * @param ModelInterface $obj The object to load the last revision of. * @return ObjectRevision The last revision for the give object. */ - public function lastObjectRevision(RevisionableInterface $obj) + public function lastObjectRevision(ModelInterface $obj) { $rev = $this->modelFactory()->create(self::class); @@ -410,11 +411,11 @@ public function lastObjectRevision(RevisionableInterface $obj) * * @todo Should return NULL if source does not exist. * - * @param RevisionableInterface $obj Target object. + * @param ModelInterface $obj Target object. * @param integer $revNum The revision number to load. * @return ObjectRevision */ - public function objectRevisionNum(RevisionableInterface $obj, $revNum) + public function objectRevisionNum(ModelInterface $obj, $revNum) { $rev = $this->modelFactory()->create(self::class); diff --git a/packages/object/src/Charcoal/Object/ObjectRevisionInterface.php b/packages/object/src/Charcoal/Object/ObjectRevisionInterface.php index 9206ee66c..f95d75d81 100644 --- a/packages/object/src/Charcoal/Object/ObjectRevisionInterface.php +++ b/packages/object/src/Charcoal/Object/ObjectRevisionInterface.php @@ -2,6 +2,8 @@ namespace Charcoal\Object; +use Charcoal\Model\ModelInterface; + /** * Defines a changeset of an object implementing {@see \Charcoal\Object\RevisionableInterface}. * @@ -104,10 +106,10 @@ public function getDataDiff(); * 2. Load the current item from DB * 3. Create diff from (1) and (2). * - * @param RevisionableInterface $obj The object to create the revision from. + * @param ModelInterface $obj The object to create the revision from. * @return ObjectRevision Chainable */ - public function createFromObject(RevisionableInterface $obj); + public function createFromObject(ModelInterface $obj); /** * @param array $dataPrev Optional. The previous revision data. @@ -126,17 +128,17 @@ public function createDiff(array $dataPrev, array $dataObj); public function recursiveDiff(array $array1, array $array2); /** - * @param RevisionableInterface $obj The object to load the last revision of. + * @param ModelInterface $obj The object to load the last revision of. * @return ObjectRevision The last revision for the give object. */ - public function lastObjectRevision(RevisionableInterface $obj); + public function lastObjectRevision(ModelInterface $obj); /** * Retrieve a specific object revision, by revision number. * - * @param RevisionableInterface $obj Target object. + * @param ModelInterface $obj Target object. * @param integer $revNum The revision number to load. * @return ObjectRevision */ - public function objectRevisionNum(RevisionableInterface $obj, $revNum); + public function objectRevisionNum(ModelInterface $obj, $revNum); } From 8fb6b257858b16b0c17727691fc5af920488f2f3 Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Mon, 26 Sep 2022 14:12:23 -0400 Subject: [PATCH 03/14] feat(revision): remove revision generation from Content.php --- packages/object/src/Charcoal/Object/Content.php | 5 ----- 1 file changed, 5 deletions(-) diff --git a/packages/object/src/Charcoal/Object/Content.php b/packages/object/src/Charcoal/Object/Content.php index 32cf80941..57eea1018 100644 --- a/packages/object/src/Charcoal/Object/Content.php +++ b/packages/object/src/Charcoal/Object/Content.php @@ -197,11 +197,6 @@ protected function preUpdate(array $properties = null) { parent::preUpdate($properties); - // Content is revisionable - if ($this['revisionEnabled']) { - $this->generateRevision(); - } - // Timestampable propertiees $this->setLastModified('now'); From 0936d20e320aea239972bd6e5d312c6486ef563c Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Mon, 26 Sep 2022 14:13:05 -0400 Subject: [PATCH 04/14] feat(revision): add a revision service to handle all revision related operations --- .../src/Charcoal/Object/RevisionService.php | 89 +++++++++++++++++++ 1 file changed, 89 insertions(+) create mode 100644 packages/object/src/Charcoal/Object/RevisionService.php diff --git a/packages/object/src/Charcoal/Object/RevisionService.php b/packages/object/src/Charcoal/Object/RevisionService.php new file mode 100644 index 000000000..a2c9a5a75 --- /dev/null +++ b/packages/object/src/Charcoal/Object/RevisionService.php @@ -0,0 +1,89 @@ +config = $dependencies['config']; + $this->setModelFactory($dependencies['model/factory']); + } + + public function generateRevision(ModelInterface $model): ?ObjectRevisionInterface + { + if (!$this->canCreateRevision($model)) { + return null; + } + + // TODO config should be a config class. + $config = $this->findRevisionsConfig($model); + + $revisionObject = isset($config['revision_class']) + ? $this->createRevisionObject($config['revision_class']) + : $this->createRevisionObject(); + $revisionObject->createFromObject($model); + + if (!empty($revisionObject->getDataDiff())) { + $revisionObject->save(); + } + + return $revisionObject; + } + + public function createRevisionObject(string $objectRevisionClass = ObjectRevision::class): ObjectRevisionInterface + { + return $this->modelFactory()->create($objectRevisionClass); + } + + public function canCreateRevision(ModelInterface $model): bool + { + if (!$this->config->get('revision_enabled')) { + return false; + } + + $revisionConfig = $this->findRevisionsConfig($model); + + return ($revisionConfig['enabled'] ?? true); + } + + public function findRevisionsConfig(ModelInterface $model): array + { + $class = get_class($model); + if (in_array($class, $this->getRevisionableClasses())) { + return $this->getRevisionsConfig($class); + } + + foreach ($this->getRevisionableClasses() as $revisonable) { + if ($model instanceof $revisonable) { + $this->getRevisionsConfig($revisonable); + } + } + } + + public function getRevisionsConfig(?string $class = null): array + { + $revisions = $this->config->get('revisions'); + + return $class ? $revisions[$class] : $revisions; + } + + public function getRevisionableClasses(): array + { + return array_keys($this->getRevisionsConfig()); + } +} From 4cb6fbb1ce10f0f85c8686419f02124d53473163 Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Mon, 26 Sep 2022 14:14:00 -0400 Subject: [PATCH 05/14] feat(revision): add a listener to hook revision generation --- .../Object/GenerateRevisionListener.php | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 packages/object/src/Charcoal/Object/GenerateRevisionListener.php diff --git a/packages/object/src/Charcoal/Object/GenerateRevisionListener.php b/packages/object/src/Charcoal/Object/GenerateRevisionListener.php new file mode 100644 index 000000000..7431cf4a7 --- /dev/null +++ b/packages/object/src/Charcoal/Object/GenerateRevisionListener.php @@ -0,0 +1,30 @@ +getObject(); + + $this->revisionService->generateRevision($model); + } + + public function setDependencies(Container $container) + { + parent::setDependencies($container); + + $this->revisionService = $container->get('revision/service'); + } +} From 2bc3eced6a52b6ca17b9fd7419baeb1a831e9481 Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Mon, 26 Sep 2022 16:07:55 -0400 Subject: [PATCH 06/14] feat(revision): add RevisionConfig.php to cast revisions config nodes to --- .../src/Charcoal/Object/RevisionConfig.php | 19 ++++++++++ .../src/Charcoal/Object/RevisionService.php | 35 +++++++++++++------ 2 files changed, 43 insertions(+), 11 deletions(-) create mode 100644 packages/object/src/Charcoal/Object/RevisionConfig.php diff --git a/packages/object/src/Charcoal/Object/RevisionConfig.php b/packages/object/src/Charcoal/Object/RevisionConfig.php new file mode 100644 index 000000000..7f88362b4 --- /dev/null +++ b/packages/object/src/Charcoal/Object/RevisionConfig.php @@ -0,0 +1,19 @@ +findRevisionsConfig($model); - $revisionObject = isset($config['revision_class']) - ? $this->createRevisionObject($config['revision_class']) - : $this->createRevisionObject(); + $revisionObject = $this->createRevisionObject($config->get('revisionClass')); $revisionObject->createFromObject($model); if (!empty($revisionObject->getDataDiff())) { @@ -58,32 +55,48 @@ public function canCreateRevision(ModelInterface $model): bool $revisionConfig = $this->findRevisionsConfig($model); + // If we did not find a config of the value of the config is false, we don't want to revision. + if (!$revisionConfig) { + return false; + } + return ($revisionConfig['enabled'] ?? true); } - public function findRevisionsConfig(ModelInterface $model): array + public function findRevisionsConfig(ModelInterface $model): ?RevisionConfig { $class = get_class($model); if (in_array($class, $this->getRevisionableClasses())) { return $this->getRevisionsConfig($class); } - foreach ($this->getRevisionableClasses() as $revisonable) { - if ($model instanceof $revisonable) { - $this->getRevisionsConfig($revisonable); + // Allows ancestor level configuration. + foreach ($this->getRevisionableClasses() as $class) { + if ($model instanceof $class) { + return $this->getRevisionsConfig($class); } } + + return null; } - public function getRevisionsConfig(?string $class = null): array + private function getRevisionsConfig(string $class): RevisionConfig { $revisions = $this->config->get('revisions'); + $revisionsData = $revisions[$class]; + + // If a config is a boolean instead of a data array, it means we only want to affect the enabled state. + if (is_bool($revisionsData)) { + $revisionsData = [ + 'enabled' => $revisionsData + ]; + } - return $class ? $revisions[$class] : $revisions; + return new RevisionConfig($revisionsData); } public function getRevisionableClasses(): array { - return array_keys($this->getRevisionsConfig()); + return array_keys($this->config->get('revisions')); } } From f2cf7c9d80c0c30490310ae0a7060153978e73e3 Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Mon, 26 Sep 2022 17:45:52 -0400 Subject: [PATCH 07/14] feat(revision): add `properties` and `propertyBlacklist` options for Revisions `properties` limits the scope of revision to only some properties while `propertyBlacklist` ensures that some properties are not processed into the revision --- .../object/src/Charcoal/Object/ObjectRevision.php | 5 +++-- .../Charcoal/Object/ObjectRevisionInterface.php | 3 ++- .../object/src/Charcoal/Object/RevisionConfig.php | 9 ++++++++- .../src/Charcoal/Object/RevisionService.php | 15 ++++++++++++++- 4 files changed, 27 insertions(+), 5 deletions(-) diff --git a/packages/object/src/Charcoal/Object/ObjectRevision.php b/packages/object/src/Charcoal/Object/ObjectRevision.php index 7773b74b1..93f91ab80 100644 --- a/packages/object/src/Charcoal/Object/ObjectRevision.php +++ b/packages/object/src/Charcoal/Object/ObjectRevision.php @@ -293,9 +293,10 @@ public function getDataDiff() * 3. Create diff from (1) and (2). * * @param ModelInterface $obj The object to create the revision from. + * @param array|null $properties List of properties to revision. * @return ObjectRevision Chainable */ - public function createFromObject(ModelInterface $obj) + public function createFromObject(ModelInterface $obj, ?array $properties = null) { $prevRev = $this->lastObjectRevision($obj); @@ -308,7 +309,7 @@ public function createFromObject(ModelInterface $obj) $this->setRevUser($obj['lastModifiedBy']); } - $this->setDataObj($obj->data()); + $this->setDataObj($obj->data($properties)); $this->setDataPrev($prevRev->getDataObj()); $diff = $this->createDiff(); diff --git a/packages/object/src/Charcoal/Object/ObjectRevisionInterface.php b/packages/object/src/Charcoal/Object/ObjectRevisionInterface.php index f95d75d81..de052fafe 100644 --- a/packages/object/src/Charcoal/Object/ObjectRevisionInterface.php +++ b/packages/object/src/Charcoal/Object/ObjectRevisionInterface.php @@ -107,9 +107,10 @@ public function getDataDiff(); * 3. Create diff from (1) and (2). * * @param ModelInterface $obj The object to create the revision from. + * @param array|null $properties List of properties to revision. * @return ObjectRevision Chainable */ - public function createFromObject(ModelInterface $obj); + public function createFromObject(ModelInterface $obj, ?array $properties = null); /** * @param array $dataPrev Optional. The previous revision data. diff --git a/packages/object/src/Charcoal/Object/RevisionConfig.php b/packages/object/src/Charcoal/Object/RevisionConfig.php index 7f88362b4..71a2dab1b 100644 --- a/packages/object/src/Charcoal/Object/RevisionConfig.php +++ b/packages/object/src/Charcoal/Object/RevisionConfig.php @@ -10,10 +10,17 @@ * The config loaded when creating a revision for a model. * The config is generated from the `revisions` key in the config and can be customized per model. * - * `'revisions' : {'Namespace\\Model: {...}'}` : here the `...` represents the data used to create the config. + * {'revisions' : {'Namespace\\Model: {...}'}} here the `...` represents the data used to create the config. */ class RevisionConfig extends AbstractConfig { protected bool $enabled = true; protected string $revisionClass = ObjectRevision::class; + protected array $properties = []; + protected array $propertyBlacklist = [ + 'created', + 'lastModified', + 'createdBy', + 'lastModifiedBy', + ]; } diff --git a/packages/object/src/Charcoal/Object/RevisionService.php b/packages/object/src/Charcoal/Object/RevisionService.php index f619be0f0..f075a3636 100644 --- a/packages/object/src/Charcoal/Object/RevisionService.php +++ b/packages/object/src/Charcoal/Object/RevisionService.php @@ -32,8 +32,21 @@ public function generateRevision(ModelInterface $model): ?ObjectRevisionInterfac $config = $this->findRevisionsConfig($model); + $revisionProperties = array_keys($model->data()); + + if (count($config['properties'])) { + $revisionProperties = array_intersect_key($revisionProperties, $config['properties']); + } + + if (count($config['propertyBlacklist'])) { + $revisionProperties = array_filter( + $revisionProperties, + fn($n) => !in_array($n, $config['propertyBlacklist']) + ); + } + $revisionObject = $this->createRevisionObject($config->get('revisionClass')); - $revisionObject->createFromObject($model); + $revisionObject->createFromObject($model, $revisionProperties); if (!empty($revisionObject->getDataDiff())) { $revisionObject->save(); From fced96e7d9a91f4c0c52f2d0d6e7e467e600c120 Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Tue, 27 Sep 2022 18:07:38 -0400 Subject: [PATCH 08/14] refactor(revision): refactor revision config and service to allow for more flexible configuration --- .../Charcoal/Object/ObjectServiceProvider.php | 17 +- .../src/Charcoal/Object/RevisionConfig.php | 154 ++++++++++++++++-- .../Charcoal/Object/RevisionModelConfig.php | 83 ++++++++++ .../src/Charcoal/Object/RevisionService.php | 98 +++++------ 4 files changed, 283 insertions(+), 69 deletions(-) create mode 100644 packages/object/src/Charcoal/Object/RevisionModelConfig.php diff --git a/packages/object/src/Charcoal/Object/ObjectServiceProvider.php b/packages/object/src/Charcoal/Object/ObjectServiceProvider.php index 8407cf2cd..55e57f84b 100644 --- a/packages/object/src/Charcoal/Object/ObjectServiceProvider.php +++ b/packages/object/src/Charcoal/Object/ObjectServiceProvider.php @@ -17,10 +17,23 @@ public function register(Container $pimple) private function registerRevisionServices(Container $pimple) { + $pimple['revision/config'] = function (Container $pimple): RevisionConfig { + $configData = $pimple['config']->get('revisions'); + + // If the config data is a boolean, it means we only want to affect the enabled state. + if (is_bool($configData)) { + $configData = [ + 'enabled' => $configData, + ]; + } + + return new RevisionConfig($configData); + }; + $pimple['revision/service'] = function (Container $pimple): RevisionService { return new RevisionService([ - 'config' => $pimple['admin/config'], - 'model/factory' => $pimple['model/factory'], + 'revision/config' => $pimple['revision/config'], + 'model/factory' => $pimple['model/factory'], ]); }; } diff --git a/packages/object/src/Charcoal/Object/RevisionConfig.php b/packages/object/src/Charcoal/Object/RevisionConfig.php index 71a2dab1b..c7b9155ef 100644 --- a/packages/object/src/Charcoal/Object/RevisionConfig.php +++ b/packages/object/src/Charcoal/Object/RevisionConfig.php @@ -3,24 +3,156 @@ namespace Charcoal\Object; use Charcoal\Config\AbstractConfig; +use Charcoal\Model\ModelInterface; /** * Revision Config * - * The config loaded when creating a revision for a model. - * The config is generated from the `revisions` key in the config and can be customized per model. - * - * {'revisions' : {'Namespace\\Model: {...}'}} here the `...` represents the data used to create the config. + * Configuration for the project's revision system */ class RevisionConfig extends AbstractConfig { protected bool $enabled = true; protected string $revisionClass = ObjectRevision::class; - protected array $properties = []; - protected array $propertyBlacklist = [ - 'created', - 'lastModified', - 'createdBy', - 'lastModifiedBy', - ]; + // TODO implement the limit feature. + protected ?int $limitPerModel = null; + protected array $models = []; + // Exclude properties from the revision process. + protected array $excludedProperties = []; + + /** + * @param ModelInterface $model + * @return ?RevisionModelConfig + */ + public function buildModelConfig(ModelInterface $model): ?RevisionModelConfig + { + $class = get_class($model); + + if (isset($models[$class])) { + return $this->prepareRevisionModelConfig($model, $models[$class]); + } + + // If the exact class is not defined in the revisions models key, try to find options from inheritance. + foreach ($this->models as $class => $revisionOptions) { + if ($model instanceof $class) { + return $this->prepareRevisionModelConfig($model, $revisionOptions); + } + } + + return null; + } + + /** + * @param ModelInterface $model + * @param array|boolean $revisionOptions + * @return RevisionModelConfig + */ + private function prepareRevisionModelConfig(ModelInterface $model, $revisionOptions): RevisionModelConfig + { + // If a config is a boolean instead of a data array, it means we only want to affect the enabled state. + if (is_bool($revisionOptions)) { + $revisionOptions = [ + 'enabled' => $revisionOptions, + ]; + } + + $extraOptions = [ + 'excludedProperties' => $this->getExcludedProperties(), + ]; + + // Extract excludedProperties options from the model's ancestors. + foreach ($this->models as $class => $modelConfig) { + if ($model instanceof $class) { + // keep only excludedProperties from ancestors + $modelConfig = array_intersect_key($modelConfig, array_flip(['excludedProperties'])); + $extraOptions = array_merge_recursive($extraOptions, $modelConfig); + } + } + + return new RevisionModelConfig(array_merge($revisionOptions, $extraOptions)); + } + + /** + * @return bool + */ + public function isEnabled(): bool + { + return $this->enabled; + } + + /** + * @return string + */ + public function getRevisionClass(): string + { + return $this->revisionClass; + } + + /** + * @param string $revisionClass RevisionClass for RevisionConfig. + * @return self + */ + public function setRevisionClass(string $revisionClass): self + { + $this->revisionClass = $revisionClass; + + return $this; + } + + /** + * @return int|null + */ + public function getLimitPerModel(): ?int + { + return $this->limitPerModel; + } + + /** + * @param int|null $limitPerModel LimitPerModel for RevisionConfig. + * @return self + */ + public function setLimitPerModel(?int $limitPerModel): self + { + $this->limitPerModel = $limitPerModel; + + return $this; + } + + /** + * @return array + */ + public function getModels(): array + { + return $this->models; + } + + /** + * @param array $models Models for RevisionConfig. + * @return self + */ + public function setModels(array $models): self + { + $this->models = $models; + + return $this; + } + + /** + * @return array + */ + public function getExcludedProperties(): array + { + return $this->excludedProperties; + } + + /** + * @param array $excludedProperties ExcludedProperties for RevisionConfig. + * @return self + */ + public function setExcludedProperties(array $excludedProperties): self + { + $this->excludedProperties = $excludedProperties; + + return $this; + } } diff --git a/packages/object/src/Charcoal/Object/RevisionModelConfig.php b/packages/object/src/Charcoal/Object/RevisionModelConfig.php new file mode 100644 index 000000000..ddd39e743 --- /dev/null +++ b/packages/object/src/Charcoal/Object/RevisionModelConfig.php @@ -0,0 +1,83 @@ +enabled; + } + + /** + * @return array + */ + public function getProperties(): array + { + return $this->properties; + } + + public function hasProperties(): bool + { + return !!count($this->properties); + } + + /** + * @return array + */ + public function getExcludedProperties(): array + { + return $this->excludedProperties; + } + + public function hasExcludedProperties(): bool + { + return !!count($this->excludedProperties); + } + + /** + * @return array + */ + public function getIncludedProperties(): array + { + return $this->includedProperties; + } + + public function hasIncludedProperties(): bool + { + return !!count($this->includedProperties); + } + + /** + * @return string + */ + public function getRevisionClass(): string + { + return $this->revisionClass; + } +} diff --git a/packages/object/src/Charcoal/Object/RevisionService.php b/packages/object/src/Charcoal/Object/RevisionService.php index f075a3636..899bf2864 100644 --- a/packages/object/src/Charcoal/Object/RevisionService.php +++ b/packages/object/src/Charcoal/Object/RevisionService.php @@ -2,7 +2,6 @@ namespace Charcoal\Object; -use Charcoal\Admin\Config; use Charcoal\Model\ModelFactoryTrait; use Charcoal\Model\ModelInterface; @@ -16,43 +15,62 @@ class RevisionService { use ModelFactoryTrait; - private Config $config; + private RevisionConfig $revisionConfig; + private array $modelRevisionConfig; public function __construct(array $dependencies) { - $this->config = $dependencies['config']; + $this->revisionConfig = $dependencies['revision/config']; $this->setModelFactory($dependencies['model/factory']); } public function generateRevision(ModelInterface $model): ?ObjectRevisionInterface { - if (!$this->canCreateRevision($model)) { + // Bail early + if ( + !$this->revisionConfig->isEnabled() || + !$this->canCreateRevision($model) + ) { return null; } - $config = $this->findRevisionsConfig($model); + $modelConfig = $this->getModelRevisionConfig($model); + $revisionProperties = $this->parseRevisionProperties($model); - $revisionProperties = array_keys($model->data()); + $revisionObject = $this->createRevisionObject($modelConfig->getRevisionClass()); + $revisionObject->createFromObject($model, $revisionProperties); - if (count($config['properties'])) { - $revisionProperties = array_intersect_key($revisionProperties, $config['properties']); + if (!empty($revisionObject->getDataDiff())) { + $revisionObject->save(); } - if (count($config['propertyBlacklist'])) { - $revisionProperties = array_filter( - $revisionProperties, - fn($n) => !in_array($n, $config['propertyBlacklist']) - ); + return $revisionObject; + } + + public function parseRevisionProperties(ModelInterface $model): array + { + $modelConfig = $this->getModelRevisionConfig($model); + $properties = array_keys($model->data()); + + if ($modelConfig->hasProperties()) { + return array_intersect_key($properties, $modelConfig->getProperties()); } - $revisionObject = $this->createRevisionObject($config->get('revisionClass')); - $revisionObject->createFromObject($model, $revisionProperties); + if ($modelConfig->hasExcludedProperties()) { + $excludedProperties = $modelConfig->getExcludedProperties(); - if (!empty($revisionObject->getDataDiff())) { - $revisionObject->save(); + if ($modelConfig->hasIncludedProperties()) { + $includedProperties = $modelConfig->getIncludedProperties(); + $excludedProperties = array_filter($excludedProperties, fn($e) => in_array($e, $includedProperties)); + } + + return array_filter( + $properties, + fn($n) => !in_array($n, $excludedProperties) + ); } - return $revisionObject; + return $properties; } public function createRevisionObject(string $objectRevisionClass = ObjectRevision::class): ObjectRevisionInterface @@ -62,54 +80,22 @@ public function createRevisionObject(string $objectRevisionClass = ObjectRevisio public function canCreateRevision(ModelInterface $model): bool { - if (!$this->config->get('revision_enabled')) { - return false; - } - - $revisionConfig = $this->findRevisionsConfig($model); + $revisionConfig = $this->getModelRevisionConfig($model); // If we did not find a config of the value of the config is false, we don't want to revision. if (!$revisionConfig) { return false; } - return ($revisionConfig['enabled'] ?? true); + return $revisionConfig->isEnabled(); } - public function findRevisionsConfig(ModelInterface $model): ?RevisionConfig + private function getModelRevisionConfig(ModelInterface $model): ?RevisionModelConfig { - $class = get_class($model); - if (in_array($class, $this->getRevisionableClasses())) { - return $this->getRevisionsConfig($class); + if (!isset($this->modelRevisionConfig[get_class($model)])) { + $this->modelRevisionConfig[get_class($model)] = $this->revisionConfig->buildModelConfig($model); } - // Allows ancestor level configuration. - foreach ($this->getRevisionableClasses() as $class) { - if ($model instanceof $class) { - return $this->getRevisionsConfig($class); - } - } - - return null; - } - - private function getRevisionsConfig(string $class): RevisionConfig - { - $revisions = $this->config->get('revisions'); - $revisionsData = $revisions[$class]; - - // If a config is a boolean instead of a data array, it means we only want to affect the enabled state. - if (is_bool($revisionsData)) { - $revisionsData = [ - 'enabled' => $revisionsData - ]; - } - - return new RevisionConfig($revisionsData); - } - - public function getRevisionableClasses(): array - { - return array_keys($this->config->get('revisions')); + return $this->modelRevisionConfig[get_class($model)]; } } From feddd68103900fd2ecd701fc540b523d47cf8c98 Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Wed, 28 Sep 2022 09:34:10 -0400 Subject: [PATCH 09/14] fix(revision): fix included properties and properties options --- packages/object/src/Charcoal/Object/RevisionService.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/object/src/Charcoal/Object/RevisionService.php b/packages/object/src/Charcoal/Object/RevisionService.php index 899bf2864..087afd70f 100644 --- a/packages/object/src/Charcoal/Object/RevisionService.php +++ b/packages/object/src/Charcoal/Object/RevisionService.php @@ -53,7 +53,7 @@ public function parseRevisionProperties(ModelInterface $model): array $properties = array_keys($model->data()); if ($modelConfig->hasProperties()) { - return array_intersect_key($properties, $modelConfig->getProperties()); + return array_intersect($properties, $modelConfig->getProperties()); } if ($modelConfig->hasExcludedProperties()) { @@ -61,7 +61,7 @@ public function parseRevisionProperties(ModelInterface $model): array if ($modelConfig->hasIncludedProperties()) { $includedProperties = $modelConfig->getIncludedProperties(); - $excludedProperties = array_filter($excludedProperties, fn($e) => in_array($e, $includedProperties)); + $excludedProperties = array_filter($excludedProperties, fn($e) => !in_array($e, $includedProperties)); } return array_filter( From aef32f05c28e6a6b09f4df09d61bddb1d12e05f3 Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Thu, 29 Sep 2022 15:04:22 -0400 Subject: [PATCH 10/14] feat(revision): use the revisions service everywhere and refactor it to require setting a model on the service - a ModelInterface instance must be set on the service - Remove RevisionableInterface.php and RevisionableTrait.php - use dependency locator for RevisionService --- .../Action/Object/RevertRevisionAction.php | 38 +-- .../Admin/Ui/ObjectRevisionsInterface.php | 2 +- .../Admin/Ui/ObjectRevisionsTrait.php | 11 +- .../FormGroup/ObjectRevisionsFormGroup.php | 8 + .../Admin/Widget/FormSidebarWidget.php | 17 +- .../Admin/Widget/ObjectRevisionsWidget.php | 16 ++ .../charcoal/object/object-revision.json | 4 +- .../object/src/Charcoal/Object/Content.php | 4 - .../Object/GenerateRevisionListener.php | 2 +- .../src/Charcoal/Object/ObjectRevision.php | 1 - .../Object/ObjectRevisionInterface.php | 2 +- .../Charcoal/Object/ObjectServiceProvider.php | 8 +- .../src/Charcoal/Object/RevisionService.php | 154 ++++++++++- .../Charcoal/Object/RevisionableInterface.php | 62 ----- .../src/Charcoal/Object/RevisionableTrait.php | 243 ------------------ 15 files changed, 215 insertions(+), 357 deletions(-) delete mode 100644 packages/object/src/Charcoal/Object/RevisionableInterface.php delete mode 100644 packages/object/src/Charcoal/Object/RevisionableTrait.php diff --git a/packages/admin/src/Charcoal/Admin/Action/Object/RevertRevisionAction.php b/packages/admin/src/Charcoal/Admin/Action/Object/RevertRevisionAction.php index 3b320b310..aed868789 100644 --- a/packages/admin/src/Charcoal/Admin/Action/Object/RevertRevisionAction.php +++ b/packages/admin/src/Charcoal/Admin/Action/Object/RevertRevisionAction.php @@ -2,14 +2,15 @@ namespace Charcoal\Admin\Action\Object; +use Charcoal\Object\RevisionService; use Exception; use InvalidArgumentException; // From PSR-7 +use Pimple\Container; use Psr\Http\Message\RequestInterface; use Psr\Http\Message\ResponseInterface; // From 'charcoal-object' use Charcoal\Object\ObjectRevisionInterface; -use Charcoal\Object\RevisionableInterface; // From 'charcoal-admin' use Charcoal\Admin\AdminAction; use Charcoal\Admin\Ui\ObjectContainerInterface; @@ -45,6 +46,15 @@ class RevertRevisionAction extends AdminAction implements ObjectContainerInterfa */ protected $revNum; + private RevisionService $revisionService; + + protected function setDependencies(Container $container) + { + parent::setDependencies($container); + + $this->revisionService = $container->get('revision/service'); + } + /** * Retrieve the list of parameters to extract from the HTTP request. * @@ -62,9 +72,9 @@ protected function validDataFromRequest() /** * Set the revision number to restore. * - * @param integer $revNum The revision number to load. - * @throws InvalidArgumentException If the given revision is invalid. + * @param integer $revNum The revision number to load. * @return ObjectContainerInterface Chainable + * @throws InvalidArgumentException If the given revision is invalid. */ protected function setRevNum($revNum) { @@ -91,8 +101,8 @@ public function revNum() } /** - * @param RequestInterface $request A PSR-7 compatible Request instance. - * @param ResponseInterface $response A PSR-7 compatible Response instance. + * @param RequestInterface $request A PSR-7 compatible Request instance. + * @param ResponseInterface $response A PSR-7 compatible Response instance. * @return ResponseInterface */ public function run(RequestInterface $request, ResponseInterface $response) @@ -107,19 +117,11 @@ public function run(RequestInterface $request, ResponseInterface $response) '{{ errorMessage }}' => $failMessage ]); - $obj = $this->obj(); - if (!($obj instanceof RevisionableInterface)) { - $this->setSuccess(false); - - $this->addFeedback('error', strtr('{{ model }} does not support revisions', [ - '{{ model }}' => $this->getSingularLabelFromObj($obj), - ])); - - return $response->withStatus(400); - } - + $obj = $this->obj(); $revNum = $this->revNum(); - $revision = $obj->revisionNum($revNum); + $this->revisionService->setModel($obj); + + $revision = $this->revisionService->revisionFromNumber($revNum); if (!$revision['id']) { $this->setSuccess(false); @@ -139,7 +141,7 @@ public function run(RequestInterface $request, ResponseInterface $response) return $response->withStatus(404); } - $result = $obj->revertToRevision($revNum); + $result = $this->revisionService->revertToRevision($revNum); if ($result) { $doneMessage = $translator->translate( diff --git a/packages/admin/src/Charcoal/Admin/Ui/ObjectRevisionsInterface.php b/packages/admin/src/Charcoal/Admin/Ui/ObjectRevisionsInterface.php index 846efab13..cb5262de4 100644 --- a/packages/admin/src/Charcoal/Admin/Ui/ObjectRevisionsInterface.php +++ b/packages/admin/src/Charcoal/Admin/Ui/ObjectRevisionsInterface.php @@ -12,5 +12,5 @@ interface ObjectRevisionsInterface /** * @return \Charcoal\Object\ObjectRevisionInterface[] */ - public function objectRevisions(); + public function objectRevisions(): array; } diff --git a/packages/admin/src/Charcoal/Admin/Ui/ObjectRevisionsTrait.php b/packages/admin/src/Charcoal/Admin/Ui/ObjectRevisionsTrait.php index f30af4628..3e6766615 100644 --- a/packages/admin/src/Charcoal/Admin/Ui/ObjectRevisionsTrait.php +++ b/packages/admin/src/Charcoal/Admin/Ui/ObjectRevisionsTrait.php @@ -6,6 +6,7 @@ use Charcoal\Factory\FactoryInterface; // From 'charcoal-object' use Charcoal\Object\ObjectRevisionInterface; +use Charcoal\Object\RevisionService; /** * An implementation, as Trait, of the {@see \Charcoal\Admin\Ui\ObjectRevisionsInterface}. @@ -15,7 +16,7 @@ trait ObjectRevisionsTrait /** * @return ObjectRevisionInterface[] */ - public function objectRevisions() + public function objectRevisions(): array { if (!$this->objType() || !$this->objId()) { return []; @@ -24,7 +25,9 @@ public function objectRevisions() $obj = $this->modelFactory()->create($this->objType()); $obj->setId($this->objId()); - $lastRevision = $obj->latestRevision(); + $this->revisionService()->setModel($obj); + + $lastRevision = $this->revisionService()->latestRevision(); $propLabel = '%2$s'; $callback = function (ObjectRevisionInterface &$revision) use ($lastRevision, $obj, $propLabel) { @@ -67,7 +70,7 @@ public function objectRevisions() $revision->allowRevert = ($lastRevision['revNum'] !== $revision['revNum']); }; - return $obj->allRevisions($callback); + return $this->revisionService()->allRevisions($callback); } /** @@ -88,4 +91,6 @@ abstract public function objId(); * @return FactoryInterface */ abstract protected function modelFactory(); + + abstract protected function revisionService(): RevisionService; } diff --git a/packages/admin/src/Charcoal/Admin/Widget/FormGroup/ObjectRevisionsFormGroup.php b/packages/admin/src/Charcoal/Admin/Widget/FormGroup/ObjectRevisionsFormGroup.php index 526d6d514..70c01bd7e 100644 --- a/packages/admin/src/Charcoal/Admin/Widget/FormGroup/ObjectRevisionsFormGroup.php +++ b/packages/admin/src/Charcoal/Admin/Widget/FormGroup/ObjectRevisionsFormGroup.php @@ -3,6 +3,7 @@ namespace Charcoal\Admin\Widget\FormGroup; // From 'pimple/pimple' +use Charcoal\Object\RevisionService; use Pimple\Container; // From 'charcoal-core' use Charcoal\Model\ModelFactoryTrait; @@ -37,6 +38,12 @@ class ObjectRevisionsFormGroup extends AbstractFormGroup implements */ public $widgetId; + private RevisionService $revisionService; + + protected function revisionService(): RevisionService + { + return $this->revisionService; + } /** * @param string $widgetId The widget identifier. @@ -110,6 +117,7 @@ protected function setDependencies(Container $container) parent::setDependencies($container); $this->setModelFactory($container['model/factory']); + $this->revisionService = $container['revision/service']; $this->objType = $container['request']->getParam('obj_type'); $this->objId = $container['request']->getParam('obj_id'); diff --git a/packages/admin/src/Charcoal/Admin/Widget/FormSidebarWidget.php b/packages/admin/src/Charcoal/Admin/Widget/FormSidebarWidget.php index d2189706b..d96ca5ca3 100644 --- a/packages/admin/src/Charcoal/Admin/Widget/FormSidebarWidget.php +++ b/packages/admin/src/Charcoal/Admin/Widget/FormSidebarWidget.php @@ -2,7 +2,7 @@ namespace Charcoal\Admin\Widget; -use Charcoal\Object\RevisionableInterface; +use Charcoal\Object\RevisionService; use Charcoal\User\AuthAwareInterface; use InvalidArgumentException; // From Pimple @@ -163,6 +163,8 @@ class FormSidebarWidget extends AdminWidget implements */ private $requiredGlobalAclPermissions = []; + private RevisionService $revisionService; + /** * @param array|ArrayInterface $data Class data. * @return FormSidebarWidget Chainable @@ -552,8 +554,10 @@ public function isObjRevisionable() return $this->isObjRevisionable; } - if ($obj instanceof RevisionableInterface && $obj['revisionEnabled']) { - $this->isObjRevisionable = !!count($obj->allRevisions()); + $this->revisionService->setModel($obj); + + if ($this->revisionService->revisionEnabled()) { + $this->isObjRevisionable = !!count($this->revisionService->allRevisions()); } } } @@ -894,4 +898,11 @@ protected function isAssoc(array $array) return !!array_filter($array, 'is_string', ARRAY_FILTER_USE_KEY); } + + protected function setDependencies(Container $container) + { + parent::setDependencies($container); + + $this->revisionService = $container['revision/service']; + } } diff --git a/packages/admin/src/Charcoal/Admin/Widget/ObjectRevisionsWidget.php b/packages/admin/src/Charcoal/Admin/Widget/ObjectRevisionsWidget.php index cb482ded4..25049a3cf 100644 --- a/packages/admin/src/Charcoal/Admin/Widget/ObjectRevisionsWidget.php +++ b/packages/admin/src/Charcoal/Admin/Widget/ObjectRevisionsWidget.php @@ -8,6 +8,8 @@ use Charcoal\Admin\AdminWidget; use Charcoal\Admin\Ui\ObjectRevisionsInterface; use Charcoal\Admin\Ui\ObjectRevisionsTrait; +use Charcoal\Object\RevisionService; +use Pimple\Container; /** * Class ObjectRevisionWidget @@ -27,6 +29,20 @@ class ObjectRevisionsWidget extends AdminWidget implements */ protected $objId; + private RevisionService $revisionService; + + protected function setDependencies(Container $container) + { + parent::setDependencies($container); + + $this->revisionService = $container['revision/service']; + } + + protected function revisionService(): RevisionService + { + return $this->revisionService; + } + /** * @return boolean */ diff --git a/packages/object/metadata/admin/charcoal/object/object-revision.json b/packages/object/metadata/admin/charcoal/object/object-revision.json index 14fd32a23..f5f2954b2 100644 --- a/packages/object/metadata/admin/charcoal/object/object-revision.json +++ b/packages/object/metadata/admin/charcoal/object/object-revision.json @@ -39,7 +39,7 @@ "form": { "type": "charcoal/admin/widget/object-form", "form_ident": "default", - "target_type": "charcoal/object/object-revision" + "obj_type": "charcoal/object/object-revision" } }, "layout": { @@ -57,7 +57,7 @@ "form": { "type": "charcoal/admin/widget/table", "collection_ident": "default", - "target_type": "charcoal/object/object-revision" + "obj_type": "charcoal/object/object-revision" } }, "layout": { diff --git a/packages/object/src/Charcoal/Object/Content.php b/packages/object/src/Charcoal/Object/Content.php index 57eea1018..2b53f1bf0 100644 --- a/packages/object/src/Charcoal/Object/Content.php +++ b/packages/object/src/Charcoal/Object/Content.php @@ -15,8 +15,6 @@ use Charcoal\Object\ContentInterface; use Charcoal\Object\AuthorableInterface; use Charcoal\Object\AuthorableTrait; -use Charcoal\Object\RevisionableInterface; -use Charcoal\Object\RevisionableTrait; use Charcoal\Object\TimestampableInterface; use Charcoal\Object\TimestampableTrait; @@ -26,11 +24,9 @@ class Content extends AbstractModel implements AuthorableInterface, ContentInterface, - RevisionableInterface, TimestampableInterface { use AuthorableTrait; - use RevisionableTrait; use TranslatorAwareTrait; use TimestampableTrait; diff --git a/packages/object/src/Charcoal/Object/GenerateRevisionListener.php b/packages/object/src/Charcoal/Object/GenerateRevisionListener.php index 7431cf4a7..7339f0971 100644 --- a/packages/object/src/Charcoal/Object/GenerateRevisionListener.php +++ b/packages/object/src/Charcoal/Object/GenerateRevisionListener.php @@ -18,7 +18,7 @@ public function __invoke(object $event) /** @var ModelInterface $model */ $model = $event->getObject(); - $this->revisionService->generateRevision($model); + $this->revisionService->setModel($model)->generateRevision(); } public function setDependencies(Container $container) diff --git a/packages/object/src/Charcoal/Object/ObjectRevision.php b/packages/object/src/Charcoal/Object/ObjectRevision.php index 93f91ab80..675ec5bba 100644 --- a/packages/object/src/Charcoal/Object/ObjectRevision.php +++ b/packages/object/src/Charcoal/Object/ObjectRevision.php @@ -15,7 +15,6 @@ use Charcoal\Model\ModelFactoryTrait; // From 'charcoal-object' use Charcoal\Object\ObjectRevisionInterface; -use Charcoal\Object\RevisionableInterface; /** * Represents the changeset of an object. diff --git a/packages/object/src/Charcoal/Object/ObjectRevisionInterface.php b/packages/object/src/Charcoal/Object/ObjectRevisionInterface.php index de052fafe..349c18108 100644 --- a/packages/object/src/Charcoal/Object/ObjectRevisionInterface.php +++ b/packages/object/src/Charcoal/Object/ObjectRevisionInterface.php @@ -5,7 +5,7 @@ use Charcoal\Model\ModelInterface; /** - * Defines a changeset of an object implementing {@see \Charcoal\Object\RevisionableInterface}. + * Defines a changeset of an object implementing {@see \Charcoal\Object\ModelInterface}. * * {@see \Charcoal\Object\ObjectRevision} for a basic implementation. */ diff --git a/packages/object/src/Charcoal/Object/ObjectServiceProvider.php b/packages/object/src/Charcoal/Object/ObjectServiceProvider.php index 55e57f84b..2d0e12978 100644 --- a/packages/object/src/Charcoal/Object/ObjectServiceProvider.php +++ b/packages/object/src/Charcoal/Object/ObjectServiceProvider.php @@ -3,6 +3,7 @@ namespace Charcoal\Object; use Pimple\Container; +use Pimple\Psr11\ServiceLocator; use Pimple\ServiceProviderInterface; /** @@ -31,10 +32,9 @@ private function registerRevisionServices(Container $pimple) }; $pimple['revision/service'] = function (Container $pimple): RevisionService { - return new RevisionService([ - 'revision/config' => $pimple['revision/config'], - 'model/factory' => $pimple['model/factory'], - ]); + $services = new ServiceLocator($pimple, ['revision/config', 'model/factory', 'logger']); + + return new RevisionService($services); }; } } diff --git a/packages/object/src/Charcoal/Object/RevisionService.php b/packages/object/src/Charcoal/Object/RevisionService.php index 087afd70f..b8c5ba9fc 100644 --- a/packages/object/src/Charcoal/Object/RevisionService.php +++ b/packages/object/src/Charcoal/Object/RevisionService.php @@ -2,42 +2,66 @@ namespace Charcoal\Object; +use Charcoal\Loader\CollectionLoader; use Charcoal\Model\ModelFactoryTrait; use Charcoal\Model\ModelInterface; +use Pimple\Psr11\ServiceLocator; +use Psr\Container\ContainerExceptionInterface; +use Psr\Container\NotFoundExceptionInterface; +use Psr\Log\LoggerAwareTrait; /** * Revision Service * * Service handling revision generation and retrieval. * Can be implemented in a listener + * + * Revisions need to act on a ModelInterface, + * So to use the revision service, one have to set a ModelInterface beforehand. + * Failure to do so will result in a */ class RevisionService { use ModelFactoryTrait; + use LoggerAwareTrait; private RevisionConfig $revisionConfig; private array $modelRevisionConfig; + private ModelInterface $model; - public function __construct(array $dependencies) + /** + * @throws ContainerExceptionInterface + * @throws NotFoundExceptionInterface + */ + public function __construct(ServiceLocator $locator) { - $this->revisionConfig = $dependencies['revision/config']; - $this->setModelFactory($dependencies['model/factory']); + $this->revisionConfig = $locator->get('revision/config'); + $this->setModelFactory($locator->get('model/factory')); + $this->setLogger($locator->get('logger')); } - public function generateRevision(ModelInterface $model): ?ObjectRevisionInterface + public function __invoke(ModelInterface $model): self { + $this->setModel($model); + + return $this; + } + + public function generateRevision(): ?ObjectRevisionInterface + { + $model = $this->getModel(); + // Bail early if ( !$this->revisionConfig->isEnabled() || - !$this->canCreateRevision($model) + !$this->revisionEnabled() ) { return null; } - $modelConfig = $this->getModelRevisionConfig($model); - $revisionProperties = $this->parseRevisionProperties($model); + $revisionProperties = $this->parseRevisionProperties(); + $revisionObject = $this->createRevisionObject(); - $revisionObject = $this->createRevisionObject($modelConfig->getRevisionClass()); $revisionObject->createFromObject($model, $revisionProperties); if (!empty($revisionObject->getDataDiff())) { @@ -47,10 +71,67 @@ public function generateRevision(ModelInterface $model): ?ObjectRevisionInterfac return $revisionObject; } - public function parseRevisionProperties(ModelInterface $model): array + public function latestRevision(): ObjectRevisionInterface + { + $model = $this->getModel(); + $revision = $this->createRevisionObject(); + + return $revision->lastObjectRevision($model); + } + + /** + * @return ObjectRevisionInterface[] + */ + public function allRevisions(callable $callback = null): array + { + $model = $this->getModel(); + $loader = $this->createRevisionObjectCollectionLoader(); + + $loader + ->addOrder('revTs', 'desc') + ->addFilters([ + [ + 'property' => 'targetType', + 'value' => $model->objType(), + ], + [ + 'property' => 'targetId', + 'value' => $model->id(), + ], + ]); + + if ($callback !== null) { + $loader->setCallback($callback); + } + + $revisions = $loader->load(); + + return $revisions->objects(); + } + + public function revertToRevision(int $number): bool + { + $model = $this->getModel(); + $revision = $this->revisionFromNumber($number); + + if (!$revision->id()) { + return false; + } + + if (isset($model['lastModifiedBy'])) { + $model['lastModifiedBy'] = $revision->getRevUser(); + } + + $model->setData($revision->getDataObj()); + + return $model->update(); + } + + public function parseRevisionProperties(): array { + $model = $this->getModel(); $modelConfig = $this->getModelRevisionConfig($model); - $properties = array_keys($model->data()); + $properties = array_keys($model->data()); if ($modelConfig->hasProperties()) { return array_intersect($properties, $modelConfig->getProperties()); @@ -73,13 +154,40 @@ public function parseRevisionProperties(ModelInterface $model): array return $properties; } - public function createRevisionObject(string $objectRevisionClass = ObjectRevision::class): ObjectRevisionInterface + public function getObjectRevisionClass(): string { - return $this->modelFactory()->create($objectRevisionClass); + $modelConfig = $this->getModelRevisionConfig(); + + return $modelConfig->getRevisionClass(); } - public function canCreateRevision(ModelInterface $model): bool + public function createRevisionObjectCollectionLoader(): CollectionLoader { + return new CollectionLoader([ + 'logger' => $this->logger, + 'factory' => $this->modelFactory(), + 'model' => $this->getRevisionObjectPrototype($this->getObjectRevisionClass()), + ]); + } + + public function getRevisionObjectPrototype(): ObjectRevisionInterface + { + return $this->modelFactory()->get($this->getObjectRevisionClass()); + } + + public function createRevisionObject(): ObjectRevisionInterface + { + return $this->modelFactory()->create($this->getObjectRevisionClass()); + } + + public function revisionFromNumber(int $number): ObjectRevisionInterface + { + return $this->createRevisionObject()->objectRevisionNum($this->getModel(), $number); + } + + public function revisionEnabled(): bool + { + $model = $this->getModel(); $revisionConfig = $this->getModelRevisionConfig($model); // If we did not find a config of the value of the config is false, we don't want to revision. @@ -90,12 +198,30 @@ public function canCreateRevision(ModelInterface $model): bool return $revisionConfig->isEnabled(); } - private function getModelRevisionConfig(ModelInterface $model): ?RevisionModelConfig + private function getModelRevisionConfig(): ?RevisionModelConfig { + $model = $this->getModel(); + if (!isset($this->modelRevisionConfig[get_class($model)])) { $this->modelRevisionConfig[get_class($model)] = $this->revisionConfig->buildModelConfig($model); } return $this->modelRevisionConfig[get_class($model)]; } + + public function getModel(): ModelInterface + { + if (!isset($this->model)) { + throw new \InvalidArgumentException('Setting a `ModelInterface` is imperative to use the RevisionService'); + } + + return $this->model; + } + + public function setModel(ModelInterface $model): self + { + $this->model = $model; + + return $this; + } } diff --git a/packages/object/src/Charcoal/Object/RevisionableInterface.php b/packages/object/src/Charcoal/Object/RevisionableInterface.php deleted file mode 100644 index 6b60497ed..000000000 --- a/packages/object/src/Charcoal/Object/RevisionableInterface.php +++ /dev/null @@ -1,62 +0,0 @@ -revisionEnabled = !!$enabled; - return $this; - } - - /** - * @return boolean - */ - public function getRevisionEnabled() - { - return $this->revisionEnabled; - } - - /** - * Create a revision collection loader. - * - * @return CollectionLoader - */ - public function createRevisionObjectCollectionLoader() - { - $loader = new CollectionLoader([ - 'logger' => $this->logger, - 'factory' => $this->modelFactory(), - 'model' => $this->getRevisionObjectPrototype(), - ]); - - return $loader; - } - - /** - * Create a revision object. - * - * @return ObjectRevisionInterface - */ - public function createRevisionObject() - { - $rev = $this->modelFactory()->create($this->getObjectRevisionClass()); - - return $rev; - } - - /** - * Retrieve the revision object prototype. - * - * @return ObjectRevisionInterface - */ - public function getRevisionObjectPrototype() - { - $proto = $this->modelFactory()->get($this->getObjectRevisionClass()); - - return $proto; - } - - /** - * Set the class name of the object revision model. - * - * @param string $className The class name of the object revision model. - * @throws InvalidArgumentException If the class name is not a string. - * @return AbstractPropertyDisplay Chainable - */ - protected function setObjectRevisionClass($className) - { - if (!is_string($className)) { - throw new InvalidArgumentException( - 'Route class name must be a string.' - ); - } - - $this->objectRevisionClass = $className; - return $this; - } - - /** - * Retrieve the class name of the object revision model. - * - * @return string - */ - public function getObjectRevisionClass() - { - return $this->objectRevisionClass; - } - - /** - * Alias of {@see self::getObjectRevisionClass()}. - * - * @return string - */ - public function objectRevisionClass() - { - return $this->getObjectRevisionClass(); - } - - /** - * @see \Charcoal\Object\ObjectRevision::create_fromObject() - * @return ObjectRevision - */ - public function generateRevision() - { - $rev = $this->createRevisionObject(); - - $rev->createFromObject($this); - if (!empty($rev->getDataDiff())) { - $rev->save(); - } - - return $rev; - } - - /** - * @see \Charcoal\Object\ObejctRevision::lastObjectRevision - * @return ObjectRevision - */ - public function latestRevision() - { - $rev = $this->createRevisionObject(); - $rev = $rev->lastObjectRevision($this); - - return $rev; - } - - /** - * @see \Charcoal\Object\ObejctRevision::objectRevisionNum() - * - * @todo Should return NULL if source does not exist. - * - * @param integer $revNum The revision number. - * @return ObjectRevision - */ - public function revisionNum($revNum) - { - $rev = $this->createRevisionObject(); - $rev = $rev->objectRevisionNum($this, intval($revNum)); - - return $rev; - } - - /** - * Retrieves all revisions for the current objet - * - * @param callable $callback Optional object callback. - * @return array - */ - public function allRevisions(callable $callback = null) - { - $loader = $this->createRevisionObjectCollectionLoader(); - $loader - ->addOrder('revTs', 'desc') - ->addFilters([ - [ - 'property' => 'targetType', - 'value' => $this->objType(), - ], - [ - 'property' => 'targetId', - 'value' => $this->id(), - ], - ]); - - if ($callback !== null) { - $loader->setCallback($callback); - } - - $revisions = $loader->load(); - return $revisions->objects(); - } - - /** - * @param integer $revNum The revision number to revert to. - * @throws InvalidArgumentException If revision number is invalid. - * @return boolean Success / Failure. - */ - public function revertToRevision($revNum) - { - if (!$revNum) { - throw new InvalidArgumentException( - 'Invalid revision number' - ); - } - - $rev = $this->revisionNum(intval($revNum)); - - if (!$rev->id()) { - return false; - } - - if (isset($obj['lastModifiedBy'])) { - $obj['lastModifiedBy'] = $rev->getRevUser(); - } - - $this->setData($rev->getDataObj()); - $this->update(); - - return true; - } - - /** - * Retrieve the object model factory. - * - * @return \Charcoal\Factory\FactoryInterface - */ - abstract public function modelFactory(); - - /** - * @return \Charcoal\Model\MetadataInterface - */ - abstract public function metadata(); -} From 87490fa34dfacf66d95e36b89b3963794b4c99cf Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Fri, 30 Sep 2022 10:20:42 -0400 Subject: [PATCH 11/14] refactor(revisions): rename `RevisionService` to `RevisionsManager` --- .../Charcoal/Admin/Action/Object/RevertRevisionAction.php | 4 ++-- .../admin/src/Charcoal/Admin/Ui/ObjectRevisionsTrait.php | 4 ++-- .../Admin/Widget/FormGroup/ObjectRevisionsFormGroup.php | 6 +++--- .../admin/src/Charcoal/Admin/Widget/FormSidebarWidget.php | 4 ++-- .../src/Charcoal/Admin/Widget/ObjectRevisionsWidget.php | 6 +++--- .../src/Charcoal/Object/GenerateRevisionListener.php | 2 +- .../object/src/Charcoal/Object/ObjectServiceProvider.php | 4 ++-- .../Object/{RevisionService.php => RevisionsManager.php} | 8 ++++---- 8 files changed, 19 insertions(+), 19 deletions(-) rename packages/object/src/Charcoal/Object/{RevisionService.php => RevisionsManager.php} (97%) diff --git a/packages/admin/src/Charcoal/Admin/Action/Object/RevertRevisionAction.php b/packages/admin/src/Charcoal/Admin/Action/Object/RevertRevisionAction.php index aed868789..91c82008d 100644 --- a/packages/admin/src/Charcoal/Admin/Action/Object/RevertRevisionAction.php +++ b/packages/admin/src/Charcoal/Admin/Action/Object/RevertRevisionAction.php @@ -2,7 +2,7 @@ namespace Charcoal\Admin\Action\Object; -use Charcoal\Object\RevisionService; +use Charcoal\Object\RevisionsManager; use Exception; use InvalidArgumentException; // From PSR-7 @@ -46,7 +46,7 @@ class RevertRevisionAction extends AdminAction implements ObjectContainerInterfa */ protected $revNum; - private RevisionService $revisionService; + private RevisionsManager $revisionService; protected function setDependencies(Container $container) { diff --git a/packages/admin/src/Charcoal/Admin/Ui/ObjectRevisionsTrait.php b/packages/admin/src/Charcoal/Admin/Ui/ObjectRevisionsTrait.php index 3e6766615..45b33dfa5 100644 --- a/packages/admin/src/Charcoal/Admin/Ui/ObjectRevisionsTrait.php +++ b/packages/admin/src/Charcoal/Admin/Ui/ObjectRevisionsTrait.php @@ -6,7 +6,7 @@ use Charcoal\Factory\FactoryInterface; // From 'charcoal-object' use Charcoal\Object\ObjectRevisionInterface; -use Charcoal\Object\RevisionService; +use Charcoal\Object\RevisionsManager; /** * An implementation, as Trait, of the {@see \Charcoal\Admin\Ui\ObjectRevisionsInterface}. @@ -92,5 +92,5 @@ abstract public function objId(); */ abstract protected function modelFactory(); - abstract protected function revisionService(): RevisionService; + abstract protected function revisionService(): RevisionsManager; } diff --git a/packages/admin/src/Charcoal/Admin/Widget/FormGroup/ObjectRevisionsFormGroup.php b/packages/admin/src/Charcoal/Admin/Widget/FormGroup/ObjectRevisionsFormGroup.php index 70c01bd7e..3ba6a6198 100644 --- a/packages/admin/src/Charcoal/Admin/Widget/FormGroup/ObjectRevisionsFormGroup.php +++ b/packages/admin/src/Charcoal/Admin/Widget/FormGroup/ObjectRevisionsFormGroup.php @@ -3,7 +3,7 @@ namespace Charcoal\Admin\Widget\FormGroup; // From 'pimple/pimple' -use Charcoal\Object\RevisionService; +use Charcoal\Object\RevisionsManager; use Pimple\Container; // From 'charcoal-core' use Charcoal\Model\ModelFactoryTrait; @@ -38,9 +38,9 @@ class ObjectRevisionsFormGroup extends AbstractFormGroup implements */ public $widgetId; - private RevisionService $revisionService; + private RevisionsManager $revisionService; - protected function revisionService(): RevisionService + protected function revisionService(): RevisionsManager { return $this->revisionService; } diff --git a/packages/admin/src/Charcoal/Admin/Widget/FormSidebarWidget.php b/packages/admin/src/Charcoal/Admin/Widget/FormSidebarWidget.php index d96ca5ca3..11cb758cb 100644 --- a/packages/admin/src/Charcoal/Admin/Widget/FormSidebarWidget.php +++ b/packages/admin/src/Charcoal/Admin/Widget/FormSidebarWidget.php @@ -2,7 +2,7 @@ namespace Charcoal\Admin\Widget; -use Charcoal\Object\RevisionService; +use Charcoal\Object\RevisionsManager; use Charcoal\User\AuthAwareInterface; use InvalidArgumentException; // From Pimple @@ -163,7 +163,7 @@ class FormSidebarWidget extends AdminWidget implements */ private $requiredGlobalAclPermissions = []; - private RevisionService $revisionService; + private RevisionsManager $revisionService; /** * @param array|ArrayInterface $data Class data. diff --git a/packages/admin/src/Charcoal/Admin/Widget/ObjectRevisionsWidget.php b/packages/admin/src/Charcoal/Admin/Widget/ObjectRevisionsWidget.php index 25049a3cf..b7887eb16 100644 --- a/packages/admin/src/Charcoal/Admin/Widget/ObjectRevisionsWidget.php +++ b/packages/admin/src/Charcoal/Admin/Widget/ObjectRevisionsWidget.php @@ -8,7 +8,7 @@ use Charcoal\Admin\AdminWidget; use Charcoal\Admin\Ui\ObjectRevisionsInterface; use Charcoal\Admin\Ui\ObjectRevisionsTrait; -use Charcoal\Object\RevisionService; +use Charcoal\Object\RevisionsManager; use Pimple\Container; /** @@ -29,7 +29,7 @@ class ObjectRevisionsWidget extends AdminWidget implements */ protected $objId; - private RevisionService $revisionService; + private RevisionsManager $revisionService; protected function setDependencies(Container $container) { @@ -38,7 +38,7 @@ protected function setDependencies(Container $container) $this->revisionService = $container['revision/service']; } - protected function revisionService(): RevisionService + protected function revisionService(): RevisionsManager { return $this->revisionService; } diff --git a/packages/object/src/Charcoal/Object/GenerateRevisionListener.php b/packages/object/src/Charcoal/Object/GenerateRevisionListener.php index 7339f0971..bfcf6eb6e 100644 --- a/packages/object/src/Charcoal/Object/GenerateRevisionListener.php +++ b/packages/object/src/Charcoal/Object/GenerateRevisionListener.php @@ -11,7 +11,7 @@ */ class GenerateRevisionListener extends AbstractEventListener { - protected RevisionService $revisionService; + protected RevisionsManager $revisionService; public function __invoke(object $event) { diff --git a/packages/object/src/Charcoal/Object/ObjectServiceProvider.php b/packages/object/src/Charcoal/Object/ObjectServiceProvider.php index 2d0e12978..e9451a5f7 100644 --- a/packages/object/src/Charcoal/Object/ObjectServiceProvider.php +++ b/packages/object/src/Charcoal/Object/ObjectServiceProvider.php @@ -31,10 +31,10 @@ private function registerRevisionServices(Container $pimple) return new RevisionConfig($configData); }; - $pimple['revision/service'] = function (Container $pimple): RevisionService { + $pimple['revision/service'] = function (Container $pimple): RevisionsManager { $services = new ServiceLocator($pimple, ['revision/config', 'model/factory', 'logger']); - return new RevisionService($services); + return new RevisionsManager($services); }; } } diff --git a/packages/object/src/Charcoal/Object/RevisionService.php b/packages/object/src/Charcoal/Object/RevisionsManager.php similarity index 97% rename from packages/object/src/Charcoal/Object/RevisionService.php rename to packages/object/src/Charcoal/Object/RevisionsManager.php index b8c5ba9fc..75cce4b9e 100644 --- a/packages/object/src/Charcoal/Object/RevisionService.php +++ b/packages/object/src/Charcoal/Object/RevisionsManager.php @@ -11,16 +11,16 @@ use Psr\Log\LoggerAwareTrait; /** - * Revision Service + * Revisions Manager * * Service handling revision generation and retrieval. - * Can be implemented in a listener + * Can be implemented in an event listener * * Revisions need to act on a ModelInterface, * So to use the revision service, one have to set a ModelInterface beforehand. - * Failure to do so will result in a + * Failure to do so will result in an \InvalidArgumentException being thrown. */ -class RevisionService +class RevisionsManager { use ModelFactoryTrait; use LoggerAwareTrait; From a5640ce9579311159e006df446ecfd4ba92967d7 Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Fri, 30 Sep 2022 10:24:59 -0400 Subject: [PATCH 12/14] refactor(revisions): rename revisions config and container keys with the plural form of `Revision` --- .../Admin/Action/Object/RevertRevisionAction.php | 2 +- .../Widget/FormGroup/ObjectRevisionsFormGroup.php | 2 +- .../src/Charcoal/Admin/Widget/FormSidebarWidget.php | 2 +- .../Charcoal/Admin/Widget/ObjectRevisionsWidget.php | 2 +- .../src/Charcoal/Object/GenerateRevisionListener.php | 2 +- .../src/Charcoal/Object/ObjectServiceProvider.php | 12 ++++++++---- .../{RevisionConfig.php => RevisionsConfig.php} | 6 +++--- .../object/src/Charcoal/Object/RevisionsManager.php | 4 ++-- 8 files changed, 18 insertions(+), 14 deletions(-) rename packages/object/src/Charcoal/Object/{RevisionConfig.php => RevisionsConfig.php} (97%) diff --git a/packages/admin/src/Charcoal/Admin/Action/Object/RevertRevisionAction.php b/packages/admin/src/Charcoal/Admin/Action/Object/RevertRevisionAction.php index 91c82008d..0f8b85f69 100644 --- a/packages/admin/src/Charcoal/Admin/Action/Object/RevertRevisionAction.php +++ b/packages/admin/src/Charcoal/Admin/Action/Object/RevertRevisionAction.php @@ -52,7 +52,7 @@ protected function setDependencies(Container $container) { parent::setDependencies($container); - $this->revisionService = $container->get('revision/service'); + $this->revisionService = $container->get('revisions/manager'); } /** diff --git a/packages/admin/src/Charcoal/Admin/Widget/FormGroup/ObjectRevisionsFormGroup.php b/packages/admin/src/Charcoal/Admin/Widget/FormGroup/ObjectRevisionsFormGroup.php index 3ba6a6198..55bc1a978 100644 --- a/packages/admin/src/Charcoal/Admin/Widget/FormGroup/ObjectRevisionsFormGroup.php +++ b/packages/admin/src/Charcoal/Admin/Widget/FormGroup/ObjectRevisionsFormGroup.php @@ -117,7 +117,7 @@ protected function setDependencies(Container $container) parent::setDependencies($container); $this->setModelFactory($container['model/factory']); - $this->revisionService = $container['revision/service']; + $this->revisionService = $container['revisions/manager']; $this->objType = $container['request']->getParam('obj_type'); $this->objId = $container['request']->getParam('obj_id'); diff --git a/packages/admin/src/Charcoal/Admin/Widget/FormSidebarWidget.php b/packages/admin/src/Charcoal/Admin/Widget/FormSidebarWidget.php index 11cb758cb..407fb886b 100644 --- a/packages/admin/src/Charcoal/Admin/Widget/FormSidebarWidget.php +++ b/packages/admin/src/Charcoal/Admin/Widget/FormSidebarWidget.php @@ -903,6 +903,6 @@ protected function setDependencies(Container $container) { parent::setDependencies($container); - $this->revisionService = $container['revision/service']; + $this->revisionService = $container['revisions/manager']; } } diff --git a/packages/admin/src/Charcoal/Admin/Widget/ObjectRevisionsWidget.php b/packages/admin/src/Charcoal/Admin/Widget/ObjectRevisionsWidget.php index b7887eb16..8b52e753e 100644 --- a/packages/admin/src/Charcoal/Admin/Widget/ObjectRevisionsWidget.php +++ b/packages/admin/src/Charcoal/Admin/Widget/ObjectRevisionsWidget.php @@ -35,7 +35,7 @@ protected function setDependencies(Container $container) { parent::setDependencies($container); - $this->revisionService = $container['revision/service']; + $this->revisionService = $container['revisions/manager']; } protected function revisionService(): RevisionsManager diff --git a/packages/object/src/Charcoal/Object/GenerateRevisionListener.php b/packages/object/src/Charcoal/Object/GenerateRevisionListener.php index bfcf6eb6e..7abed4340 100644 --- a/packages/object/src/Charcoal/Object/GenerateRevisionListener.php +++ b/packages/object/src/Charcoal/Object/GenerateRevisionListener.php @@ -25,6 +25,6 @@ public function setDependencies(Container $container) { parent::setDependencies($container); - $this->revisionService = $container->get('revision/service'); + $this->revisionService = $container->get('revisions/manager'); } } diff --git a/packages/object/src/Charcoal/Object/ObjectServiceProvider.php b/packages/object/src/Charcoal/Object/ObjectServiceProvider.php index e9451a5f7..1b17e2a44 100644 --- a/packages/object/src/Charcoal/Object/ObjectServiceProvider.php +++ b/packages/object/src/Charcoal/Object/ObjectServiceProvider.php @@ -18,7 +18,7 @@ public function register(Container $pimple) private function registerRevisionServices(Container $pimple) { - $pimple['revision/config'] = function (Container $pimple): RevisionConfig { + $pimple['revisions/config'] = function (Container $pimple): RevisionsConfig { $configData = $pimple['config']->get('revisions'); // If the config data is a boolean, it means we only want to affect the enabled state. @@ -28,11 +28,15 @@ private function registerRevisionServices(Container $pimple) ]; } - return new RevisionConfig($configData); + return new RevisionsConfig($configData); }; - $pimple['revision/service'] = function (Container $pimple): RevisionsManager { - $services = new ServiceLocator($pimple, ['revision/config', 'model/factory', 'logger']); + $pimple['revisions/manager'] = function (Container $pimple): RevisionsManager { + $services = new ServiceLocator($pimple, [ + 'revisions/config', + 'model/factory', + 'logger' + ]); return new RevisionsManager($services); }; diff --git a/packages/object/src/Charcoal/Object/RevisionConfig.php b/packages/object/src/Charcoal/Object/RevisionsConfig.php similarity index 97% rename from packages/object/src/Charcoal/Object/RevisionConfig.php rename to packages/object/src/Charcoal/Object/RevisionsConfig.php index c7b9155ef..4d849c430 100644 --- a/packages/object/src/Charcoal/Object/RevisionConfig.php +++ b/packages/object/src/Charcoal/Object/RevisionsConfig.php @@ -6,11 +6,11 @@ use Charcoal\Model\ModelInterface; /** - * Revision Config + * Revisions Config * - * Configuration for the project's revision system + * Configuration for the project's revisions system */ -class RevisionConfig extends AbstractConfig +class RevisionsConfig extends AbstractConfig { protected bool $enabled = true; protected string $revisionClass = ObjectRevision::class; diff --git a/packages/object/src/Charcoal/Object/RevisionsManager.php b/packages/object/src/Charcoal/Object/RevisionsManager.php index 75cce4b9e..24c5051ce 100644 --- a/packages/object/src/Charcoal/Object/RevisionsManager.php +++ b/packages/object/src/Charcoal/Object/RevisionsManager.php @@ -25,7 +25,7 @@ class RevisionsManager use ModelFactoryTrait; use LoggerAwareTrait; - private RevisionConfig $revisionConfig; + private RevisionsConfig $revisionConfig; private array $modelRevisionConfig; private ModelInterface $model; @@ -35,7 +35,7 @@ class RevisionsManager */ public function __construct(ServiceLocator $locator) { - $this->revisionConfig = $locator->get('revision/config'); + $this->revisionConfig = $locator->get('revisions/config'); $this->setModelFactory($locator->get('model/factory')); $this->setLogger($locator->get('logger')); } From f296dab3b91b2c6261495c19b4ffdb9b5cb1bb11 Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Fri, 30 Sep 2022 11:13:36 -0400 Subject: [PATCH 13/14] refactor(revisions): rename `ObjectServiceProvider` to `RevisionServiceProvider` --- .../Charcoal/App/ServiceProvider/AppServiceProvider.php | 4 ++-- ...ctServiceProvider.php => RevisionServiceProvider.php} | 9 ++------- 2 files changed, 4 insertions(+), 9 deletions(-) rename packages/object/src/Charcoal/Object/{ObjectServiceProvider.php => RevisionServiceProvider.php} (81%) diff --git a/packages/app/src/Charcoal/App/ServiceProvider/AppServiceProvider.php b/packages/app/src/Charcoal/App/ServiceProvider/AppServiceProvider.php index b831ad0aa..84ee46cd7 100644 --- a/packages/app/src/Charcoal/App/ServiceProvider/AppServiceProvider.php +++ b/packages/app/src/Charcoal/App/ServiceProvider/AppServiceProvider.php @@ -38,7 +38,7 @@ use Charcoal\App\Template\TemplateInterface; use Charcoal\App\Template\WidgetInterface; use Charcoal\App\Template\WidgetBuilder; -use Charcoal\Object\ObjectServiceProvider; +use Charcoal\Object\RevisionServiceProvider; use Charcoal\View\Twig\DebugHelpers as TwigDebugHelpers; use Charcoal\View\Twig\HelpersInterface as TwigHelpersInterface; use Charcoal\View\Twig\UrlHelpers as TwigUrlHelpers; @@ -79,7 +79,7 @@ public function register(Container $container) $container->register(new ScriptServiceProvider()); $container->register(new TranslatorServiceProvider()); $container->register(new ViewServiceProvider()); - $container->register(new ObjectServiceProvider()); + $container->register(new RevisionServiceProvider()); $this->registerKernelServices($container); $this->registerHandlerServices($container); diff --git a/packages/object/src/Charcoal/Object/ObjectServiceProvider.php b/packages/object/src/Charcoal/Object/RevisionServiceProvider.php similarity index 81% rename from packages/object/src/Charcoal/Object/ObjectServiceProvider.php rename to packages/object/src/Charcoal/Object/RevisionServiceProvider.php index 1b17e2a44..38adc231c 100644 --- a/packages/object/src/Charcoal/Object/ObjectServiceProvider.php +++ b/packages/object/src/Charcoal/Object/RevisionServiceProvider.php @@ -7,16 +7,11 @@ use Pimple\ServiceProviderInterface; /** - * Object Service Provider + * Revision Service Provider */ -class ObjectServiceProvider implements ServiceProviderInterface +class RevisionServiceProvider implements ServiceProviderInterface { public function register(Container $pimple) - { - $this->registerRevisionServices($pimple); - } - - private function registerRevisionServices(Container $pimple) { $pimple['revisions/config'] = function (Container $pimple): RevisionsConfig { $configData = $pimple['config']->get('revisions'); From 7d530941eedd224f3cd60930e4342d79e45a740a Mon Sep 17 00:00:00 2001 From: Joel Alphonso Date: Fri, 30 Sep 2022 11:30:21 -0400 Subject: [PATCH 14/14] refactor(revisions): fix method comments --- .../src/Charcoal/Object/RevisionModelConfig.php | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/packages/object/src/Charcoal/Object/RevisionModelConfig.php b/packages/object/src/Charcoal/Object/RevisionModelConfig.php index ddd39e743..d7c1c41ac 100644 --- a/packages/object/src/Charcoal/Object/RevisionModelConfig.php +++ b/packages/object/src/Charcoal/Object/RevisionModelConfig.php @@ -26,16 +26,13 @@ class RevisionModelConfig extends AbstractConfig // include a property that was excluded by a parent. protected array $includedProperties = []; - /** - * @return bool - */ public function isEnabled(): bool { return $this->enabled; } /** - * @return array + * @return string[] */ public function getProperties(): array { @@ -48,7 +45,7 @@ public function hasProperties(): bool } /** - * @return array + * @return string[] */ public function getExcludedProperties(): array { @@ -61,7 +58,7 @@ public function hasExcludedProperties(): bool } /** - * @return array + * @return string[] */ public function getIncludedProperties(): array { @@ -70,11 +67,11 @@ public function getIncludedProperties(): array public function hasIncludedProperties(): bool { - return !!count($this->includedProperties); + return (bool)$this->includedProperties; } /** - * @return string + * @return class-string */ public function getRevisionClass(): string {