diff --git a/Classes/Suffle/Snapshot/Aspects/FusionCachingAspect.php b/Classes/Suffle/Snapshot/Aspects/FusionCachingAspect.php index 6751800..d87f894 100644 --- a/Classes/Suffle/Snapshot/Aspects/FusionCachingAspect.php +++ b/Classes/Suffle/Snapshot/Aspects/FusionCachingAspect.php @@ -1,4 +1,6 @@ getMergedFusionObjectTreeForSitePackage())") - * @param JoinPointInterface $joinPoint The current join point - * @return mixed - */ - public function cacheGetMergedFusionObjectTree(JoinPointInterface $joinPoint) + #[Flow\Around('method(Suffle\Snapshot\Fusion\FusionService->getMergedFusionObjectTreeForSitePackage())')] + public function cacheGetMergedFusionObjectTree(JoinPointInterface $joinPoint): mixed { $siteResourcesPackageKey = $joinPoint->getMethodArgument('siteResourcesPackageKey'); $cacheIdentifier = str_replace('.', '_', $siteResourcesPackageKey); @@ -43,7 +40,11 @@ public function cacheGetMergedFusionObjectTree(JoinPointInterface $joinPoint) $fusionObjectTree = $this->fusionCache->get($cacheIdentifier); } else { $fusionObjectTree = $joinPoint->getAdviceChain()->proceed($joinPoint); - $this->fusionCache->set($cacheIdentifier, $fusionObjectTree); + try { + $this->fusionCache->set($cacheIdentifier, $fusionObjectTree); + } catch (Exception) { + // Cache could not be written + } } return $fusionObjectTree; diff --git a/Classes/Suffle/Snapshot/Command/SnapshotCommandController.php b/Classes/Suffle/Snapshot/Command/SnapshotCommandController.php index 30cc4ea..b015bed 100644 --- a/Classes/Suffle/Snapshot/Command/SnapshotCommandController.php +++ b/Classes/Suffle/Snapshot/Command/SnapshotCommandController.php @@ -1,5 +1,7 @@ testPrototype($prototypeName); $this->outputTestResults($testStats); @@ -87,13 +84,13 @@ public function testCommand(string $prototypeName, bool $interactive = false, bo * Test all Fusion Components * * @param bool $interactive use interactive mode - * @param bool $updateall update all failed snapshots - * @param string $packageKey site-package (defaults to first found) + * @param bool $updateAll update all failed snapshots + * @param string|null $packageKey site-package (defaults to first found) * @throws \Exception */ - public function testAllCommand(bool $interactive = false, bool $updateall = false, $packageKey = null): void + public function testAllCommand(bool $interactive = false, bool $updateAll = false, string $packageKey = null): void { - $testingService = new TestingService($packageKey, $interactive, $updateall); + $testingService = new TestingService($packageKey, $interactive, $updateAll); $testStats = $testingService->testAllPrototypes(); $this->outputTestResults($testStats); @@ -103,7 +100,7 @@ public function testAllCommand(bool $interactive = false, bool $updateall = fals /** * Get all items currently available for testing * - * @param string $packageKey site-package (defaults to first found) + * @param string|null $packageKey site-package (defaults to first found) * @throws \Exception */ public function itemsCommand(string $packageKey = null): void @@ -124,9 +121,6 @@ public function itemsCommand(string $packageKey = null): void /** * Output results returned from snapshot service - * - * @param array $stats - * @throws \Exception */ private function outputSnapshotResults(array $stats): void { @@ -143,7 +137,7 @@ private function outputSnapshotResults(array $stats): void } if (!$stats['success']) { - throw new \Exception('Not all Snapshots could be written'); + throw new \RuntimeException('Not all Snapshots could be written'); } $this->output(PHP_EOL . "All Snapshots saved successfully"); @@ -151,9 +145,6 @@ private function outputSnapshotResults(array $stats): void /** * Output results returned from TestService - * - * @param array $stats - * @throws \Exception */ private function outputTestResults(array $stats): void { @@ -176,12 +167,12 @@ private function outputTestResults(array $stats): void if($stats['failedPrototypes']) { foreach ($stats['failedPrototypes'] as $key => $propSets) { $propsetString = count($propSets) > 1 ? 'propsets' : 'propset'; - $this->output("\t" . $key . " with " . $propsetString . ": " . join(', ', $propSets) . "" . PHP_EOL); + $this->output("\t" . $key . " with " . $propsetString . ": " . implode(', ', $propSets) . "" . PHP_EOL); } } if (!$stats['success']) { - throw new \Exception('Snapshot Testing failed'); + throw new \RuntimeException('Snapshot Testing failed'); } $this->output(PHP_EOL . "Snapshot testing successful"); diff --git a/Classes/Suffle/Snapshot/Controller/ApiController.php b/Classes/Suffle/Snapshot/Controller/ApiController.php index 49935b6..8bbe898 100644 --- a/Classes/Suffle/Snapshot/Controller/ApiController.php +++ b/Classes/Suffle/Snapshot/Controller/ApiController.php @@ -1,4 +1,7 @@ getFirstOnlineSitePackageKey(); @@ -70,16 +56,13 @@ public function snapshotObjectsAction($packageKey = null) /** * Get data for single prototype - * - * @Flow\SkipCsrfProtection - * @param string $prototypeName - * @param string $packageKey - * @return void */ - public function snapshotDataAction($prototypeName, $packageKey = null) + #[Flow\SkipCsrfProtection] + public function snapshotDataAction(string $prototypeName, string $packageKey = null): void { $packageKey = $packageKey ?: $this->getFirstOnlineSitePackageKey(); - $prototypePreviewRenderPath = FusionService::RENDERPATH_DISCRIMINATOR . str_replace(['.', ':'], ['_', '__'], $prototypeName); + $prototypePreviewRenderPath = FusionService::RENDERPATH_DISCRIMINATOR . str_replace(['.', ':'], ['_', '__'], + $prototypeName); $fusionView = new FusionView(); $fusionView->setControllerContext($this->createDummyContext()); @@ -93,10 +76,20 @@ public function snapshotDataAction($prototypeName, $packageKey = null) $builder = new DiffOutputBuilder(); $differ = new Differ($builder); - $renderedPrototypes = $fusionView->renderSnapshotPrototype($prototypeName); + try { + $renderedPrototypes = $fusionView->renderSnapshotPrototype($prototypeName); + } catch (\Throwable $e) { + $this->logger->error($e->getMessage()); + $renderedPrototypes = []; + } foreach ($renderedPrototypes as $propSetName => $renderedPrototype) { - $savedSnapshot = $snapshotService->getSnapshotOfPropSet($prototypeName, $propSetName, $packageKey); + try { + $savedSnapshot = $snapshotService->getSnapshotOfPropSet($prototypeName, $propSetName, $packageKey); + } catch (FilesException $e) { + $this->logger->error($e->getMessage()); + $savedSnapshot = null; + } if ($savedSnapshot) { $diff = $differ->diff($savedSnapshot, $renderedPrototype); @@ -105,8 +98,8 @@ public function snapshotDataAction($prototypeName, $packageKey = null) $result[$propSetName] = [ 'snapshot' => $savedSnapshot, 'current' => $renderedPrototype, - 'hasSnapshot' => $savedSnapshot ? true : false, - 'testSuccess' => $diff ? false : true + 'hasSnapshot' => (bool)$savedSnapshot, + 'testSuccess' => $savedSnapshot && !$diff, ]; } @@ -115,39 +108,33 @@ public function snapshotDataAction($prototypeName, $packageKey = null) /** * Get preview markup - * - * @Flow\SkipCsrfProtection - * @param string $packageKey - * @return void */ - public function previewMarkupAction($packageKey = null) + #[Flow\SkipCsrfProtection] + public function previewMarkupAction(string $packageKey = null): void { $packageKey = $packageKey ?: $this->getFirstOnlineSitePackageKey(); $previewPrototypeName = $this->settings['previewPrototypeName']; - $prototypePreviewRenderPath = str_replace(['.', ':'], ['_', '__'], $previewPrototypeName); $fusionView = new FusionView(); - - $fusionRootPath = sprintf('/<%s>', $prototypePreviewRenderPath); $fusionView->setControllerContext($this->controllerContext); $fusionView->setPackageKey($packageKey); // get the status and headers from the view - $result = [ - 'previewMarkup' => $fusionView->renderPrototype($previewPrototypeName) - ]; - - + try { + $result = [ + 'previewMarkup' => $fusionView->renderPrototype($previewPrototypeName) + ]; + } catch (\Throwable $e) { + $result = 'Error: ' . $e->getMessage(); + } $this->view->assign('value', $result); } /** * Get all site packages - * - * @Flow\SkipCsrfProtection - * @return void */ - public function sitePackagesAction() + #[Flow\SkipCsrfProtection] + public function sitePackagesAction(): void { $sitePackages = $this->getSitePackages(); $result = []; diff --git a/Classes/Suffle/Snapshot/Controller/OverviewController.php b/Classes/Suffle/Snapshot/Controller/OverviewController.php index 9e20396..15f8c78 100644 --- a/Classes/Suffle/Snapshot/Controller/OverviewController.php +++ b/Classes/Suffle/Snapshot/Controller/OverviewController.php @@ -1,4 +1,7 @@ sitePackage) { $this->sitePackage = $this->getFirstOnlineSitePackage(); @@ -40,10 +33,8 @@ public function initializeView(ViewInterface $view) $this->view->assign('currentSitePackageKey', $this->sitePackage['packageKey']); } - /** - * @return void - */ - public function indexAction() + + public function indexAction(): void { } } diff --git a/Classes/Suffle/Snapshot/Controller/SnapshotController.php b/Classes/Suffle/Snapshot/Controller/SnapshotController.php index 8e98b3c..e3fca93 100644 --- a/Classes/Suffle/Snapshot/Controller/SnapshotController.php +++ b/Classes/Suffle/Snapshot/Controller/SnapshotController.php @@ -1,4 +1,6 @@ arguments->hasArgument('node')) { - $this->arguments->getArgument('node')->getPropertyMappingConfiguration()->setTypeConverterOption('Neos\ContentRepository\TypeConverter\NodeConverter', - \Neos\Neos\TypeConverter\NodeConverter::REMOVED_CONTENT_SHOWN, true); + $this->arguments->getArgument('node')->getPropertyMappingConfiguration()->setTypeConverterOption( + NodeConverter::class, + NodeConverter::REMOVED_CONTENT_SHOWN, true + ); } @@ -49,10 +45,7 @@ protected function initializeAction() parent::initializeAction(); } - /** - * @return void - */ - public function indexAction() + public function indexAction(): void { } diff --git a/Classes/Suffle/Snapshot/Diff/DiffOutputBuilder.php b/Classes/Suffle/Snapshot/Diff/DiffOutputBuilder.php index 7ecf6a3..62b11e2 100644 --- a/Classes/Suffle/Snapshot/Diff/DiffOutputBuilder.php +++ b/Classes/Suffle/Snapshot/Diff/DiffOutputBuilder.php @@ -1,5 +1,7 @@ = 0 - */ - private $commonLineThreshold = 6; - - /** - * @var int >= 0 - */ - private $contextLines = 3; - - /** - * @var string - */ - private $header; + private int $commonLineThreshold = 6; + private int $contextLines = 3; + private string $header; public function __construct() { @@ -41,9 +31,6 @@ public function __construct() /** * get diff of two values - * - * @param array $diff - * @return string */ public function getDiff(array $diff): string { @@ -53,16 +40,15 @@ public function getDiff(array $diff): string $this->writeDiffHunks($buffer, $diff); } - $diff = \stream_get_contents($buffer, -1, 0); + $output = \stream_get_contents($buffer, -1, 0); \fclose($buffer); - if ($diff) { - $diff = $this->header . $diff; + if ($output) { + $output = $this->header . $output; } - - return $diff; + return $output; } /** @@ -83,7 +69,8 @@ private function writeDiffHunks($output, array $diff): void $lc = \substr($diff[$i][0], -1); if (PHP_EOL !== $lc) { - \array_splice($diff, $i + 1, 0, [[PHP_EOL . "\\ No newline at end of file" . PHP_EOL, Differ::NO_LINE_END_EOF_WARNING]]); + \array_splice($diff, $i + 1, 0, + [[PHP_EOL . "\\ No newline at end of file" . PHP_EOL, Differ::NO_LINE_END_EOF_WARNING]]); } if (!\count($toFind)) { @@ -95,22 +82,18 @@ private function writeDiffHunks($output, array $diff): void $cutOff = \max($this->commonLineThreshold, $this->contextLines); $hunkCapture = false; - $sameCount = $toRange = $fromRange = 0; - $toStart = $fromStart = 1; + $sameCount = $fromRange = 0; + $fromStart = 1; foreach ($diff as $i => $entry) { - // Write part of diff if commonLineThreshold is reached (collapse common lines) if (0 === $entry[1]) { if (false === $hunkCapture) { ++$fromStart; - ++$toStart; - continue; } ++$sameCount; - ++$toRange; ++$fromRange; if ($sameCount === $cutOff) { @@ -126,10 +109,8 @@ private function writeDiffHunks($output, array $diff): void ); $fromStart += $fromRange; - $toStart += $toRange; - $hunkCapture = false; - $sameCount = $toRange = $fromRange = 0; + $sameCount = $fromRange = 0; } continue; @@ -145,10 +126,6 @@ private function writeDiffHunks($output, array $diff): void $hunkCapture = $i; } - if (Differ::ADDED === $entry[1]) { - ++$toRange; - } - if (Differ::REMOVED === $entry[1]) { ++$fromRange; } @@ -192,9 +169,7 @@ private function writeHunk( int $diffEndIndex, int $fromStart, $output - ): void - { - + ): void { \fwrite($output, "@@ Line: " . $fromStart . " @@" . PHP_EOL); for ($i = $diffStartIndex; $i < $diffEndIndex; ++$i) { @@ -212,4 +187,4 @@ private function writeHunk( } } -} \ No newline at end of file +} diff --git a/Classes/Suffle/Snapshot/Fusion/FusionService.php b/Classes/Suffle/Snapshot/Fusion/FusionService.php index 04d380b..2478997 100644 --- a/Classes/Suffle/Snapshot/Fusion/FusionService.php +++ b/Classes/Suffle/Snapshot/Fusion/FusionService.php @@ -1,5 +1,7 @@ settings['annotationKey'] ?: 'snapshot'; @@ -81,10 +67,6 @@ protected function addSnapshotPrototypesToFusionAst(array $fusionAst): array '__value' => null, '__eelExpression' => null ]; - if (array_key_exists('props', $prototypeConfiguration['__meta'][$annotationKey]) - && is_array($prototypeConfiguration['__meta'][$annotationKey]['props'])) { - $snapshotRenderingProps[$prototypeName] = $prototypeConfiguration['__meta'][$annotationKey]['props']; - } $snapshotRenderingPrototypes[$prototypeName] = $renderPrototypeFusion; } @@ -99,9 +81,6 @@ protected function addSnapshotPrototypesToFusionAst(array $fusionAst): array /** * Get all snapshot objects for the given fusion-ast - * - * @param array $fusionAst - * @return array */ public function getSnapshotObjectsFromFusionAst(array $fusionAst): array { @@ -113,13 +92,14 @@ public function getSnapshotObjectsFromFusionAst(array $fusionAst): array if (array_key_exists('__meta', $prototypeObject) && is_array($prototypeObject['__meta']) && array_key_exists($annotationKey, $prototypeObject['__meta'])) { - list($prototypeVendor, $prototypeName) = explode(':', $prototypeFullName, 2); + [, $prototypeName] = explode(':', $prototypeFullName, 2); $snapshotConfiguration = $prototypeObject['__meta'][$annotationKey]; $snapshotObjects[$prototypeFullName] = [ - 'title' => (isset($snapshotConfiguration['title'])) ? $snapshotConfiguration['title'] : implode(' ', array_reverse(explode('.', $prototypeName))), - 'path' => (isset($snapshotConfiguration['path'])) ? $snapshotConfiguration['path'] : $prototypeName, - 'description' => (isset($snapshotConfiguration['description'])) ? $snapshotConfiguration['description'] : '', - 'options' => (isset($snapshotConfiguration['options'])) ? $snapshotConfiguration['options'] : null, + 'title' => $snapshotConfiguration['title'] ?? implode(' ', + array_reverse(explode('.', $prototypeName))), + 'path' => $snapshotConfiguration['path'] ?? $prototypeName, + 'description' => $snapshotConfiguration['description'] ?? '', + 'options' => $snapshotConfiguration['options'] ?? null, ]; } } @@ -130,10 +110,7 @@ public function getSnapshotObjectsFromFusionAst(array $fusionAst): array /** * Returns a list of testable prototypes * - * @param string $siteResourcesPackageKey * @return array Array of prototype names to test - * @throws \Neos\Fusion\Exception - * @throws \Neos\Neos\Domain\Exception */ public function getPrototypeNamesForTesting(string $siteResourcesPackageKey): array { @@ -143,26 +120,22 @@ public function getPrototypeNamesForTesting(string $siteResourcesPackageKey): ar /** * Add snapshot rendering configuration to the fusion-ast - * - * @param array $fusionAst - * @return array */ protected function filterSnapshotPrototypes(array $fusionAst): array { - $snapshotPrototypeConfigurations = []; $prototypesList = []; $annotationKey = $this->settings['annotationKey'] ?: 'snapshot'; + $excludedPackageKeys = $this->settings['exclude']['packageKeys'] ?? []; foreach ($fusionAst['__prototypes'] as $prototypeName => $prototypeConfiguration) { + $prototypePackageKey = explode(':', $prototypeName)[0]; if (array_key_exists('__meta', $prototypeConfiguration) && array_key_exists($annotationKey, $prototypeConfiguration['__meta']) + && !in_array($prototypePackageKey, $excludedPackageKeys, true) ) { - $snapshotPrototypeConfigurations[$prototypeName] = $prototypeConfiguration; - array_push($prototypesList, $prototypeName); + $prototypesList[] = $prototypeName; } } - - return $prototypesList; } } diff --git a/Classes/Suffle/Snapshot/Fusion/FusionView.php b/Classes/Suffle/Snapshot/Fusion/FusionView.php index 2511591..53eec18 100644 --- a/Classes/Suffle/Snapshot/Fusion/FusionView.php +++ b/Classes/Suffle/Snapshot/Fusion/FusionView.php @@ -1,5 +1,7 @@ getOption('fusionPathPatterns') - * - * @return void * @throws \Neos\Flow\Mvc\Exception - * @throws \Neos\Fusion\Exception - * @throws \Neos\Neos\Domain\Exception */ - protected function loadFusion(): void { - $fusionAst = $this->fusionService->getMergedFusionObjectTreeForSitePackage($this->getOption('packageKey')); + $fusionAst = $this->fusionService->getMergedFusionObjectTreeForSitePackage( + $this->getOption('packageKey') + ); $this->parsedFusion = $fusionAst; } - /** - * @var array - */ - protected $overriddenPropsPerPrototype = []; - /** * Special method to render a specific prototype and all of its propSets - * - * @param string $prototypeName - * @param array $locales - * @return array - * @throws \Exception - * @throws \Neos\Flow\I18n\Exception\InvalidLocaleIdentifierException - * @throws \Neos\Flow\Mvc\Exception - * @throws \Neos\Flow\Security\Exception - * @throws \Neos\Fusion\Exception - * @throws \Neos\Neos\Domain\Exception + * @throws \Throwable */ public function renderSnapshotPrototype(string $prototypeName, array $locales = []): array { if ($locales) { - $currentLocale = new Locale($locales[0]); - $this->i18nService->getConfiguration()->setCurrentLocale($currentLocale); - $this->i18nService->getConfiguration()->setFallbackRule(array('strict' => false, 'order' => array_reverse($locales))); + try { + $currentLocale = new Locale($locales[0]); + $this->i18nService->getConfiguration()->setCurrentLocale($currentLocale); + $this->i18nService->getConfiguration()->setFallbackRule([ + 'strict' => false, + 'order' => array_reverse($locales) + ]); + } catch (InvalidLocaleIdentifierException) { + } } $fusionAst = $this->fusionService->getMergedFusionObjectTreeForSitePackage($this->getOption('packageKey')); @@ -107,7 +89,12 @@ public function renderSnapshotPrototype(string $prototypeName, array $locales = return $output; } - public function renderPrototype($prototypeName) + /** + * @throws \Throwable + * @throws Exception + * @throws \Neos\Flow\Mvc\Exception + */ + public function renderPrototype(string $prototypeName): mixed { $fusionAst = $this->fusionService->getMergedFusionObjectTreeForSitePackage($this->getOption('packageKey')); $fusionPath = sprintf('/<%s>', $prototypeName); @@ -124,12 +111,8 @@ public function renderPrototype($prototypeName) /** * Override props via parameters, props and propSet configuration * - * @param array $fusionAst - * @param string $prototypeName - * @return array * @throws \Exception */ - protected function postProcessFusionAstForPrototype(array $fusionAst, string $prototypeName): array { if (!$prototypeName || $prototypeName === 'undefined') { @@ -150,7 +133,6 @@ protected function postProcessFusionAstForPrototype(array $fusionAst, string $pr $prototypeBaseConfiguration, $snapshotConfiguration['props'] ); - } else { $prototypeDefaultConfiguration = $prototypeBaseConfiguration; } @@ -158,9 +140,7 @@ protected function postProcessFusionAstForPrototype(array $fusionAst, string $pr $prototypeConfigurations['default'] = $prototypeDefaultConfiguration; // Add configurations for propSets - if ( - array_key_exists('propSets', $snapshotConfiguration) - ) { + if (array_key_exists('propSets', $snapshotConfiguration)) { foreach ($snapshotConfiguration['propSets'] as $propSetName => $propSet) { $propSetPrototypeConfiguration = array_replace_recursive( $prototypeDefaultConfiguration, @@ -172,22 +152,21 @@ protected function postProcessFusionAstForPrototype(array $fusionAst, string $pr } foreach ($prototypeConfigurations as $propSet => $fusionConfiguration) { - $fusionAstArray[$propSet] = $this->postProcessSingleConfiguration($fusionAst, $fusionConfiguration, $prototypeName); + $fusionAstArray[$propSet] = $this->postProcessSingleConfiguration($fusionAst, $fusionConfiguration, + $prototypeName); } return $fusionAstArray; } /** - * get fusionAst for single configuration - * - * @param array $fusionAst - * @param $fusionConfiguration - * @param string $prototypeName - * @return array + * Get fusionAst for single configuration */ - protected function postProcessSingleConfiguration(array $fusionAst, $fusionConfiguration, string $prototypeName): array - { + protected function postProcessSingleConfiguration( + array $fusionAst, + array $fusionConfiguration, + string $prototypeName + ): array { $prototypeConfiguration = $fusionConfiguration; $fusionAst['__prototypes'][$prototypeName] = $prototypeConfiguration; $annotationKey = $this->settings['annotationKey'] ?: 'snapshot'; @@ -214,24 +193,19 @@ protected function postProcessSingleConfiguration(array $fusionAst, $fusionConfi /** * Make sure, that this prototype is actually configured for being rendered as a snapshot - * - * @param array $fusionAst - * @param string $prototypeName - * @return void - * @throws \Exception */ protected function assertWellFormedSnapshotObject(array $fusionAst, string $prototypeName): void { $annotationKey = $this->settings['annotationKey'] ?: 'snapshot'; if (!array_key_exists($prototypeName, $fusionAst['__prototypes'])) { - throw new \Exception(sprintf('Prototype "%s" does not exist.', $prototypeName), 1500825696); + throw new \RuntimeException(sprintf('Prototype "%s" does not exist.', $prototypeName), 1500825696); } if (!array_key_exists('__meta', $fusionAst['__prototypes'][$prototypeName]) || !array_key_exists($annotationKey, $fusionAst['__prototypes'][$prototypeName]['__meta']) ) { - throw new \Exception( + throw new \RuntimeException( sprintf( 'Prototype "%s" has no snapshot configuration. ' . 'Remember to add one one under "@snapshot" in your fusion code.', diff --git a/Classes/Suffle/Snapshot/Package.php b/Classes/Suffle/Snapshot/Package.php index 5d7583d..0b82b3b 100644 --- a/Classes/Suffle/Snapshot/Package.php +++ b/Classes/Suffle/Snapshot/Package.php @@ -1,4 +1,6 @@ getSignalSlotDispatcher(); $context = $bootstrap->getContext(); if (!$context->isProduction()) { - $dispatcher->connect(Sequence::class, 'afterInvokeStep', function ($step) use ($bootstrap, $dispatcher) { + $dispatcher->connect(Sequence::class, 'afterInvokeStep', function ($step) use ($bootstrap) { if ($step->getIdentifier() === 'neos.flow:systemfilemonitor') { - $templateFileMonitor = FileMonitor::createFileMonitorAtBoot('Suffle_Snapshot_Fusion_Files', $bootstrap); + $templateFileMonitor = FileMonitor::createFileMonitorAtBoot('Suffle_Snapshot_Fusion_Files', + $bootstrap); /** * @var PackageManager $packageManager */ $packageManager = $bootstrap->getEarlyInstance(PackageManager::class); - foreach ($packageManager->getAvailablePackages() as $packageKey => $package) { + foreach ($packageManager->getAvailablePackages() as $package) { if (method_exists($package, 'getResourcesPath')) { $templatesPath = $package->getResourcesPath() . 'Private/Fusion'; if (is_dir($templatesPath)) { diff --git a/Classes/Suffle/Snapshot/Resource/Target/OverridableFileSystemTarget.php b/Classes/Suffle/Snapshot/Resource/Target/OverridableFileSystemTarget.php index 41cba79..cae61df 100644 --- a/Classes/Suffle/Snapshot/Resource/Target/OverridableFileSystemTarget.php +++ b/Classes/Suffle/Snapshot/Resource/Target/OverridableFileSystemTarget.php @@ -1,19 +1,15 @@ customBaseUri === null) { return parent::getResourcesBaseUri(); @@ -22,12 +18,9 @@ protected function getResourcesBaseUri() return $this->customBaseUri . $this->baseUri; } - /** - * @param string $baseUri - */ - public function setCustomBaseUri(string $baseUri) + public function setCustomBaseUri(string $baseUri): void { $this->customBaseUri = $baseUri; } -} \ No newline at end of file +} diff --git a/Classes/Suffle/Snapshot/Service/FileStorage.php b/Classes/Suffle/Snapshot/Service/FileStorage.php index 6d966cf..6af0abd 100644 --- a/Classes/Suffle/Snapshot/Service/FileStorage.php +++ b/Classes/Suffle/Snapshot/Service/FileStorage.php @@ -1,5 +1,7 @@ createSnapshotFile($html, $prototypeName, $propSetName, $sitePackageName); } /** * Get saved snapshot of given prototype and its propSetName. - * - * @param string $prototypeName - * @param string $propSetName - * @param string $sitePackageName - * @return string * @throws FilesException */ public function getSnapshotByPropSet(string $prototypeName, string $propSetName, string $sitePackageName): string @@ -65,16 +60,14 @@ public function getSnapshotByPropSet(string $prototypeName, string $propSetName, } /** - * @param string $html - * @param string $prototypeName - * @param string $propSetName - * @param string $sitePackageName - * @return bool * @throws FilesException */ - - private function createSnapshotFile(string $html, string $prototypeName, string $propSetName, string $sitePackageName): bool - { + private function createSnapshotFile( + string $html, + string $prototypeName, + string $propSetName, + string $sitePackageName + ): bool { $filePath = $this->getSavePathForSnapshot([$sitePackageName, $prototypeName, $propSetName]); file_put_contents($filePath, $html); if (!file_exists($filePath)) { @@ -92,8 +85,11 @@ private function createSnapshotFile(string $html, string $prototypeName, string * @return string * @throws FilesException */ - private function loadSnapshotByPropSetName(string $prototypeName, string $propSetName, string $sitePackageName): string - { + private function loadSnapshotByPropSetName( + string $prototypeName, + string $propSetName, + string $sitePackageName + ): string { $filePath = $this->getSavePathForSnapshot([$sitePackageName, $prototypeName, $propSetName]); if (file_exists($filePath)) { @@ -105,20 +101,16 @@ private function loadSnapshotByPropSetName(string $prototypeName, string $propSe /** * Generate file name and folder - * - * @param array $fileNameComponents - * @return string * @throws FilesException */ private function getSavePathForSnapshot(array $fileNameComponents): string { - $fileName = array_reduce($fileNameComponents, function ($acc, $item) { + $fileName = array_reduce($fileNameComponents, static function ($acc, $item) { if ($acc) { $acc .= "_"; } $acc .= str_replace(['.', ':', ' ', '-'], '_', $item); - return $acc; }); @@ -129,27 +121,25 @@ private function getSavePathForSnapshot(array $fileNameComponents): string if (strlen($fileName) > self::MAX_FILENAME_LENGTH) { $shortenedFilename = $this->truncateString($fileName, self::MAX_FILENAME_LENGTH - strlen($directoryPath)); - $savePath = Files::concatenatePaths([$this->settings['snapshotSavePath'], $directoryPath, $shortenedFilename . '.snap']); + $savePath = Files::concatenatePaths([ + $this->settings['snapshotSavePath'], + $directoryPath, + $shortenedFilename . '.snap' + ]); } Files::createDirectoryRecursively(dirname($savePath)); - return $savePath; } /** * Truncate an identifier if needed and append a hash to ensure uniqueness. - * - * @param string $string - * @param integer $lengthLimit - * @return string */ private function truncateString(string $string, int $lengthLimit): string { if (strlen($string) > $lengthLimit) { $string = substr($string, 0, $lengthLimit - 6) . '_' . substr(sha1($string), 0, 5); } - return $string; } } diff --git a/Classes/Suffle/Snapshot/Service/SnapshotService.php b/Classes/Suffle/Snapshot/Service/SnapshotService.php index 00f1a2f..0da4c74 100644 --- a/Classes/Suffle/Snapshot/Service/SnapshotService.php +++ b/Classes/Suffle/Snapshot/Service/SnapshotService.php @@ -1,4 +1,6 @@ = 0 - */ - private $totalSnapshots = 0; - - /** - * @var int >= 0 - */ - private $failedSnapshots = 0; + #[Flow\Inject] + protected FusionService $fusionService; - /** - * @var bool - */ - private $snapshotsSuccessful = true; + #[Flow\Inject] + protected FileStorage $fileStorage; - /** - * @var array - */ - private $sitePackages; + protected int $totalSnapshots = 0; + protected int $failedSnapshots = 0; + protected bool $snapshotsSuccessful = true; + protected ?array $sitePackages = null; /** * Constructs the command controller - * @param string $packageKey */ public function __construct(string $packageKey = null) { $this->sitePackages = $packageKey ? $this->getSitePackageByKey($packageKey) : null; } - /** - * @return array - * @throws \Exception - * @throws \Neos\Flow\I18n\Exception\InvalidLocaleIdentifierException - * @throws \Neos\Flow\Mvc\Exception - * @throws \Neos\Flow\Security\Exception - * @throws \Neos\Fusion\Exception - * @throws \Neos\Neos\Domain\Exception - * @throws \Neos\Utility\Exception\FilesException - */ public function takeSnapshotOfAllPrototypes(): array { $this->reset(); $this->sitePackages = $this->sitePackages ?: $this->getSitePackages(); - foreach($this->sitePackages as $sitePackage) { + foreach ($this->sitePackages as $sitePackage) { $sitePackageKey = $sitePackage['packageKey']; $this->injectBaseUriIntoFileSystemTargets($sitePackage['baseUri']); $this->outputInfoText($sitePackageKey); $this->outputNewLine(); $prototypesToSnapshot = $this->fusionService->getPrototypeNamesForTesting($sitePackageKey); - foreach($prototypesToSnapshot as $prototypeName) { + foreach ($prototypesToSnapshot as $prototypeName) { $this->takeSinglePrototype($prototypeName, $sitePackageKey); } } @@ -100,23 +69,12 @@ public function takeSnapshotOfAllPrototypes(): array return $this->getStats(); } - /** - * @param $prototypeName - * @return array - * @throws \Exception - * @throws \Neos\Flow\I18n\Exception\InvalidLocaleIdentifierException - * @throws \Neos\Flow\Mvc\Exception - * @throws \Neos\Flow\Security\Exception - * @throws \Neos\Fusion\Exception - * @throws \Neos\Neos\Domain\Exception - * @throws \Neos\Utility\Exception\FilesException - */ - public function takeSnapshotOfPrototype($prototypeName): array + public function takeSnapshotOfPrototype(string $prototypeName): array { $this->reset(); $this->sitePackages = $this->sitePackages ?: $this->getSitePackages(); - foreach($this->sitePackages as $sitePackage) { + foreach ($this->sitePackages as $sitePackage) { $sitePackageKey = $sitePackage['packageKey']; $this->injectBaseUriIntoFileSystemTargets($sitePackage['baseUri']); $this->outputInfoText($sitePackageKey); @@ -127,16 +85,12 @@ public function takeSnapshotOfPrototype($prototypeName): array return $this->getStats(); } - /** - * @param string $html - * @param string $prototypeName - * @param string $propSetName - * @param string $sitePackageName - * @return array - * @throws \Neos\Utility\Exception\FilesException - */ - public function takeSnapshotOfPropSet($html, string $prototypeName, string $propSetName, string $sitePackageName): array - { + public function takeSnapshotOfPropSet( + string $html, + string $prototypeName, + string $propSetName, + string $sitePackageName + ): array { $this->reset(); $this->takeSinglePropSet($html, $prototypeName, $propSetName, $sitePackageName); @@ -144,57 +98,46 @@ public function takeSnapshotOfPropSet($html, string $prototypeName, string $prop } /** - * @param string $prototypeName - * @param string $propSetName - * @param string $sitePackageKey - * @return string - * @throws \Neos\Utility\Exception\FilesException + * @throws FilesException */ public function getSnapshotOfPropSet(string $prototypeName, string $propSetName, string $sitePackageKey): string { return $this->fileStorage->getSnapshotByPropSet($prototypeName, $propSetName, $sitePackageKey); } - /** - * @param string $html - * @param string $prototypeName - * @param string $propSetName - * @param string $sitePackageKey - * @return bool - * @throws \Neos\Utility\Exception\FilesException - */ - private function takeSinglePropSet($html, string $prototypeName, string $propSetName, string $sitePackageKey): bool - { + private function takeSinglePropSet( + string $html, + string $prototypeName, + string $propSetName, + string $sitePackageKey + ): bool { if (!$html) { - $this->outputInfoText("Snapshot for PropSet " . $propSetName . " did not return any Markup. Skipped." . PHP_EOL, 2); + $this->outputInfoText("Snapshot for PropSet " . $propSetName . " did not return any Markup. Skipped." . PHP_EOL, + 2); return true; } - if ($this->fileStorage->saveSnapshotByPropSet($html, $prototypeName, $propSetName, $sitePackageKey)) { - $this->outputSuccess("Snapshot written for PropSet " . $propSetName . PHP_EOL, [], 2); - return true; - } else { - $this->outputFailed("Snapshot could not be written for PropSet " . $propSetName . PHP_EOL, [], 2); + try { + if ($this->fileStorage->saveSnapshotByPropSet($html, $prototypeName, $propSetName, $sitePackageKey)) { + $this->outputSuccess("Snapshot written for PropSet " . $propSetName . PHP_EOL, [], 2); + return true; + } + } catch (FilesException $e) { + $this->outputFailed("Snapshot could not be written for PropSet " . $propSetName . ': ' . $e->getMessage() . PHP_EOL, + [], 2); return false; } + $this->outputFailed("Snapshot could not be written for PropSet " . $propSetName . PHP_EOL, [], 2); + return false; } /** * Take snapshot of prototype including all propSets - * - * @param string $prototypeName - * @param string $sitePackageKey - * @throws \Exception - * @throws \Neos\Flow\I18n\Exception\InvalidLocaleIdentifierException - * @throws \Neos\Flow\Mvc\Exception - * @throws \Neos\Flow\Security\Exception - * @throws \Neos\Fusion\Exception - * @throws \Neos\Neos\Domain\Exception - * @throws \Neos\Utility\Exception\FilesException */ private function takeSinglePrototype(string $prototypeName, string $sitePackageKey): void { - $prototypePreviewRenderPath = FusionService::RENDERPATH_DISCRIMINATOR . str_replace(['.', ':'], ['_', '__'], $prototypeName); + $prototypePreviewRenderPath = FusionService::RENDERPATH_DISCRIMINATOR . str_replace(['.', ':'], ['_', '__'], + $prototypeName); $fusionView = new FusionView(); @@ -202,14 +145,19 @@ private function takeSinglePrototype(string $prototypeName, string $sitePackageK $fusionView->setFusionPath($prototypePreviewRenderPath); $fusionView->setPackageKey($sitePackageKey); - $renderedPrototypes = $fusionView->renderSnapshotPrototype($prototypeName); + try { + $renderedPrototypes = $fusionView->renderSnapshotPrototype($prototypeName); + } catch (\Throwable $e) { + $this->outputFailed("Could not render Prototype " . $prototypeName . ': ' . $e->getMessage() . PHP_EOL); + return; + } $this->outputInfoText($prototypeName, 1); foreach ($renderedPrototypes as $propSetName => $html) { - $this->totalSnapshots += 1; + ++$this->totalSnapshots; if (!$this->takeSinglePropSet($html, $prototypeName, $propSetName, $sitePackageKey)) { - $this->failedSnapshots +=1; + ++$this->failedSnapshots; $this->snapshotsSuccessful = false; } } diff --git a/Classes/Suffle/Snapshot/Service/TestingService.php b/Classes/Suffle/Snapshot/Service/TestingService.php index 3460dec..c6e70fe 100644 --- a/Classes/Suffle/Snapshot/Service/TestingService.php +++ b/Classes/Suffle/Snapshot/Service/TestingService.php @@ -1,5 +1,7 @@ "update this snapshot", "n" => "do not update this snapshot", "q" => "do not update and quit immediately", "a" => "update this and all following failed snapshots", "d" => "do not update this or any following snapshots" - ); - - /** - * @Flow\Inject - * @var FusionService - */ - protected $fusionService; - - /** - * @var int >= 0 - */ - private $totalTests = 0; - - /** - * @var int >= 0 - */ - private $failedTests = 0; - - /** - * @var array - */ - private $failedPrototypes; - - /** - * @var int >= 0 - */ - private $newSnapshots = 0; - - /** - * @var bool - */ - private $testSuccess = true; - - /** - * @var bool - */ - private $interactiveMode = false; - - /** - * @var bool - */ - private $updateAllSnapshots = false; - - /** - * @var bool - */ - private $skipAllSnapshots = false; - - /** - * @var array - */ - private $sitePackages; - - /** - * @var array - */ - private $detailedTestResults; + ]; + + #[Flow\Inject] + protected FusionService $fusionService; + + private int $totalTests = 0; + private int $failedTests = 0; + private array $failedPrototypes = []; + private int $newSnapshots = 0; + private bool $testSuccess = true; + private bool $interactiveMode; + private bool $updateAllSnapshots; + private bool $skipAllSnapshots = false; + private ?array $sitePackages; + private array $detailedTestResults = []; /** * Constructs the command controller - * @param string $packageKey - * @param bool $interactive - * @param $updateAll */ public function __construct(string $packageKey = null, bool $interactive = false, bool $updateAll = false) { @@ -109,16 +65,6 @@ public function __construct(string $packageKey = null, bool $interactive = false $this->updateAllSnapshots = $updateAll; } - /** - * @return array - * @throws \Exception - * @throws \Neos\Flow\I18n\Exception\InvalidLocaleIdentifierException - * @throws \Neos\Flow\Mvc\Exception - * @throws \Neos\Flow\Security\Exception - * @throws \Neos\Fusion\Exception - * @throws \Neos\Neos\Domain\Exception - * @throws \Neos\Utility\Exception\FilesException - */ public function testAllPrototypes(): array { $this->reset(); @@ -139,17 +85,6 @@ public function testAllPrototypes(): array return $this->getStats(); } - /** - * @param string $prototypeName - * @return array - * @throws \Exception - * @throws \Neos\Flow\I18n\Exception\InvalidLocaleIdentifierException - * @throws \Neos\Flow\Mvc\Exception - * @throws \Neos\Flow\Security\Exception - * @throws \Neos\Fusion\Exception - * @throws \Neos\Neos\Domain\Exception - * @throws \Neos\Utility\Exception\FilesException - */ public function testPrototype(string $prototypeName): array { $this->reset(); @@ -167,17 +102,6 @@ public function testPrototype(string $prototypeName): array return $this->getStats(); } - /** - * @param string $prototypeName - * @param string $sitePackageKey - * @throws \Exception - * @throws \Neos\Flow\I18n\Exception\InvalidLocaleIdentifierException - * @throws \Neos\Flow\Mvc\Exception - * @throws \Neos\Flow\Security\Exception - * @throws \Neos\Fusion\Exception - * @throws \Neos\Neos\Domain\Exception - * @throws \Neos\Utility\Exception\FilesException - */ private function testSinglePrototype(string $prototypeName, string $sitePackageKey): void { $prototypePreviewRenderPath = FusionService::RENDERPATH_DISCRIMINATOR . str_replace(['.', ':'], ['_', '__'], $prototypeName); @@ -187,7 +111,12 @@ private function testSinglePrototype(string $prototypeName, string $sitePackageK $fusionView->setFusionPath($prototypePreviewRenderPath); $fusionView->setPackageKey($sitePackageKey); - $renderedPrototypes = $fusionView->renderSnapshotPrototype($prototypeName); + try { + $renderedPrototypes = $fusionView->renderSnapshotPrototype($prototypeName); + } catch (\Throwable $e) { + $this->outputFailed("Error rendering prototype %s: %s", [$prototypeName, $e->getMessage()], 1); + return; + } $builder = new DiffOutputBuilder(); $differ = new Differ($builder); @@ -197,12 +126,17 @@ private function testSinglePrototype(string $prototypeName, string $sitePackageK $this->outputInfoText($prototypeName, 1); foreach ($renderedPrototypes as $propSetName => $renderedPrototype) { - $savedSnapshot = $snapshotService->getSnapshotOfPropSet($prototypeName, $propSetName, $sitePackageKey); + try { + $savedSnapshot = $snapshotService->getSnapshotOfPropSet($prototypeName, $propSetName, $sitePackageKey); + } catch (FilesException $e) { + $this->outputFailed("Error reading snapshot for propSet %s: %s", [$propSetName, $e->getMessage()], 2); + continue; + } if (!$savedSnapshot) { $this->outputInfo("No snapshot found for propSet %s", [$propSetName], 2); $snapshotService->takeSnapshotOfPropSet($renderedPrototype, $prototypeName, $propSetName, $sitePackageKey); - $this->newSnapshots += 1; + ++$this->newSnapshots; $this->detailedTestResults[$prototypeName][$propSetName] = [ 'success' => false, 'newSnapshot' => true @@ -215,7 +149,7 @@ private function testSinglePrototype(string $prototypeName, string $sitePackageK if ($diff && $this->updateAllSnapshots) { $this->outputInfo("Auto-update snapshot for propSet %s", [$propSetName], 2); $snapshotService->takeSnapshotOfPropSet($renderedPrototype, $prototypeName, $propSetName, $sitePackageKey); - $this->newSnapshots += 1; + ++$this->newSnapshots; $this->detailedTestResults[$prototypeName][$propSetName] = [ 'success' => false, 'newSnapshot' => true @@ -228,60 +162,57 @@ private function testSinglePrototype(string $prototypeName, string $sitePackageK continue; } - if ($diff && $this->interactiveMode) { - $this->outputInfo("PropSet %s has changed", [$propSetName], 2); - $this->outputTabbed($diff, [], 3); - $this->outputNewLine(); - // give non-existing answer as default to force decision - $answer = $this->waitAndAsk("Update snapshot?", self::UPDATE_SNAPSHOT_ANSWERS, "false", 2); - - switch($answer) { - case "y": - $snapshotService->takeSnapshotOfPropSet($renderedPrototype, $prototypeName, $propSetName, $sitePackageKey); - $this->newSnapshots += 1; - $this->detailedTestResults[$prototypeName][$propSetName] = [ - 'success' => false, - 'newSnapshot' => true - ]; - break; - case "n": - $this->makeTest($diff, $propSetName, $prototypeName); - break; - case "q": - throw new \Exception('Testing aborted'); - break; - case "a": - $snapshotService->takeSnapshotOfPropSet($renderedPrototype, $prototypeName, $propSetName, $sitePackageKey); - $this->newSnapshots += 1; - $this->updateAllSnapshots = true; - $this->detailedTestResults[$prototypeName][$propSetName] = [ - 'success' => false, - 'newSnapshot' => true - ]; - break; - case "d": - $this->skipAllSnapshots = true; - $this->makeTest($diff, $propSetName, $prototypeName); - break; - } + $this->outputInfo("PropSet %s has changed", [$propSetName], 2); + $this->outputTabbed($diff, [], 3); + $this->outputNewLine(); + // give non-existing answer as default to force decision + $answer = $this->waitAndAsk("Update snapshot?", self::UPDATE_SNAPSHOT_ANSWERS, "false", 2); + + switch($answer) { + case "y": + $snapshotService->takeSnapshotOfPropSet($renderedPrototype, $prototypeName, $propSetName, $sitePackageKey); + ++$this->newSnapshots; + $this->detailedTestResults[$prototypeName][$propSetName] = [ + 'success' => false, + 'newSnapshot' => true + ]; + break; + case "n": + $this->makeTest($diff, $propSetName, $prototypeName); + break; + case "q": + throw new \RuntimeException('Testing aborted'); + case "a": + $snapshotService->takeSnapshotOfPropSet($renderedPrototype, $prototypeName, $propSetName, $sitePackageKey); + ++$this->newSnapshots; + $this->updateAllSnapshots = true; + $this->detailedTestResults[$prototypeName][$propSetName] = [ + 'success' => false, + 'newSnapshot' => true + ]; + break; + case "d": + $this->skipAllSnapshots = true; + $this->makeTest($diff, $propSetName, $prototypeName); + break; } } $this->outputNewLine(); } - private function makeTest($diff, $propSetName, $prototypeName) + private function makeTest(string $diff, string $propSetName, string $prototypeName): void { - $this->totalTests += 1; + ++$this->totalTests; if (!$diff) { $this->outputSuccess($propSetName, [], 2); } else { $this->testSuccess = false; - $this->failedTests += 1; + ++$this->failedTests; if ($this->failedPrototypes && array_key_exists($prototypeName, $this->failedPrototypes)) { - array_push($this->failedPrototypes[$prototypeName], $propSetName); + $this->failedPrototypes[$prototypeName][] = $propSetName; } else { $this->failedPrototypes[$prototypeName] = array($propSetName); } diff --git a/Classes/Suffle/Snapshot/Traits/OutputTrait.php b/Classes/Suffle/Snapshot/Traits/OutputTrait.php index 7371bfa..47f381c 100644 --- a/Classes/Suffle/Snapshot/Traits/OutputTrait.php +++ b/Classes/Suffle/Snapshot/Traits/OutputTrait.php @@ -1,5 +1,7 @@ " . $prefix . "\t" . $text . PHP_EOL; $this->outputTabbed($formattedText, $arguments, $tabs); } - - /** - * @param string $text - * @param array $arguments - */ protected function output(string $text, array $arguments = []): void { $this->output->output($text, $arguments); @@ -145,7 +120,7 @@ protected function output(string $text, array $arguments = []): void * * @param string $question * @param array $answers in form of answer => explanation - * @param string $default default value if user presses enter without an answer (can't be null => throws Exception) + * @param string $default default value if user presses enter without an answer (can't be null => throws Exception) * @param int $tabs * @return string */ @@ -165,7 +140,8 @@ protected function waitAndAsk(string $question, array $answers, string $default, } } - $response = strtolower($this->output->ask("" . $formattedQuestion . " " . $answersShort . "", $default)); + $response = strtolower($this->output->ask("" . $formattedQuestion . " " . $answersShort . "", + $default)); } $this->output->outputLine(); diff --git a/Classes/Suffle/Snapshot/Traits/PackageTrait.php b/Classes/Suffle/Snapshot/Traits/PackageTrait.php index 86a647f..bd7ac82 100644 --- a/Classes/Suffle/Snapshot/Traits/PackageTrait.php +++ b/Classes/Suffle/Snapshot/Traits/PackageTrait.php @@ -1,5 +1,7 @@ findFirstOnline(); - return array( - 'packageKey' => $sitePackage->getSiteResourcesPackageKey(), - 'baseUri' => $this->generateBaseUri($sitePackage->getPrimaryDomain()) - ); + return [ + 'packageKey' => $sitePackage?->getSiteResourcesPackageKey(), + 'baseUri' => $this->generateBaseUri($sitePackage?->getPrimaryDomain()) + ]; } - /** - * @return string - */ - protected function getFirstOnlineSitePackageKey() + protected function getFirstOnlineSitePackageKey(): string { $sitePackage = $this->getFirstOnlineSitePackage(); - return $sitePackage['packageKey']; } @@ -88,12 +83,7 @@ function (array $packages, Site $site) { ); } - - /** - * @param $domain \Neos\Neos\Domain\Model\Domain - * @return string - */ - private function generateBaseUri($domain) + private function generateBaseUri(?Domain $domain): string { if (!$domain) { return ''; @@ -102,22 +92,16 @@ private function generateBaseUri($domain) $scheme = $domain->getScheme(); $port = $domain->getPort(); - $baseUri = ''; - $baseUri .= $scheme ?: 'http'; + $baseUri = $scheme ?: 'http'; $baseUri .= '://'; $baseUri .= $domain->getHostname(); if ($port !== null) { - switch ($scheme) { - case 'http': - $baseUri .= ($port !== 80 ? ':' . $port : ''); - break; - case 'https': - $baseUri .= ($port !== 443 ? ':' . $port : ''); - break; - default: - $baseUri .= (isset($port) ? ':' . $port : ''); - } + $baseUri .= match ($scheme) { + 'http' => ($port !== 80 ? ':' . $port : ''), + 'https' => ($port !== 443 ? ':' . $port : ''), + default => ':' . $port, + }; } return $baseUri; } diff --git a/Classes/Suffle/Snapshot/Traits/SimulateContextTrait.php b/Classes/Suffle/Snapshot/Traits/SimulateContextTrait.php index f7fd662..684b631 100644 --- a/Classes/Suffle/Snapshot/Traits/SimulateContextTrait.php +++ b/Classes/Suffle/Snapshot/Traits/SimulateContextTrait.php @@ -1,4 +1,6 @@ controllerContext) { $arguments = new Arguments([]); - if (method_exists(ActionRequest::class, 'fromHttpRequest')) { - // From Flow 6+ we have to use a static method to create an ActionRequest. Earlier versions use the constructor. - $actionRequest = ActionRequest::fromHttpRequest(new ServerRequest('GET', new Uri('http://neos.io'))); - $response = new ActionResponse(); - } else { - // This can be cleaned up when this package in a future release only support Flow 6+. - $httpRequest = \Neos\Flow\Http\Request::create(new \Neos\Flow\Http\Uri('http://neos.io')); - $actionRequest = new ActionRequest($httpRequest); - $response = new \Neos\Flow\Http\Response(); - } + // From Flow 6+ we have to use a static method to create an ActionRequest. Earlier versions use the constructor. + $actionRequest = ActionRequest::fromHttpRequest(new ServerRequest('GET', new Uri('http://neos.io'))); + $response = new ActionResponse(); $uriBuilder = new UriBuilder(); $uriBuilder @@ -85,18 +68,15 @@ protected function createDummyContext(): ControllerContext * Override the baseUri of static resource targets * * This is needed because the rendering can be executed via CLI without a baseUri - * - * @param string $baseUri - * @throws \Neos\Utility\Exception\PropertyNotAccessibleException */ - protected function injectBaseUriIntoFileSystemTargets($baseUri) + protected function injectBaseUriIntoFileSystemTargets(string $baseUri): void { // Make sure the base URI ends with a slash $baseUri = rtrim($baseUri, '/') . '/'; $collections = $this->resourceManager->getCollections(); - /** @var \Neos\Flow\ResourceManagement\Collection $collection */ + /** @var Collection $collection */ foreach ($collections as $collection) { $target = $collection->getTarget(); if ($target instanceof OverridableFileSystemTarget) { @@ -105,5 +85,3 @@ protected function injectBaseUriIntoFileSystemTargets($baseUri) } } } - - diff --git a/Configuration/Settings.yaml b/Configuration/Settings.yaml index 8ba2ab4..4020622 100644 --- a/Configuration/Settings.yaml +++ b/Configuration/Settings.yaml @@ -3,6 +3,8 @@ Suffle: snapshotSavePath: '%FLOW_PATH_DATA%Persistent/fusionSnapshots/' annotationKey: 'snapshot' previewPrototypeName: 'Suffle.Snapshot:Preview.Page' + exclude: + packageKeys: [] Neos: Flow: diff --git a/README.md b/README.md index 64bab6a..7ca8d44 100644 --- a/README.md +++ b/README.md @@ -26,16 +26,23 @@ Suffle: Snapshot: snapshotSavePath: '%FLOW_PATH_DATA%Persistent/fusionSnapshots/' annotationKey: 'snapshot' + exclude: + packageKeys: [] ```` ### snapshotSavePath The snapshotSavePath defines the directory, where the snapshots are saved. If you use any Version Control Software like Git, make sure not to ignore this folder. -## annotationKey +### annotationKey The annotationKey can be set, if you want to use another name to annotate test cases. Since the syntax of the cases is the same used for the [Monocle Styleguide](https://github.com/sitegeist/Sitegeist.Monocle), you can use the styleguide annotation for the testing as well. +### exclude.packageKeys + +You can exclude certain packages from the snapshot testing. +This is useful if you have packages that are not relevant for the snapshot testing. + ## Annotating Test Cases As long as the annotation ist present, the component is tested in a pure version, which uses the basic props of the Fusion Component.