From 2fe42ea705ae641b02ba1ca53ad8bb7949c6dfae Mon Sep 17 00:00:00 2001 From: Wilhelm Behncke Date: Tue, 19 Feb 2019 09:18:11 +0100 Subject: [PATCH 1/4] TASK: Move ConfigurationService Injection to AbstractCommandController --- Classes/Command/AbstractCommandController.php | 6 ++++++ Classes/Command/CloneCommandController.php | 6 ------ 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Classes/Command/AbstractCommandController.php b/Classes/Command/AbstractCommandController.php index 6ef5b3b..a7a7730 100644 --- a/Classes/Command/AbstractCommandController.php +++ b/Classes/Command/AbstractCommandController.php @@ -44,6 +44,12 @@ abstract class AbstractCommandController extends CommandController */ protected $flowCommand; + /** + * @Flow\Inject + * @var ConfigurationService + */ + protected $configurationService; + /** * @param string $commands * @param array $arguments diff --git a/Classes/Command/CloneCommandController.php b/Classes/Command/CloneCommandController.php index f50b713..82c25ff 100644 --- a/Classes/Command/CloneCommandController.php +++ b/Classes/Command/CloneCommandController.php @@ -43,12 +43,6 @@ class CloneCommandController extends AbstractCommandController */ protected $dbal; - /** - * @Flow\Inject - * @var ConfigurationService - */ - protected $configurationService; - /** * Show the list of predefined clone configurations */ From 3caccf2ee8fc8389b7e84167ddf781afb4706eb9 Mon Sep 17 00:00:00 2001 From: Wilhelm Behncke Date: Tue, 19 Feb 2019 09:19:02 +0100 Subject: [PATCH 2/4] TASK: Fix code style and typos --- Classes/Command/StashCommandController.php | 5 +---- Classes/Domain/Service/ConfigurationService.php | 6 +++--- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/Classes/Command/StashCommandController.php b/Classes/Command/StashCommandController.php index 4efa509..5ccad09 100644 --- a/Classes/Command/StashCommandController.php +++ b/Classes/Command/StashCommandController.php @@ -15,9 +15,6 @@ */ class StashCommandController extends AbstractCommandController { - - - /** * Creates a new stash entry with the given name. * @@ -277,7 +274,7 @@ protected function restoreStashEntry($source, $name, $force = false, $preserve = . '`; CREATE DATABASE `' . $this->databaseConfiguration['dbname'] . '` collate utf8_unicode_ci;'; - + $this->executeLocalShellCommand( 'echo %s | mysql --host=%s --user=%s --password=%s', [ diff --git a/Classes/Domain/Service/ConfigurationService.php b/Classes/Domain/Service/ConfigurationService.php index d48c71e..c39fb29 100644 --- a/Classes/Domain/Service/ConfigurationService.php +++ b/Classes/Domain/Service/ConfigurationService.php @@ -24,9 +24,9 @@ class ConfigurationService */ public function getCurrentConfiguration(): array { - $cloneInformations = $this->clonePresetInformationCache->get('current'); - if ($cloneInformations && is_array($this->clonePresets) && array_key_exists($cloneInformations['presetName'], $this->clonePresets)) { - return $this->clonePresets[$cloneInformations['presetName']]; + $cloneInformation = $this->clonePresetInformationCache->get('current'); + if ($cloneInformation && is_array($this->clonePresets) && array_key_exists($cloneInformation['presetName'], $this->clonePresets)) { + return $this->clonePresets[$cloneInformation['presetName']]; } else { return []; } From 7742ec283dd234f0c7d5fb89b6d2c0dcf94a4984 Mon Sep 17 00:00:00 2001 From: Wilhelm Behncke Date: Tue, 19 Feb 2019 11:58:13 +0100 Subject: [PATCH 3/4] TASK: Fix namespaces between Abstract and Clone CommandControllers --- Classes/Command/AbstractCommandController.php | 2 +- Classes/Command/CloneCommandController.php | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/Classes/Command/AbstractCommandController.php b/Classes/Command/AbstractCommandController.php index a7a7730..1069a22 100644 --- a/Classes/Command/AbstractCommandController.php +++ b/Classes/Command/AbstractCommandController.php @@ -9,10 +9,10 @@ use Neos\Flow\Annotations as Flow; use Neos\Flow\Core\Bootstrap; use Neos\Flow\Cli\CommandController; +use Sitegeist\MagicWand\Domain\Service\ConfigurationService; abstract class AbstractCommandController extends CommandController { - const HIDE_RESULT = 1; const HIDE_COMMAND = 2; diff --git a/Classes/Command/CloneCommandController.php b/Classes/Command/CloneCommandController.php index 82c25ff..2ee5052 100644 --- a/Classes/Command/CloneCommandController.php +++ b/Classes/Command/CloneCommandController.php @@ -10,7 +10,6 @@ use Neos\Utility\Arrays; use Neos\Flow\Core\Bootstrap; use Sitegeist\MagicWand\DBAL\SimpleDBAL; -use Sitegeist\MagicWand\Domain\Service\ConfigurationService; use Symfony\Component\Yaml\Yaml; /** From e7be8636c72cc9239370d286a4ad314c2219a63f Mon Sep 17 00:00:00 2001 From: Wilhelm Behncke Date: Tue, 19 Feb 2019 11:59:00 +0100 Subject: [PATCH 4/4] FEATURE: Write manifest files in stash entries and restore preset states --- Classes/Command/StashCommandController.php | 100 ++++++++++++++++-- .../Domain/Service/ConfigurationService.php | 84 +++++++++++++-- 2 files changed, 170 insertions(+), 14 deletions(-) diff --git a/Classes/Command/StashCommandController.php b/Classes/Command/StashCommandController.php index 5ccad09..81f5c63 100644 --- a/Classes/Command/StashCommandController.php +++ b/Classes/Command/StashCommandController.php @@ -29,10 +29,7 @@ public function createCommand($name) # Build Paths # ####################### - $basePath = sprintf( - FLOW_PATH_ROOT . 'Data/MagicWandStash/%s', - $name - ); + $basePath = $this->getStashEntryPath($name); $databaseDestination = $basePath . '/database.sql'; $persistentDestination = $basePath . '/persistent/'; @@ -52,6 +49,24 @@ public function createCommand($name) $this->addSecret($this->databaseConfiguration['user']); $this->addSecret($this->databaseConfiguration['password']); + ###################### + # Write Manifest # + ###################### + $this->renderHeadLine('Write Manifest'); + $presetName = $this->configurationService->getCurrentPreset(); + $presetConfiguration = $this->configurationService->getCurrentConfiguration(); + $cloneTimestamp = $this->configurationService->getMostRecentCloneTimeStamp(); + $stashTimestamp = time(); + + $this->writeStashEntryManifest($name, [ + 'preset' => [ + 'name' => $presetName, + 'configuration' => $presetConfiguration + ], + 'cloned_at' => $cloneTimestamp, + 'stashed_at' => $stashTimestamp + ]); + ###################### # Backup Database # ###################### @@ -99,6 +114,8 @@ public function createCommand($name) */ public function listCommand() { + $head = ['Name', 'Stashed At', 'From Preset', 'Cloned At']; + $rows = []; $basePath = sprintf(FLOW_PATH_ROOT . 'Data/MagicWandStash'); if (!is_dir($basePath)) { @@ -111,7 +128,16 @@ public function listCommand() foreach ($baseDir as $entry) { if (!in_array($entry, ['.', '..'])) { - $this->renderLine(' • %s', [$entry->getFilename()]); + $stashEntryName = $entry->getFilename(); + $manifest = $this->readStashEntryManifest($stashEntryName) ?: []; + + $rows[] = [ + $stashEntryName, + $manifest['stashed_at'] ? date('Y-m-d H:i:s', $manifest['stashed_at']) : 'N/A', + isset($manifest['preset']['name']) ? $manifest['preset']['name'] : 'N/A', + $manifest['cloned_at'] ? date('Y-m-d H:i:s', $manifest['cloned_at']) : 'N/A', + ]; + $anyEntry = true; } } @@ -120,6 +146,8 @@ public function listCommand() $this->renderLine('Stash is empty.'); $this->quit(1); } + + $this->output->outputTable($rows, $head); } /** @@ -155,7 +183,7 @@ public function clearCommand() */ public function restoreCommand($name, $yes = false, $keepDb = false) { - $basePath = sprintf(FLOW_PATH_ROOT . 'Data/MagicWandStash/%s', $name); + $basePath = $this->getStashEntryPath($name); $this->restoreStashEntry($basePath, $name, $yes, true, $keepDb); } @@ -344,6 +372,13 @@ protected function restoreStashEntry($source, $name, $force = false, $preserve = $this->renderHeadLine('Publish Resources'); $this->executeLocalFlowCommand('resource:publish'); + ############################# + # Restore Clone Information # + ############################# + if($manifest = $this->readStashEntryManifest($name)) { + $this->configurationService->setCurrentStashEntry($name, $manifest); + } + ################# # Final Message # ################# @@ -369,4 +404,57 @@ protected function checkConfiguration() $this->renderLine(' - Configuration seems ok ...'); } + + /** + * @param string $stashEntryName + * @return string + */ + protected function getStashEntryPath(string $stashEntryName): string + { + return sprintf( + FLOW_PATH_ROOT . 'Data/MagicWandStash/%s', + $stashEntryName + ); + } + + /** + * @param string $stashEntryName + * @return array|null + */ + protected function readStashEntryManifest(string $stashEntryName): ?array + { + $manifestDestination = $this->getStashEntryPath($stashEntryName) . '/manifest.json'; + + if (file_exists($manifestDestination)) { + if ($manifest = json_decode(file_get_contents($manifestDestination), true)) { + if (is_array($manifest)) { + return $manifest; + } + } + + $this->outputLine('Manifest file has been corrupted.'); + } + + return null; + } + + /** + * @param string $stashEntryName + * @param array $manifest + * @return void + */ + protected function writeStashEntryManifest(string $stashEntryName, array $manifest): void + { + $manifestDestination = $this->getStashEntryPath($stashEntryName) . '/manifest.json'; + + // Create directory, if not exists + if (!file_exists(dirname($manifestDestination))) { + FileUtils::createDirectoryRecursively(dirname($manifestDestination)); + } + + // Write manifest file + file_put_contents($manifestDestination, json_encode($manifest, JSON_PRETTY_PRINT)); + + $this->outputLine('Wrote "%s"', [$manifestDestination]); + } } diff --git a/Classes/Domain/Service/ConfigurationService.php b/Classes/Domain/Service/ConfigurationService.php index c39fb29..b461d46 100644 --- a/Classes/Domain/Service/ConfigurationService.php +++ b/Classes/Domain/Service/ConfigurationService.php @@ -19,17 +19,46 @@ class ConfigurationService */ protected $clonePresets; + /** + * @return string + */ + public function getCurrentPreset(): ?string + { + $clonePresetInformation = $this->clonePresetInformationCache->get('current'); + + if ($clonePresetInformation && is_array($clonePresetInformation) && isset($clonePresetInformation['presetName'])) { + return $clonePresetInformation['presetName']; + } + + return null; + } + + /** + * @return integer + */ + public function getMostRecentCloneTimeStamp(): ?int + { + $clonePresetInformation = $this->clonePresetInformationCache->get('current'); + + if ($clonePresetInformation && is_array($clonePresetInformation) && isset($clonePresetInformation['cloned_at'])) { + return intval($clonePresetInformation['cloned_at']); + } + + return null; + } + /** * @return array */ public function getCurrentConfiguration(): array { - $cloneInformation = $this->clonePresetInformationCache->get('current'); - if ($cloneInformation && is_array($this->clonePresets) && array_key_exists($cloneInformation['presetName'], $this->clonePresets)) { - return $this->clonePresets[$cloneInformation['presetName']]; - } else { - return []; + if ($presetName = $this->getCurrentPreset()) { + if (is_array($this->clonePresets) && array_key_exists($presetName, $this->clonePresets)) { + return $this->clonePresets[$presetName]; + } } + + return []; } /** @@ -44,17 +73,56 @@ public function getCurrentConfigurationByPath($path) /** * @return boolean */ - public function hasConfiguration(): bool + public function hasCurrentPreset(): bool { - return $this->clonePresetInformationCache->has('current'); + if ($this->clonePresetInformationCache->has('current')) { + return true; + } + + $clonePresetInformation = $this->clonePresetInformationCache->get('current'); + + if ($clonePresetInformation && is_array($clonePresetInformation) && isset($clonePresetInformation['presetName'])) { + return true; + } + + return false; } /** * @param $presetName string + * @return void * @throws \Neos\Cache\Exception */ public function setCurrentPreset(string $presetName): void { - $this->clonePresetInformationCache->set('current', ['presetName' => $presetName, 'timestamp' => time()]); + $this->clonePresetInformationCache->set('current', [ + 'presetName' => $presetName, + 'cloned_at' => time() + ]); + } + + /** + * @param string $stashEntryName + * @param array $stashEntryManifest + * @return void + * @throws \Neos\Cache\Exception + */ + public function setCurrentStashEntry(string $stashEntryName, array $stashEntryManifest): void + { + if (!isset($stashEntryManifest['preset']['name'])) { + return; + } + + if (!isset($stashEntryManifest['cloned_at'])) { + return; + } + + $presetName = $stashEntryManifest['preset']['name']; + $clonedAt = $stashEntryManifest['cloned_at']; + + $this->clonePresetInformationCache->set('current', [ + 'presetName' => $presetName, + 'cloned_at' => $clonedAt + ]); } }