From 8b063a167e74afc63ee61d4fe1cf08bb6a6375ca Mon Sep 17 00:00:00 2001 From: Ulrich Mathes Date: Tue, 16 Jul 2024 11:32:30 +0200 Subject: [PATCH 1/8] [v13] initialize PackageManager with mandatory DependencyOrderingService maybe we could use DI to get PackageManager but typically DI is not used for models as this can lead to performance issues with many instances --- Classes/Domain/Model/Package.php | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/Classes/Domain/Model/Package.php b/Classes/Domain/Model/Package.php index 088ed79..4c1c527 100644 --- a/Classes/Domain/Model/Package.php +++ b/Classes/Domain/Model/Package.php @@ -3,8 +3,9 @@ namespace Sitegeist\FluidStyleguide\Domain\Model; +use TYPO3\CMS\Core\Package\PackageInterface; use TYPO3\CMS\Core\Package\PackageManager; -use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; +use TYPO3\CMS\Core\Service\DependencyOrderingService; use TYPO3\CMS\Core\Utility\GeneralUtility; class Package @@ -59,18 +60,22 @@ public function getPath(): string return $this->path; } - public function getExtension(): ?\TYPO3\CMS\Core\Package\PackageInterface + public function getExtension(): ?PackageInterface { - if (!$this->extension) { - $activeExtensions = GeneralUtility::makeInstance(PackageManager::class)->getActivePackages(); + if ($this->extension) { + return $this->extension; + } + + $dependencyOrderingService = GeneralUtility::makeInstance(DependencyOrderingService::class); + $activeExtensions = GeneralUtility::makeInstance(PackageManager::class, $dependencyOrderingService)->getActivePackages(); foreach ($activeExtensions as $extension) { if (strpos($this->getPath(), $extension->getPackagePath()) === 0) { $this->extension = $extension; - break; - } + return $this->extension; } } - return $this->extension; + + return null; } /** From 4bda1be76ef8d726835964a71b4019ff036f5a8d Mon Sep 17 00:00:00 2001 From: Ulrich Mathes Date: Tue, 16 Jul 2024 11:34:18 +0200 Subject: [PATCH 2/8] [v13] initialize FrontendTypoScript with two more mandatory parameters --- Classes/Middleware/StyleguideRouter.php | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/Classes/Middleware/StyleguideRouter.php b/Classes/Middleware/StyleguideRouter.php index fafa3ab..55b8d3b 100644 --- a/Classes/Middleware/StyleguideRouter.php +++ b/Classes/Middleware/StyleguideRouter.php @@ -174,10 +174,12 @@ public function process( ->withAttribute('applicationType', SystemEnvironmentBuilder::REQUESTTYPE_FE) ->withAttribute('frontend.controller', $GLOBALS['TSFE'])); - if ((new Typo3Version())->getMajorVersion() >= 12) { - $request = $request->withAttribute('frontend.typoscript', new FrontendTypoScript(new RootNode(), [])); - $view->setRequest($request); - } + + $plainFrontendTypoScript = new FrontendTypoScript(new RootNode(), [], [], []); + $plainFrontendTypoScript->setConfigArray([]); + + $request = $request->withAttribute('frontend.typoscript', $plainFrontendTypoScript); + $view->setRequest($request); $controller->setRequest($request); From 674b5e4ba29bf13c13c7f96fa2260826be631ef9 Mon Sep 17 00:00:00 2001 From: Ulrich Mathes Date: Tue, 16 Jul 2024 11:44:45 +0200 Subject: [PATCH 3/8] [v13] drop TYPO3 11 and PHP 8.0 support; enable TYPO3 13 support --- composer.json | 21 ++++++++++++++------- ext_emconf.php | 10 +++++----- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/composer.json b/composer.json index a470084..9cc28be 100644 --- a/composer.json +++ b/composer.json @@ -6,22 +6,27 @@ "license": ["GPL-2.0-or-later"], "keywords": ["typo3", "typo3-extension", "fluid", "typo3-fluid", "components", "html", "template", "styleguide", "living-styleguide"], "authors": [ + { + "name": "Ulrich Mathes", + "email": "mathes@sitegeist.de" + }, { "name": "Simon Praetorius", - "email": "praetorius@sitegeist.de" + "email": "moin@praetorius.me" } ], "support": { "issues": "https://github.com/sitegeist/fluid-styleguide/issues" }, "require": { - "typo3/cms-core": "^12.2 || ^11.5", + "php": "^8.2", + "typo3/cms-core": "^13.1 || ^12.2", "sitegeist/fluid-components": "^3.0 || dev-master", "erusev/parsedown": "^1.7.4", "colinodell/json5": "^2.1" }, "require-dev": { - "typo3/testing-framework": "^6.0 || ^7.0", + "typo3/testing-framework": "^8.2", "squizlabs/php_codesniffer": "^3.0", "editorconfig-checker/editorconfig-checker": "^10.0" }, @@ -40,7 +45,11 @@ }, "config": { "vendor-dir": ".Build/vendor", - "bin-dir": ".Build/bin" + "bin-dir": ".Build/bin", + "allow-plugins": { + "typo3/class-alias-loader": true, + "typo3/cms-composer-installers": true + } }, "extra": { "typo3/cms": { @@ -51,10 +60,8 @@ } }, "scripts": { - "post-autoload-dump": [ - "TYPO3\\TestingFramework\\Composer\\ExtensionTestEnvironment::prepare" - ], "prepare-release": [ + "sed -i'' -e \"s/'version' => ''/'version' => '$(echo ${GITHUB_REF#refs/tags/} | sed 's/v//')'/\" ext_emconf.php", "rm -r .github .ecrc .editorconfig .gitattributes Tests Build" ], "lint": [ diff --git a/ext_emconf.php b/ext_emconf.php index 076499a..bb6ae70 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -3,18 +3,18 @@ 'title' => 'Fluid Styleguide', 'description' => 'Living styleguide for Fluid Components', 'category' => 'fe', - 'author' => 'Simon Praetorius', - 'author_email' => 'praetorius@sitegeist.de', + 'author' => 'Ulrich Mathes, Simon Praetorius', + 'author_email' => 'mathes@sitegeist.de, moin@praetorius.me', 'author_company' => 'sitegeist media solutions GmbH', 'state' => 'stable', 'uploadfolder' => false, 'clearCacheOnLoad' => false, - 'version' => '2.1.1', + 'version' => '', 'constraints' => [ 'depends' => [ - 'typo3' => '10.4.0-11.9.99', + 'typo3' => '12.4.0-13.9.99', 'fluid_components' => '3.0.0-3.99.99', - 'php' => '7.4.0-8.9.99' + 'php' => '8.2.0-8.9.99' ], 'conflicts' => [ ], From d329be2aa367234f2969440ce326c31088b72ba9 Mon Sep 17 00:00:00 2001 From: Ulrich Mathes Date: Tue, 16 Jul 2024 19:52:52 +0200 Subject: [PATCH 4/8] [v13] improve readability and use PHP 8 features MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the help of rector, typo3-rector and ☕ --- Classes/Controller/StyleguideController.php | 82 ++++--------------- Classes/Domain/Model/Component.php | 43 +++------- Classes/Domain/Model/ComponentFixture.php | 32 ++------ Classes/Domain/Model/ComponentLocation.php | 21 +---- Classes/Domain/Model/ComponentName.php | 17 +--- Classes/Domain/Model/Package.php | 47 +++-------- .../Repository/ComponentNameRepository.php | 9 +- .../Domain/Repository/ComponentRepository.php | 37 ++------- .../Domain/Repository/PackageRepository.php | 23 +----- .../Event/AfterConfigurationLoadedEvent.php | 11 +-- .../Event/PostProcessComponentViewEvent.php | 40 ++------- .../Component/ComponentFactoryInterface.php | 4 - Classes/Middleware/StyleguideRouter.php | 46 ++--------- Classes/Service/ComponentDownloadService.php | 2 +- .../StyleguideConfigurationManager.php | 50 ++--------- .../Component/ExampleViewHelper.php | 8 +- .../ViewHelpers/Format/MarkdownViewHelper.php | 14 +--- .../ViewHelpers/Uri/StyleguideViewHelper.php | 11 +-- ext_emconf.php | 6 +- 19 files changed, 97 insertions(+), 406 deletions(-) diff --git a/Classes/Controller/StyleguideController.php b/Classes/Controller/StyleguideController.php index ef7812b..9fa9873 100644 --- a/Classes/Controller/StyleguideController.php +++ b/Classes/Controller/StyleguideController.php @@ -4,72 +4,36 @@ namespace Sitegeist\FluidStyleguide\Controller; use Psr\Container\ContainerInterface; +use Psr\Http\Message\ResponseInterface; use Psr\Http\Message\ServerRequestInterface; use Sitegeist\FluidComponentsLinter\Service\CodeQualityService; use Sitegeist\FluidComponentsLinter\Service\ConfigurationService; -use Sitegeist\FluidStyleguide\Domain\Model\ComponentMetadata; use Sitegeist\FluidStyleguide\Domain\Repository\ComponentRepository; use Sitegeist\FluidStyleguide\Event\PostProcessComponentViewEvent; use Sitegeist\FluidStyleguide\Service\ComponentDownloadService; use Sitegeist\FluidStyleguide\Service\StyleguideConfigurationManager; use SMS\FluidComponents\Utility\ComponentLoader; use TYPO3\CMS\Core\EventDispatcher\EventDispatcher; +use TYPO3\CMS\Core\Http\HtmlResponse; use TYPO3\CMS\Core\Http\Response; use TYPO3\CMS\Core\Utility\ExtensionManagementUtility; use TYPO3\CMS\Core\Utility\MathUtility; -use TYPO3\CMS\Extbase\SignalSlot\Dispatcher; use TYPO3\CMS\Fluid\View\StandaloneView; class StyleguideController { - /** - * @var ComponentRepository - */ - protected $componentRepository; - - /** - * @var ComponentDownloadService - */ - protected $componentDownloadService; - - /** - * @var StyleguideConfigurationManager - */ - protected $styleguideConfigurationManager; - - /** - * @var ContainerInterface - */ - protected ContainerInterface $container; - - /** - * @var StandaloneView - */ - protected $view; - - /** - * @var ServerRequestInterface - */ - protected $request; + protected StandaloneView $view; + protected ServerRequestInterface $request; public function __construct( - ComponentRepository $componentRepository, - ComponentDownloadService $componentDownloadService, - StyleguideConfigurationManager $styleguideConfigurationManager, - ContainerInterface $container + protected ComponentRepository $componentRepository, + protected ComponentDownloadService $componentDownloadService, + protected StyleguideConfigurationManager $styleguideConfigurationManager, + protected ContainerInterface $container, ) { - $this->componentRepository = $componentRepository; - $this->componentDownloadService = $componentDownloadService; - $this->styleguideConfigurationManager = $styleguideConfigurationManager; - $this->container = $container; } - /** - * Shows a list of all components - * - * @return void - */ - public function listAction() + public function listAction(): ResponseInterface { $allComponents = $this->componentRepository->findWithFixtures(); $componentPackages = $this->groupComponentsByPackage($allComponents); @@ -78,14 +42,11 @@ public function listAction() 'navigation' => $allComponents, 'packages' => $componentPackages ]); + + return new HtmlResponse($this->view->render()); } - /** - * Shows a component detail page - * - * @return void - */ - public function showAction(array $arguments = []) + public function showAction(array $arguments = []): ResponseInterface { $component = $arguments['component'] ?? ''; $fixture = $arguments['fixture'] ?? 'default'; @@ -125,6 +86,8 @@ public function showAction(array $arguments = []) 'showQualityIssues' => $showQualityIssues, 'qualityIssues' => $qualityIssues ]); + + return new HtmlResponse($this->view->render()); } /** @@ -178,8 +141,6 @@ public function componentAction(array $arguments = []) /** * Provides a zip download of a component folder - * - * @return void */ public function downloadComponentZipAction(array $arguments = []) { @@ -214,7 +175,7 @@ protected function groupComponentsByPackage(array $components): array return $componentPackages; } - public function initializeView(StandaloneView $view) + public function initializeView(StandaloneView $view): void { $this->view = $view; @@ -232,16 +193,13 @@ public function initializeView(StandaloneView $view) $this->registerDemoComponents(); } - public function setRequest(ServerRequestInterface $request) + public function setRequest(ServerRequestInterface $request): void { $this->request = $request; } /** * Makes sure that no malicious user input will be passed to a component - * - * @param array $formData - * @return array */ protected function sanitizeFormData(array $formData): array { @@ -272,20 +230,14 @@ protected function sanitizeFormData(array $formData): array /** * Make sure that the component identifier doesn't include any malicious characters - * - * @param string $componentIdentifier - * @return string */ protected function sanitizeComponentIdentifier(string $componentIdentifier): string { - return trim(preg_replace('#[^a-z0-9_\\\\]#i', '', $componentIdentifier), '\\'); + return trim((string) preg_replace('#[^a-z0-9_\\\\]#i', '', $componentIdentifier), '\\'); } /** * Make sure that the fixture name doesn't include any malicious characters - * - * @param string $fixtureName - * @return string */ protected function sanitizeFixtureName(string $fixtureName): string { diff --git a/Classes/Domain/Model/Component.php b/Classes/Domain/Model/Component.php index 5bafd26..4c96d8e 100644 --- a/Classes/Domain/Model/Component.php +++ b/Classes/Domain/Model/Component.php @@ -13,35 +13,14 @@ class Component { - /** - * @var ComponentName - */ - protected $name; - - /** - * @var ComponentLocation - */ - protected $location; - - /** - * @var array - */ - protected $fixtures; - - /** - * @var string - */ - protected $documentation; - - /** - * @var array - */ - protected $arguments; - - public function __construct(ComponentName $name, ComponentLocation $location) - { - $this->name = $name; - $this->location = $location; + protected ?array $fixtures = null; + protected ?string $documentation; + protected ?array $arguments = null; + + public function __construct( + protected ComponentName $name, + protected ComponentLocation $location, + ) { } public function getName(): ComponentName @@ -93,14 +72,12 @@ public function getFixtures(): array return $this->fixtures; } - $this->fixtures = []; - if (!$this->hasFixtures()) { return $this->fixtures; } $fixtureFile = $this->getFixtureFile(); - $fileParts = pathinfo($fixtureFile); + $fileParts = pathinfo((string) $fixtureFile); switch ($fileParts['extension']) { case 'json': $fixtures = \json_decode(file_get_contents($fixtureFile), true) ?? []; @@ -197,7 +174,7 @@ public function getCodeQualityConfiguration(): ?string return null; } - protected function getComponentRenderer() + protected function getComponentRenderer(): ComponentRenderer { $componentRenderer = GeneralUtility::makeInstance(ComponentRenderer::class); $componentRenderer->setComponentNamespace($this->name->getIdentifier()); diff --git a/Classes/Domain/Model/ComponentFixture.php b/Classes/Domain/Model/ComponentFixture.php index 33253e8..27141b8 100644 --- a/Classes/Domain/Model/ComponentFixture.php +++ b/Classes/Domain/Model/ComponentFixture.php @@ -5,33 +5,11 @@ class ComponentFixture { - /** - * Absolute path to the fixture json file - * Note that this file contains multiple fixtures - * - * @var string - */ - protected $filePath; - - /** - * Name of the individual fixture - * - * @var string - */ - protected $name; - - /** - * Fixture data - * - * @var array - */ - protected $data; - - public function __construct(string $filePath, string $name, array $data) - { - $this->filePath = $filePath; - $this->name = $name; - $this->data = $data; + public function __construct( + protected string $filePath, // Absolute path to the fixture file. Note that this file contains multiple fixtures + protected string $name, + protected array $data, + ) { } public function getFilePath(): string diff --git a/Classes/Domain/Model/ComponentLocation.php b/Classes/Domain/Model/ComponentLocation.php index 4acd60f..0727bc2 100644 --- a/Classes/Domain/Model/ComponentLocation.php +++ b/Classes/Domain/Model/ComponentLocation.php @@ -5,26 +5,13 @@ class ComponentLocation { - /** - * @var string - */ - protected $filePath; + protected string $fileName = ''; + protected string $directory = ''; - /** - * @var string - */ - protected $fileName; - - /** - * @var string - */ - protected $directory; - - public function __construct(string $filePath) + public function __construct(protected string $filePath) { - $this->filePath = $filePath; $this->fileName = basename($filePath); - $this->directory = dirname($this->filePath); + $this->directory = dirname($filePath); } public function getFileName(): string diff --git a/Classes/Domain/Model/ComponentName.php b/Classes/Domain/Model/ComponentName.php index c470294..b4de26d 100644 --- a/Classes/Domain/Model/ComponentName.php +++ b/Classes/Domain/Model/ComponentName.php @@ -7,20 +7,11 @@ class ComponentName { - /** - * @var string - */ - protected $name; - - /** - * @var Package - */ - protected $package; - - public function __construct(string $name, Package $package) - { + public function __construct( + protected string $name, + protected Package $package, + ) { $this->name = trim($name, '\\'); - $this->package = $package; } public function getName(): string diff --git a/Classes/Domain/Model/Package.php b/Classes/Domain/Model/Package.php index 4c1c527..1b8507b 100644 --- a/Classes/Domain/Model/Package.php +++ b/Classes/Domain/Model/Package.php @@ -10,39 +10,17 @@ class Package { - /** - * PHP namespace for the component package - * - * @var string - */ - protected $namespace; - - /** - * Fluid namespace alias for the component package - * - * @var string - */ - protected $alias; - - /** - * Path for the component package - * - * @var string - */ - protected $path; - /** * Associated TYPO3 extension - * - * @var \TYPO3\CMS\Core\Package\PackageInterface */ - protected $extension; + protected PackageInterface $extension; - public function __construct(string $namespace, string $alias, string $path) - { + public function __construct( + protected string $namespace, // PHP namespace for the component package + protected string $alias, // Fluid namespace alias for the component package + protected string $path, // Path for the component package + ) { $this->namespace = trim($namespace, '\\'); - $this->alias = $alias; - $this->path = $path; } public function getNamespace(): string @@ -68,9 +46,9 @@ public function getExtension(): ?PackageInterface $dependencyOrderingService = GeneralUtility::makeInstance(DependencyOrderingService::class); $activeExtensions = GeneralUtility::makeInstance(PackageManager::class, $dependencyOrderingService)->getActivePackages(); - foreach ($activeExtensions as $extension) { - if (strpos($this->getPath(), $extension->getPackagePath()) === 0) { - $this->extension = $extension; + foreach ($activeExtensions as $extension) { + if (str_starts_with($this->getPath(), (string) $extension->getPackagePath())) { + $this->extension = $extension; return $this->extension; } } @@ -80,8 +58,6 @@ public function getExtension(): ?PackageInterface /** * Returns the specificity (= depth) of the PHP namespace - * - * @var int */ public function getSpecificity(): int { @@ -90,14 +66,11 @@ public function getSpecificity(): int /** * Checks if the specified component is part of this component package - * - * @param string $componentIdentifier - * @return boolean */ public function isResponsibleForComponent(string $componentIdentifier): bool { $componentIdentifier = trim($componentIdentifier, '\\'); - return strpos($componentIdentifier, $this->namespace) === 0; + return str_starts_with($componentIdentifier, $this->namespace); } public function extractComponentName(string $componentIdentifier): ?string diff --git a/Classes/Domain/Repository/ComponentNameRepository.php b/Classes/Domain/Repository/ComponentNameRepository.php index c3624c9..afdd3e8 100644 --- a/Classes/Domain/Repository/ComponentNameRepository.php +++ b/Classes/Domain/Repository/ComponentNameRepository.php @@ -5,18 +5,11 @@ use Sitegeist\FluidStyleguide\Domain\Model\ComponentName; use Sitegeist\FluidStyleguide\Domain\Repository\PackageRepository; -use TYPO3\CMS\Core\Utility\GeneralUtility; class ComponentNameRepository implements \TYPO3\CMS\Core\SingletonInterface { - /** - * @var PackageRepository - */ - protected $packageRepository; - - public function __construct(PackageRepository $packageRepository) + public function __construct(protected PackageRepository $packageRepository) { - $this->packageRepository = $packageRepository; } public function findByComponentIdentifier(string $componentIdentifier): ?ComponentName diff --git a/Classes/Domain/Repository/ComponentRepository.php b/Classes/Domain/Repository/ComponentRepository.php index edb5fe3..72d60a9 100644 --- a/Classes/Domain/Repository/ComponentRepository.php +++ b/Classes/Domain/Repository/ComponentRepository.php @@ -11,39 +11,17 @@ class ComponentRepository implements \TYPO3\CMS\Core\SingletonInterface { - /** - * @var PackageRepository - */ - protected $packageRepository; - - /** - * @var ComponentNameRepository - */ - protected $componentNameRepository; - - /** - * @var ComponentLoader - */ - protected $componentLoader; - - /** - * @var ComponentFactoryInterface - */ - protected $componentFactory; - - public function __construct(PackageRepository $packageRepository, ComponentNameRepository $componentNameRepository, ComponentLoader $componentLoader, ComponentFactoryInterface $componentFactory) - { - $this->packageRepository = $packageRepository; - $this->componentNameRepository = $componentNameRepository; - $this->componentLoader = $componentLoader; - $this->componentFactory = $componentFactory; + public function __construct( + protected PackageRepository $packageRepository, + protected ComponentNameRepository $componentNameRepository, + protected ComponentLoader $componentLoader, + protected ComponentFactoryInterface $componentFactory, + ) { } /** * Returns a list of all components in the current TYPO3 installation that have * a fixture file and thus can be displayed in the styleguide - * - * @return array */ public function findWithFixtures(): array { @@ -72,9 +50,6 @@ public function findWithFixtures(): array /** * Returns the component record for the specified component identifier - * - * @param string $identifier - * @return Component|null */ public function findWithFixturesByIdentifier(string $identifier): ?Component { diff --git a/Classes/Domain/Repository/PackageRepository.php b/Classes/Domain/Repository/PackageRepository.php index 984ef5e..4a42224 100644 --- a/Classes/Domain/Repository/PackageRepository.php +++ b/Classes/Domain/Repository/PackageRepository.php @@ -11,26 +11,14 @@ class PackageRepository implements \TYPO3\CMS\Core\SingletonInterface { - /** - * @var ComponentLoader - */ - protected $componentLoader; - - /** - * @var ContainerInterface - */ - protected $container; - - public function __construct(ComponentLoader $componentLoader, ContainerInterface $container) - { - $this->componentLoader = $componentLoader; - $this->container = $container; + public function __construct( + protected ComponentLoader $componentLoader, + protected ContainerInterface $container, + ) { } /** * Finds all components packages that are currently registered in this TYPO3 installation - * - * @return array */ public function findAll(): array { @@ -58,9 +46,6 @@ public function findAll(): array /** * Finds the component package the specified component belongs to - * - * @param string $componentIdentifier - * @return Package|null */ public function findForComponentIdentifier(string $componentIdentifier): ?Package { diff --git a/Classes/Event/AfterConfigurationLoadedEvent.php b/Classes/Event/AfterConfigurationLoadedEvent.php index 2cc500a..ef98276 100644 --- a/Classes/Event/AfterConfigurationLoadedEvent.php +++ b/Classes/Event/AfterConfigurationLoadedEvent.php @@ -8,13 +8,10 @@ final class AfterConfigurationLoadedEvent { - private array $configuration; - private SiteInterface $site; - - public function __construct(array $configuration, SiteInterface $site) - { - $this->configuration = $configuration; - $this->site = $site; + public function __construct( + private array $configuration, + private readonly SiteInterface $site + ) { } public function getConfiguration(): array diff --git a/Classes/Event/PostProcessComponentViewEvent.php b/Classes/Event/PostProcessComponentViewEvent.php index 0ac6c47..3232d6a 100644 --- a/Classes/Event/PostProcessComponentViewEvent.php +++ b/Classes/Event/PostProcessComponentViewEvent.php @@ -7,34 +7,6 @@ final class PostProcessComponentViewEvent { - /** - * Component that has been rendered - * - * @var string - */ - private $component; - - /** - * Name of the component fixture that has been used - * - * @var string - */ - private $fixtureName; - - /** - * Form data that has been entered by the user in the styleguide - * - * @var array - */ - private $formData; - - /** - * Rendered component html that will be displayed in the iframe - * - * @var string - */ - private $renderedView; - /** * Markup that should be added to the part * @@ -49,12 +21,12 @@ final class PostProcessComponentViewEvent */ private $footerData = []; - public function __construct(Component $component, string $fixtureName, array $formData, string $renderedView) - { - $this->component = $component; - $this->fixtureName = $fixtureName; - $this->formData = $formData; - $this->renderedView = $renderedView; + public function __construct( + private readonly Component $component, // Component that has been rendered + private readonly string $fixtureName, // Name of the component fixture that has been used + private readonly array $formData, // Form data that has been entered by the user in the styleguide + private string $renderedView // Rendered component html that will be displayed in the iframe + ) { } public function getComponent(): Component diff --git a/Classes/Factory/Component/ComponentFactoryInterface.php b/Classes/Factory/Component/ComponentFactoryInterface.php index d0ecede..19fcd3b 100644 --- a/Classes/Factory/Component/ComponentFactoryInterface.php +++ b/Classes/Factory/Component/ComponentFactoryInterface.php @@ -14,10 +14,6 @@ interface ComponentFactoryInterface /** * Builds the component and passes the component name and component location on. - * - * @param ComponentName $componentName - * @param ComponentLocation $componentLocation - * @return Component */ public function build(ComponentName $componentName, ComponentLocation $componentLocation) : Component; } diff --git a/Classes/Middleware/StyleguideRouter.php b/Classes/Middleware/StyleguideRouter.php index 55b8d3b..b978b30 100644 --- a/Classes/Middleware/StyleguideRouter.php +++ b/Classes/Middleware/StyleguideRouter.php @@ -15,7 +15,6 @@ use TYPO3\CMS\Core\Core\SystemEnvironmentBuilder; use TYPO3\CMS\Core\Http\HtmlResponse; use TYPO3\CMS\Core\Http\RedirectResponse; -use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Routing\PageArguments; use TYPO3\CMS\Core\Site\Entity\SiteLanguage; use TYPO3\CMS\Core\TypoScript\AST\Node\RootNode; @@ -29,38 +28,14 @@ class StyleguideRouter implements MiddlewareInterface { - const DEFAULT_ACTION = 'list'; - - /** - * @var Context - */ - protected $context; - - /** - * @var ContainerInterface - */ - protected ContainerInterface $container; - - /** - * @var ExtensionConfiguration - */ - protected ExtensionConfiguration $extensionConfiguration; - - /** - * @var FrontendUserAuthentication - */ - protected FrontendUserAuthentication $frontendUserAuthentication; + public const DEFAULT_ACTION = 'list'; public function __construct( - Context $context, - ContainerInterface $container, - ExtensionConfiguration $extensionConfiguration, - FrontendUserAuthentication $frontendUserAuthentication + protected Context $context, + protected ContainerInterface $container, + protected ExtensionConfiguration $extensionConfiguration, + protected FrontendUserAuthentication $frontendUserAuthentication ) { - $this->context = $context; - $this->container = $container; - $this->extensionConfiguration = $extensionConfiguration; - $this->frontendUserAuthentication = $frontendUserAuthentication; } public function process( @@ -77,19 +52,19 @@ public function process( $prefix = $prefixWithoutSlash . '/'; // Check if fluid styleguide should be rendered - if (strpos($request->getUri()->getPath(), $prefixWithoutSlash) !== 0) { + if (!str_starts_with((string) $request->getUri()->getPath(), $prefixWithoutSlash)) { return $handler->handle($request); } // Correct calls without trailing slash in request url - if (strpos($request->getUri()->getPath(), $prefix) !== 0) { + if (!str_starts_with((string) $request->getUri()->getPath(), $prefix)) { return new RedirectResponse( $request->getUri()->withPath($prefix . static::DEFAULT_ACTION) ); } // Extract routing information from URI - $path = substr($request->getUri()->getPath(), strlen($prefix)); + $path = substr((string) $request->getUri()->getPath(), strlen($prefix)); $pathSegments = explode('/', $path); $actionName = array_shift($pathSegments) ?? ''; $actionName = preg_replace('#[^a-z]#i', '', $actionName); @@ -160,11 +135,6 @@ public function process( // Create view $view = $this->container->get(StandaloneView::class); - if ((new Typo3Version())->getMajorVersion() < 12) { - $view->getRenderingContext()->setControllerName('Styleguide'); - $view->getRenderingContext()->setControllerAction($actionName); - } - $extbaseAttribute = new ExtbaseRequestParameters(); $extbaseAttribute->setControllerExtensionName('fluidStyleguide'); $extbaseAttribute->setControllerName('Styleguide'); diff --git a/Classes/Service/ComponentDownloadService.php b/Classes/Service/ComponentDownloadService.php index ec2d86d..5e59034 100644 --- a/Classes/Service/ComponentDownloadService.php +++ b/Classes/Service/ComponentDownloadService.php @@ -35,7 +35,7 @@ public function downloadZip(Component $component): void '', // Do not filter files by extension true, // Include subdirectories PHP_INT_MAX, // Recursion level - false // Files and directories to exclude. + '' // Files and directories to exclude. ); // Make paths relative to extension root directory. $files = GeneralUtility::removePrefixPathFromList($files, $componentPath); diff --git a/Classes/Service/StyleguideConfigurationManager.php b/Classes/Service/StyleguideConfigurationManager.php index 76e679d..1a5925e 100644 --- a/Classes/Service/StyleguideConfigurationManager.php +++ b/Classes/Service/StyleguideConfigurationManager.php @@ -17,40 +17,20 @@ class StyleguideConfigurationManager { - /** - * @var YamlFileLoader - */ - protected $yamlFileLoader; - - /** - * @var PackageManager - */ - protected $packageManager; - - protected EventDispatcherInterface $eventDispatcher; - - /** - * @var string - */ - protected $defaultConfigurationFile = 'EXT:fluid_styleguide/Configuration/Yaml/FluidStyleguide.yaml'; - - /** - * @var array - */ - protected $mergedConfiguration; + protected string $defaultConfigurationFile = 'EXT:fluid_styleguide/Configuration/Yaml/FluidStyleguide.yaml'; + protected array $mergedConfiguration = []; public function __construct( - YamlFileLoader $yamlFileLoader, - PackageManager $packageManager, - EventDispatcherInterface $eventDispatcher + protected YamlFileLoader $yamlFileLoader, + protected PackageManager $packageManager, + protected EventDispatcherInterface $eventDispatcher ) { $this->yamlFileLoader = $yamlFileLoader; $this->packageManager = $packageManager; - $this->eventDispatcher = $eventDispatcher; $this->loadConfiguration(); } - public function loadConfiguration() + public function loadConfiguration(): void { $this->mergedConfiguration = $this->yamlFileLoader->load($this->defaultConfigurationFile)['FluidStyleguide']; @@ -150,9 +130,7 @@ public function getLanguage($languageKey): ?array { $languageMatch = array_filter( $this->getLanguages(), - function ($language) use ($languageKey) { - return $language['identifier'] === $languageKey; - } + fn($language) => $language['identifier'] === $languageKey ); return reset($languageMatch) ?: null; } @@ -197,9 +175,7 @@ public function getBrandingCss(): string return ':root {' . array_reduce( array_keys($variables), - function ($css, $variable) use ($variables) { - return $css . $variable . ':' . $variables[$variable] . ';'; - }, + fn($css, $variable) => $css . $variable . ':' . $variables[$variable] . ';', '' ) . '}'; } @@ -240,7 +216,7 @@ protected function sanitizeComponentAssets($assets) if (!static::isRemoteUri($file)) { try { $file = $this->generateAssetUrl($file); - } catch (InvalidAssetException $e) { + } catch (InvalidAssetException) { unset($assets[$key]); } } @@ -250,9 +226,6 @@ protected function sanitizeComponentAssets($assets) /** * Generates an asset (js/css) url without throwing away any url prefixes - * - * @param string $path - * @return Uri */ protected function generateAssetUrl(string $path): Uri { @@ -274,9 +247,6 @@ protected function generateAssetUrl(string $path): Uri /** * Checks if the provided uri is a valid remote uri - * - * @param string $uri - * @return boolean */ protected static function isRemoteUri(string $uri): bool { @@ -286,8 +256,6 @@ protected static function isRemoteUri(string $uri): bool /** * Returns the current Site object to create urls - * - * @return SiteInterface */ protected static function getCurrentSite(): SiteInterface { diff --git a/Classes/ViewHelpers/Component/ExampleViewHelper.php b/Classes/ViewHelpers/Component/ExampleViewHelper.php index aed3daf..ea8170b 100644 --- a/Classes/ViewHelpers/Component/ExampleViewHelper.php +++ b/Classes/ViewHelpers/Component/ExampleViewHelper.php @@ -109,7 +109,7 @@ public static function renderStatic( 'Exception: %s (#%d %s)', $e->getMessage(), $e->getCode(), - get_class($e) + $e::class ); } else { throw $e; @@ -156,9 +156,7 @@ public static function renderComponent( return ComponentRenderer::renderComponent( $data, - function () { - return ''; - }, + fn() => '', $renderingContext, $component->getName()->getIdentifier() ); @@ -253,7 +251,7 @@ public static function applyComponentContext( protected static function checkObtainComponentContextFromFile(string $context): string { // Probably not a file path - if (strpos($context, '|') !== false) { + if (str_contains($context, '|')) { return $context; } diff --git a/Classes/ViewHelpers/Format/MarkdownViewHelper.php b/Classes/ViewHelpers/Format/MarkdownViewHelper.php index b085a9c..f5e8581 100644 --- a/Classes/ViewHelpers/Format/MarkdownViewHelper.php +++ b/Classes/ViewHelpers/Format/MarkdownViewHelper.php @@ -11,32 +11,20 @@ class MarkdownViewHelper extends AbstractViewHelper { use CompileWithRenderStatic; - /** - * @var \Parsedown - */ - protected static $markdownParser; + protected static \Parsedown $markdownParser; /** * Don't escape markdown html - * - * @var boolean */ protected $escapeOutput = false; /** * Don't escape input html - * - * @var boolean */ protected $escapeChildren = false; /** * Renders markdown code in fluid templates - * - * @param array $arguments - * @param \Closure $renderChildrenClosure - * @param RenderingContextInterface $renderingContext - * @return void */ public static function renderStatic( array $arguments, diff --git a/Classes/ViewHelpers/Uri/StyleguideViewHelper.php b/Classes/ViewHelpers/Uri/StyleguideViewHelper.php index 0e0ce42..61e8a1a 100644 --- a/Classes/ViewHelpers/Uri/StyleguideViewHelper.php +++ b/Classes/ViewHelpers/Uri/StyleguideViewHelper.php @@ -15,7 +15,7 @@ class StyleguideViewHelper extends AbstractViewHelper { use CompileWithRenderStatic; - public function initializeArguments() + public function initializeArguments(): void { $this->registerArgument('action', 'string', 'Action name', true); $this->registerArgument('arguments', 'array', 'Action arguments', false, []); @@ -25,11 +25,6 @@ public function initializeArguments() /** * Renders markdown code in fluid templates - * - * @param array $arguments - * @param \Closure $renderChildrenClosure - * @param RenderingContextInterface $renderingContext - * @return void */ public static function renderStatic( array $arguments, @@ -38,7 +33,7 @@ public static function renderStatic( ): UriInterface { $prefix = GeneralUtility::makeInstance(ExtensionConfiguration::class) ->get('fluid_styleguide', 'uriPrefix'); - $prefix = rtrim($prefix, '/') . '/'; + $prefix = rtrim((string) $prefix, '/') . '/'; $baseUrl = static::getCurrentSite()->getBase(); @@ -61,8 +56,6 @@ public static function renderStatic( /** * Returns the current Site object to create urls - * - * @return SiteInterface */ protected static function getCurrentSite(): SiteInterface { diff --git a/ext_emconf.php b/ext_emconf.php index bb6ae70..05ac587 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -7,14 +7,12 @@ 'author_email' => 'mathes@sitegeist.de, moin@praetorius.me', 'author_company' => 'sitegeist media solutions GmbH', 'state' => 'stable', - 'uploadfolder' => false, - 'clearCacheOnLoad' => false, 'version' => '', 'constraints' => [ 'depends' => [ - 'typo3' => '12.4.0-13.9.99', + 'typo3' => '12.4.0-13.4.99', 'fluid_components' => '3.0.0-3.99.99', - 'php' => '8.2.0-8.9.99' + 'php' => '8.2.0-8.3.99' ], 'conflicts' => [ ], From 59484273ce400f4cf428f56878b01f7c82932612 Mon Sep 17 00:00:00 2001 From: Ulrich Mathes Date: Tue, 16 Jul 2024 12:00:50 +0200 Subject: [PATCH 5/8] [v13] update testing to PHPUnit 11 even there are no unit and functional test yet available --- .github/workflows/tests.yml | 20 ++++--------------- Build/FunctionalTests.xml | 15 +++++++------- Build/Scripts/runTests.sh | 26 ++++++++++++------------- Build/UnitTests.xml | 16 +++++++-------- Build/testing-docker/docker-compose.yml | 2 +- 5 files changed, 31 insertions(+), 48 deletions(-) diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 9edcf3f..8cc0be0 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -40,14 +40,8 @@ jobs: strategy: max-parallel: 2 matrix: - php-versions: ['8.2', '8.1', '8.0'] - typo3-versions: [12, 11] - exclude: - - php-versions: '8.0' - typo3-versions: 12 - include: - - php-versions: '7.4' - typo3-versions: 11 + php-versions: ['8.3', '8.2'] + typo3-versions: [13, 12] name: Unit (PHP ${{ matrix.php-versions }}, TYPO3 ${{ matrix.typo3-versions }}) steps: @@ -80,14 +74,8 @@ jobs: strategy: max-parallel: 2 matrix: - php-versions: ['8.2', '8.1', '8.0'] - typo3-versions: [12, 11] - exclude: - - php-versions: '8.0' - typo3-versions: 12 - include: - - php-versions: '7.4' - typo3-versions: 11 + php-versions: ['8.3', '8.2'] + typo3-versions: [13, 12] name: Functional (PHP ${{ matrix.php-versions }}, TYPO3 ${{ matrix.typo3-versions }}) steps: diff --git a/Build/FunctionalTests.xml b/Build/FunctionalTests.xml index faaca2e..ffd3c43 100644 --- a/Build/FunctionalTests.xml +++ b/Build/FunctionalTests.xml @@ -1,19 +1,18 @@ + @@ -21,8 +20,8 @@ - - - + + + diff --git a/Build/Scripts/runTests.sh b/Build/Scripts/runTests.sh index 14eddaa..3a70e3a 100755 --- a/Build/Scripts/runTests.sh +++ b/Build/Scripts/runTests.sh @@ -39,7 +39,7 @@ Also used by github actions for test execution. Usage: $0 [options] [file] -No arguments: Run all unit tests with PHP 7.4 +No arguments: Run all unit tests with PHP 8.2 Options: -s <...> @@ -61,17 +61,15 @@ Options: - postgres: use postgres - sqlite: use sqlite - -p <7.4|8.0|8.1|8.2> + -p <8.2|8.3> Specifies the PHP minor version to be used - - 7.4 (default): use PHP 7.4 - - 8.0: use PHP 8.0 - - 8.1: use PHP 8.1 - - 8.2: use PHP 8.2 + - 8.2 (default): use PHP 8.2 + - 8.3: use PHP 8.3 - -t <11|12> + -t <12|13> Specifies the TYPO3 version to be used - - 11 (default): use TYPO3 11 - - 12: use TYPO3 12 + - 12 (default): use TYPO3 12 + - 13: use TYPO3 13 -e "" Only with -s functional|unit @@ -103,11 +101,11 @@ Options: Show this help. Examples: - # Run unit tests using PHP 7.4 + # Run unit tests using PHP 8.2 TYPO3 12 ./Build/Scripts/runTests.sh - # Run unit tests using PHP 7.3 - ./Build/Scripts/runTests.sh -p 7.3 + # Run unit tests using PHP 8.3 TYPO3 13 + ./Build/Scripts/runTests.sh -p 8.3 -t 13 EOF # Test if docker-compose exists, else exit out with error @@ -133,8 +131,8 @@ else fi TEST_SUITE="unit" DBMS="mariadb" -PHP_VERSION="7.4" -TYPO3_VERSION="11" +PHP_VERSION="8.2" +TYPO3_VERSION="12" PHP_XDEBUG_ON=0 PHP_XDEBUG_PORT=9003 EXTRA_TEST_OPTIONS="" diff --git a/Build/UnitTests.xml b/Build/UnitTests.xml index 6cefaa3..8a1a0f1 100644 --- a/Build/UnitTests.xml +++ b/Build/UnitTests.xml @@ -1,21 +1,19 @@ + @@ -23,8 +21,8 @@ - - - + + + diff --git a/Build/testing-docker/docker-compose.yml b/Build/testing-docker/docker-compose.yml index 3a877f3..d2d97f4 100644 --- a/Build/testing-docker/docker-compose.yml +++ b/Build/testing-docker/docker-compose.yml @@ -38,7 +38,7 @@ services: fi composer config allow-plugins.typo3/class-alias-loader true composer config allow-plugins.typo3/cms-composer-installers true - composer require typo3/minimal "^${TYPO3_VERSION}" --prefer-dist --no-progress --no-suggest + composer require typo3/minimal "^${TYPO3_VERSION}" --prefer-dist --no-progress composer install --no-progress --no-interaction; " composer_install_max: From 5e6a2bcd2bd762c832b06fcb9f18bfc5668aebd2 Mon Sep 17 00:00:00 2001 From: Ulrich Mathes Date: Wed, 17 Jul 2024 09:17:12 +0200 Subject: [PATCH 6/8] [v13] fix backward compatibility FrontendTypoScript for TYPO3 12 --- Classes/Middleware/StyleguideRouter.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Classes/Middleware/StyleguideRouter.php b/Classes/Middleware/StyleguideRouter.php index b978b30..49d5142 100644 --- a/Classes/Middleware/StyleguideRouter.php +++ b/Classes/Middleware/StyleguideRouter.php @@ -15,6 +15,7 @@ use TYPO3\CMS\Core\Core\SystemEnvironmentBuilder; use TYPO3\CMS\Core\Http\HtmlResponse; use TYPO3\CMS\Core\Http\RedirectResponse; +use TYPO3\CMS\Core\Information\Typo3Version; use TYPO3\CMS\Core\Routing\PageArguments; use TYPO3\CMS\Core\Site\Entity\SiteLanguage; use TYPO3\CMS\Core\TypoScript\AST\Node\RootNode; @@ -146,7 +147,9 @@ public function process( $plainFrontendTypoScript = new FrontendTypoScript(new RootNode(), [], [], []); - $plainFrontendTypoScript->setConfigArray([]); + if ((new Typo3Version())->getMajorVersion() >= 13) { + $plainFrontendTypoScript->setConfigArray([]); + } $request = $request->withAttribute('frontend.typoscript', $plainFrontendTypoScript); $view->setRequest($request); From 1abea20d72676161c1631b8b59d69c0915959685 Mon Sep 17 00:00:00 2001 From: Ulrich Mathes Date: Fri, 23 Aug 2024 10:56:40 +0200 Subject: [PATCH 7/8] [v13] stop TYPO3 version compatibility at 13.2 before v13 Feature freeze --- composer.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/composer.json b/composer.json index 9cc28be..bd66eb1 100644 --- a/composer.json +++ b/composer.json @@ -20,7 +20,7 @@ }, "require": { "php": "^8.2", - "typo3/cms-core": "^13.1 || ^12.2", + "typo3/cms-core": "13.2.* || ^12.4", "sitegeist/fluid-components": "^3.0 || dev-master", "erusev/parsedown": "^1.7.4", "colinodell/json5": "^2.1" From 595983f15665005a65c3940562da99e7569de2ac Mon Sep 17 00:00:00 2001 From: Ulrich Mathes Date: Fri, 23 Aug 2024 13:39:29 +0200 Subject: [PATCH 8/8] [v13] update testing configuation for docker compose --- Build/Scripts/runTests.sh | 44 ++++++++++++------------- Build/testing-docker/docker-compose.yml | 1 - 2 files changed, 22 insertions(+), 23 deletions(-) diff --git a/Build/Scripts/runTests.sh b/Build/Scripts/runTests.sh index 3a70e3a..e416d14 100755 --- a/Build/Scripts/runTests.sh +++ b/Build/Scripts/runTests.sh @@ -108,9 +108,9 @@ Examples: ./Build/Scripts/runTests.sh -p 8.3 -t 13 EOF -# Test if docker-compose exists, else exit out with error -if ! type "docker-compose" > /dev/null; then - echo "This script relies on docker and docker-compose. Please install" >&2 +# Test if docker compose exists, else exit out with error +if ! type "docker" > /dev/null; then + echo "This script relies on docker and docker compose. Please install" >&2 exit 1 fi @@ -214,41 +214,41 @@ fi case ${TEST_SUITE} in composerInstall) setUpDockerComposeDotEnv - docker-compose run composer_install + docker compose run composer_install SUITE_EXIT_CODE=$? - docker-compose down + docker compose down ;; composerInstallMax) setUpDockerComposeDotEnv - docker-compose run composer_install_max + docker compose run composer_install_max SUITE_EXIT_CODE=$? - docker-compose down + docker compose down ;; composerInstallMin) setUpDockerComposeDotEnv - docker-compose run composer_install_min + docker compose run composer_install_min SUITE_EXIT_CODE=$? - docker-compose down + docker compose down ;; composerValidate) setUpDockerComposeDotEnv - docker-compose run composer_validate + docker compose run composer_validate SUITE_EXIT_CODE=$? - docker-compose down + docker compose down ;; functional) setUpDockerComposeDotEnv case ${DBMS} in mariadb) - docker-compose run functional_mariadb10 + docker compose run functional_mariadb10 SUITE_EXIT_CODE=$? ;; mssql) - docker-compose run functional_mssql2019latest + docker compose run functional_mssql2019latest SUITE_EXIT_CODE=$? ;; postgres) - docker-compose run functional_postgres10 + docker compose run functional_postgres10 SUITE_EXIT_CODE=$? ;; sqlite) @@ -257,7 +257,7 @@ case ${TEST_SUITE} in # root if docker creates it. Thank you, docker. We create the path beforehand # to avoid permission issues. mkdir -p ${ROOT_DIR}/.Build/Web/typo3temp/var/tests/functional-sqlite-dbs/ - docker-compose run functional_sqlite + docker compose run functional_sqlite SUITE_EXIT_CODE=$? ;; *) @@ -266,25 +266,25 @@ case ${TEST_SUITE} in echo "${HELP}" >&2 exit 1 esac - docker-compose down + docker compose down ;; lintPhp) setUpDockerComposeDotEnv - docker-compose run lint_php + docker compose run lint_php SUITE_EXIT_CODE=$? - docker-compose down + docker compose down ;; lintEditorconfig) setUpDockerComposeDotEnv - docker-compose run lint_editorconfig + docker compose run lint_editorconfig SUITE_EXIT_CODE=$? - docker-compose down + docker compose down ;; unit) setUpDockerComposeDotEnv - docker-compose run unit + docker compose run unit SUITE_EXIT_CODE=$? - docker-compose down + docker compose down ;; update) # pull typo3/core-testing-*:latest versions of those ones that exist locally diff --git a/Build/testing-docker/docker-compose.yml b/Build/testing-docker/docker-compose.yml index d2d97f4..d267530 100644 --- a/Build/testing-docker/docker-compose.yml +++ b/Build/testing-docker/docker-compose.yml @@ -1,4 +1,3 @@ -version: '2.3' services: mariadb10: image: mariadb:10