From 7c8dff72d1ee180ec206ef76132b8272f363cb95 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20H=C3=B6lzel?= <56548897+davidhoelzel@users.noreply.github.com> Date: Wed, 3 Apr 2024 10:08:14 +0200 Subject: [PATCH 1/6] Breakpoint configuration (#18) * add breakpoint config --- docs/BundleConfiguration.md | 17 +++++++++ src/DependencyInjection/Configuration.php | 9 +++++ src/DependencyInjection/TwigDocExtension.php | 1 + src/Service/ComponentService.php | 6 ++++ .../Service/ComponentServiceTest.php | 7 +++- .../DependencyInjection/ConfigurationTest.php | 35 ++++++++++++++++++- 6 files changed, 73 insertions(+), 2 deletions(-) diff --git a/docs/BundleConfiguration.md b/docs/BundleConfiguration.md index 972791f..b5aecb5 100644 --- a/docs/BundleConfiguration.md +++ b/docs/BundleConfiguration.md @@ -11,6 +11,10 @@ twig_doc: - '%twig.default_path%/components' categories: - name: Components + breakpoints: + small: 240 + medium: 640 + large: 768 ``` ### Directories @@ -66,3 +70,16 @@ twig_doc: ``` The default category is always merged into the configuration. + + +### Breakpoints + +To use custom breakpoints, simply provide a breakpoint-config. You can name the breakpoints as you like: + +```yaml +twig_doc: + breakpoints: + iphone: 598 + unusual: 743 +... +``` diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index f1c64b4..14ead37 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -19,6 +19,15 @@ public function getConfigTreeBuilder(): TreeBuilder ->thenInvalid('The twig_doc documentation identifier must match \w (regex)') ->end() ->end() + ->arrayNode('breakpoints') + ->defaultValue([ + 'small' => 240, + 'medium' => 640, + 'large' => 768, + ]) + ->integerPrototype() + ->end() + ->end() ->arrayNode('directories')->defaultValue(['%twig.default_path%/components']) ->scalarPrototype()->end() ->end() diff --git a/src/DependencyInjection/TwigDocExtension.php b/src/DependencyInjection/TwigDocExtension.php index 602679f..17740e2 100644 --- a/src/DependencyInjection/TwigDocExtension.php +++ b/src/DependencyInjection/TwigDocExtension.php @@ -22,6 +22,7 @@ public function load(array $configs, ContainerBuilder $container): void $definition = $container->getDefinition('twig_doc.service.component'); $definition->setArgument('$componentsConfig', $config['components']); + $definition->setArgument('$breakpointConfig', $config['components']); $definition->setArgument('$configReadTime', time()); $categories = array_merge([['name' => ComponentCategory::DEFAULT_CATEGORY]], $config['categories']); diff --git a/src/Service/ComponentService.php b/src/Service/ComponentService.php index c359dc9..0f7be91 100644 --- a/src/Service/ComponentService.php +++ b/src/Service/ComponentService.php @@ -18,6 +18,7 @@ public function __construct( private readonly ComponentItemFactory $itemFactory, private readonly array $componentsConfig, private readonly CacheInterface $cache, + private readonly array $breakpointConfig, private readonly int $configReadTime = 0 ) { } @@ -95,4 +96,9 @@ public function getComponent(string $name): ?ComponentItem { return array_values(array_filter((array) $this->getComponents(), fn (ComponentItem $c) => $c->getName() === $name))[0] ?? null; } + + public function getBreakpoints(): array + { + return $this->breakpointConfig; + } } diff --git a/tests/Functional/Service/ComponentServiceTest.php b/tests/Functional/Service/ComponentServiceTest.php index 44c6d4b..56951f1 100644 --- a/tests/Functional/Service/ComponentServiceTest.php +++ b/tests/Functional/Service/ComponentServiceTest.php @@ -67,7 +67,12 @@ public function testParsePerformance(): void $start = microtime(true); - $service = new ComponentService($factory, $this->getLargeConfig(), static::getContainer()->get(CacheInterface::class)); + $service = new ComponentService( + $factory, + $this->getLargeConfig(), + static::getContainer()->get(CacheInterface::class), + [] + ); $service->getComponents(); diff --git a/tests/Unit/DependencyInjection/ConfigurationTest.php b/tests/Unit/DependencyInjection/ConfigurationTest.php index 4a2b778..c6d9776 100644 --- a/tests/Unit/DependencyInjection/ConfigurationTest.php +++ b/tests/Unit/DependencyInjection/ConfigurationTest.php @@ -18,7 +18,7 @@ public function testConfigTree(array $options, array $expectedResult) $configuration = new Configuration(); $config = $processor->processConfiguration($configuration, [$options]); - $this->assertEqualsCanonicalizing($expectedResult, $config); + $this->assertEquals($expectedResult, $config); } public static function getTestConfiguration(): iterable @@ -41,6 +41,11 @@ public static function getTestConfiguration(): iterable ], [ 'doc_identifier' => 'TWIG_DOC', + 'breakpoints' => [ + 'small' => 240, + 'medium' => 640, + 'large' => 768, + ], 'directories' => [ __DIR__.'/../../TestApp/templates/components', __DIR__.'/../../TestApp/templates/snippets', @@ -100,6 +105,11 @@ public static function getTestConfiguration(): iterable ], [ 'doc_identifier' => 'TWIG_DOC', + 'breakpoints' => [ + 'small' => 240, + 'medium' => 640, + 'large' => 768, + ], 'directories' => [ __DIR__.'/../../TestApp/templates/components', __DIR__.'/../../TestApp/templates/snippets', @@ -139,5 +149,28 @@ public static function getTestConfiguration(): iterable ], ], ]; + + yield 'Breakpoint config' => [ + [ + 'breakpoints' => [ + 'iphone' => 568, + 'galaxy s10' => 658, + 'generic' => 896, + ], + ], + [ + 'breakpoints' => [ + 'iphone' => 568, + 'galaxy s10' => 658, + 'generic' => 896, + ], + 'doc_identifier' => 'TWIG_DOC', + 'directories' => [ + '%twig.default_path%/components', + ], + 'categories' => [], + 'components' => [], + ], + ]; } } From 0ffed822c41fb808e248bb55bd4fc7d59aa6e92d Mon Sep 17 00:00:00 2001 From: david Date: Wed, 3 Apr 2024 10:19:33 +0200 Subject: [PATCH 2/6] add disclaimer - added forgotten documentation for breakpoints --- README.md | 3 +++ docs/BundleConfiguration.md | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0d3cb30..0125245 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,9 @@ --- +> **Important**: This is an experimental version and might change drastically. +> Therefore, you might encounter breaking changes when updating until we release a stable version. + Allows you to create an overview for your Twig Components, be it either [UX-Components](https://symfony.com/bundles/ux-twig-component/current/index.html), [UX-Live-Components](https://symfony.com/bundles/ux-live-component/current/index.html) or simple snippet templates. Components will be grouped in categories and optional sub-categories. diff --git a/docs/BundleConfiguration.md b/docs/BundleConfiguration.md index b5aecb5..fef0896 100644 --- a/docs/BundleConfiguration.md +++ b/docs/BundleConfiguration.md @@ -1,6 +1,6 @@ ## Configuring the bundle -When you do not want to customize, you do not need any config file. +When you do not want to customize, you do not need any config file. The bundle provides following defaults: From 5a00463d0dc245b4341a29d2827e02ee81bab88d Mon Sep 17 00:00:00 2001 From: Benjamin Schultz Date: Wed, 3 Apr 2024 10:49:07 +0200 Subject: [PATCH 3/6] Fix typo --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0125245..5dee63f 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## Twic Doc Bundle +## Twig Doc Bundle [![Image](docs/resources/images/qossmic.png)](https://qossmic.com) Brought to you by qossmic! @@ -42,7 +42,7 @@ Install the bundle As symfony never creates routes for bundles, you need to configure this on your own! -Create a config file: configs/routes/twig_doc.yaml +Create a config file: config/routes/twig_doc.yaml ```yaml twig_doc: From ac0add4611d24b2cdaf37c4980ee6934c95ae1c6 Mon Sep 17 00:00:00 2001 From: Benjamin Schultz Date: Wed, 3 Apr 2024 11:17:54 +0200 Subject: [PATCH 4/6] Optimize function calls [EA] '$item->$method()' would make more sense here (it's also faster). --- src/Component/ComponentItemList.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Component/ComponentItemList.php b/src/Component/ComponentItemList.php index 64ca5d3..24de966 100644 --- a/src/Component/ComponentItemList.php +++ b/src/Component/ComponentItemList.php @@ -42,10 +42,10 @@ public function sort(string $field, string $direction = self::SORT_ASC): void $this->uasort(function (ComponentItem $item, ComponentItem $item2) use ($method, $direction) { if ($direction === self::SORT_DESC) { - return \call_user_func([$item2, $method]) <=> \call_user_func([$item, $method]); + return $item2->$method() <=> $item->$method(); } - return \call_user_func([$item, $method]) <=> \call_user_func([$item2, $method]); + return $item->$method() <=> $item2->$method(); }); } From c08343a2bd135c8e68f92f737b4f4e109fc39de5 Mon Sep 17 00:00:00 2001 From: Benjamin Schultz Date: Wed, 3 Apr 2024 12:20:24 +0200 Subject: [PATCH 5/6] Fix route prefix Regarding best practices, the bundle routes must be prefixed with the bundle alias. --- config/routing/documentation.xml | 6 +++--- templates/component/_item.html.twig | 6 +++--- templates/component/_search.html.twig | 4 ++-- templates/component/_viewport.html.twig | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/config/routing/documentation.xml b/config/routing/documentation.xml index bfcd3ee..dcf6005 100644 --- a/config/routing/documentation.xml +++ b/config/routing/documentation.xml @@ -4,13 +4,13 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://symfony.com/schema/routing https://symfony.com/schema/routing/routing-1.0.xsd"> - + twig_doc.controller.documentation::index - + twig_doc.controller.documentation::invalidComponents - + twig_doc.controller.documentation::componentView diff --git a/templates/component/_item.html.twig b/templates/component/_item.html.twig index 7b8649c..665b053 100644 --- a/templates/component/_item.html.twig +++ b/templates/component/_item.html.twig @@ -20,14 +20,14 @@

Sub-Category

{% if component.category.parent %}

- + {{ component.category.name }}

@@ -39,7 +39,7 @@

Tags

{% for tag in component.tags %}

- {{ tag }} + {{ tag }}

{% endfor %}
diff --git a/templates/component/_search.html.twig b/templates/component/_search.html.twig index 760f93f..f4f1148 100644 --- a/templates/component/_search.html.twig +++ b/templates/component/_search.html.twig @@ -1,4 +1,4 @@ -
+ @@ -11,6 +11,6 @@ {% if filterQuery %} - Show all + Show all {% endif %}
diff --git a/templates/component/_viewport.html.twig b/templates/component/_viewport.html.twig index ac3c1a2..e24cbd5 100644 --- a/templates/component/_viewport.html.twig +++ b/templates/component/_viewport.html.twig @@ -1,6 +1,6 @@
From 50f2c968f6ff18177520af4de1dc480cfd5a91b0 Mon Sep 17 00:00:00 2001 From: Benjamin Schultz Date: Wed, 3 Apr 2024 12:28:56 +0200 Subject: [PATCH 6/6] Cleanup and optimize code Add strict types and return types where it was missing. --- src/Cache/ComponentsWarmer.php | 14 ++++++++-- src/Component/ComponentInvalid.php | 6 ++--- src/Component/ComponentItem.php | 8 ++++++ src/Component/ComponentItemFactory.php | 11 +++++--- src/Component/ComponentItemList.php | 18 ++++++++----- src/Configuration/ParserInterface.php | 2 ++ src/Configuration/YamlParser.php | 6 ++++- src/Controller/TwigDocController.php | 8 +++--- .../Compiler/TwigDocCollectDocsPass.php | 26 +++++++++---------- src/DependencyInjection/Configuration.php | 2 ++ src/DependencyInjection/TwigDocExtension.php | 2 ++ src/Service/CategoryService.php | 2 +- src/Service/ComponentService.php | 14 +++++----- templates/blocks/page_blocks.html.twig | 1 - .../component/_invalid_component.html.twig | 10 +++---- templates/component/_parameter.html.twig | 2 +- templates/component/_viewport.html.twig | 5 ++-- templates/pages/invalid_components.html.twig | 2 +- .../Functional/Cache/ComponentsWarmerTest.php | 6 +++-- .../Controller/TwigDocControllerTest.php | 2 ++ .../Service/ComponentItemFactoryTest.php | 10 ++++--- .../Service/ComponentServiceTest.php | 4 ++- .../Functional/Twig/TwigDocExtensionTest.php | 2 ++ .../Component/ComponentItemFactoryTest.php | 23 +++++++++------- .../Unit/Component/ComponentItemListTest.php | 4 ++- tests/Unit/Configuration/YamlParserTest.php | 5 ++-- .../Compiler/TwigDocCollectDocsPassTest.php | 18 ++++++------- .../DependencyInjection/ConfigurationTest.php | 4 ++- .../TwigDocExtensionTest.php | 4 ++- tests/Unit/Service/CategoryServiceTest.php | 10 ++++--- 30 files changed, 147 insertions(+), 84 deletions(-) diff --git a/src/Cache/ComponentsWarmer.php b/src/Cache/ComponentsWarmer.php index 68068c2..1596ba7 100644 --- a/src/Cache/ComponentsWarmer.php +++ b/src/Cache/ComponentsWarmer.php @@ -1,14 +1,19 @@ container->get('twig_doc.service.component'); diff --git a/src/Component/ComponentInvalid.php b/src/Component/ComponentInvalid.php index 740e9eb..3395de4 100644 --- a/src/Component/ComponentInvalid.php +++ b/src/Component/ComponentInvalid.php @@ -9,11 +9,11 @@ /** * @codeCoverageIgnore */ -class ComponentInvalid +readonly class ComponentInvalid { public function __construct( - public readonly ConstraintViolationList $violationList, - public readonly array $originalConfig + public ConstraintViolationList $violationList, + public array $originalConfig ) { } } diff --git a/src/Component/ComponentItem.php b/src/Component/ComponentItem.php index 04fc317..9d529d1 100644 --- a/src/Component/ComponentItem.php +++ b/src/Component/ComponentItem.php @@ -13,21 +13,29 @@ class ComponentItem { #[Assert\NotBlank] private string $name; + #[Assert\NotBlank] private string $title; + #[Assert\NotBlank] private string $description; + #[Assert\Type('array')] private array $tags; + #[Assert\Type('array')] private array $parameters; + #[Assert\Type('array')] private array $variations; + #[Assert\Valid] private ComponentCategory $category; + #[Assert\Length(max: 4096)] #[Assert\NotBlank] private string $projectPath; + #[Assert\Length(max: 4096)] #[Assert\NotBlank] private string $renderPath; diff --git a/src/Component/ComponentItemFactory.php b/src/Component/ComponentItemFactory.php index 146338c..f584db0 100644 --- a/src/Component/ComponentItemFactory.php +++ b/src/Component/ComponentItemFactory.php @@ -9,12 +9,15 @@ use Symfony\Component\Validator\ConstraintViolationList; use Symfony\Component\Validator\Validator\ValidatorInterface; -class ComponentItemFactory +readonly class ComponentItemFactory { - public function __construct(private readonly ValidatorInterface $validator, private readonly CategoryService $categoryService) + public function __construct(private ValidatorInterface $validator, private CategoryService $categoryService) { } + /** + * @throws InvalidComponentConfigurationException + */ public function create(array $data): ComponentItem { $item = $this->createItem($data); @@ -28,7 +31,7 @@ public function create(array $data): ComponentItem isset($data['sub_category']) ? 'sub_category' : 'category', $data['sub_category'] ?? $data['category'], implode(', ', array_keys($this->categoryService->getCategories())), - implode(', ', array_map(fn (ComponentCategory $category) => $category->getName(), $this->categoryService->getSubCategories())) + implode(', ', array_map(static fn (ComponentCategory $category) => $category->getName(), $this->categoryService->getSubCategories())) ) ); throw new InvalidComponentConfigurationException($violations); @@ -68,12 +71,14 @@ public function getParamsFromVariables(array $variables): array foreach ($variables as $dotted) { $keys = explode('.', $dotted); $c = &$r[array_shift($keys)]; + foreach ($keys as $key) { if (isset($c[$key]) && $c[$key] === true) { $c[$key] = []; } $c = &$c[$key]; } + if ($c === null) { $c = 'Scalar'; } diff --git a/src/Component/ComponentItemList.php b/src/Component/ComponentItemList.php index 24de966..72fa073 100644 --- a/src/Component/ComponentItemList.php +++ b/src/Component/ComponentItemList.php @@ -1,5 +1,7 @@ sortableFields)) { + if (!\in_array($field, $this->sortableFields, true)) { throw new \InvalidArgumentException(sprintf('field "%s" is not sortable', $field)); } @@ -52,13 +54,15 @@ public function sort(string $field, string $direction = self::SORT_ASC): void public function filter(string $query, ?string $type): self { $components = []; + switch ($type) { case 'category': $components = array_filter( $this->getArrayCopy(), - function (ComponentItem $item) use ($query) { + static function (ComponentItem $item) use ($query) { $category = $item->getCategory()->getName(); $parent = $item->getCategory()->getParent(); + while ($parent !== null) { $category = $parent->getName(); $parent = $parent->getParent(); @@ -72,14 +76,14 @@ function (ComponentItem $item) use ($query) { case 'sub_category': $components = array_filter( $this->getArrayCopy(), - fn (ComponentItem $item) => $item->getCategory()->getParent() !== null + static fn (ComponentItem $item) => $item->getCategory()->getParent() !== null && strtolower($item->getCategory()->getName()) === strtolower($query) ); break; case 'tags': $tags = array_map('trim', explode(',', strtolower($query))); - $components = array_filter($this->getArrayCopy(), function (ComponentItem $item) use ($tags) { + $components = array_filter($this->getArrayCopy(), static function (ComponentItem $item) use ($tags) { return array_intersect($tags, array_map('strtolower', $item->getTags())) !== []; }); @@ -87,13 +91,13 @@ function (ComponentItem $item) use ($query) { case 'name': $components = array_filter( $this->getArrayCopy(), - fn (ComponentItem $item) => str_contains(strtolower($item->getName()), strtolower($query)) + static fn (ComponentItem $item) => str_contains(strtolower($item->getName()), strtolower($query)) ); break; default: - foreach (['category', 'sub_category', 'tags', 'name'] as $type) { - $components = array_merge($components, (array) $this->filter($query, $type)); + foreach (['category', 'sub_category', 'tags', 'name'] as $componentType) { + $components = array_merge($components, (array) $this->filter($query, $componentType)); } break; diff --git a/src/Configuration/ParserInterface.php b/src/Configuration/ParserInterface.php index 4288eff..a454a58 100644 --- a/src/Configuration/ParserInterface.php +++ b/src/Configuration/ParserInterface.php @@ -1,5 +1,7 @@ valid()) { $line = $fileObject->current(); + if (empty(trim($line))) { $fileObject->next(); continue; } + if ($firstLineDetected === false) { $firstLineDetected = true; // check for whitespaces at the beginning @@ -39,6 +42,7 @@ private function fixIndentation(string $content): string } $indentationWhitespace = $matches[1]; } + $line = substr($line, \strlen($indentationWhitespace)); $lines[] = $line; $fileObject->next(); diff --git a/src/Controller/TwigDocController.php b/src/Controller/TwigDocController.php index cbed517..b2e9694 100644 --- a/src/Controller/TwigDocController.php +++ b/src/Controller/TwigDocController.php @@ -11,12 +11,12 @@ use Symfony\Component\HttpKernel\Profiler\Profiler; use Twig\Environment; -class TwigDocController +readonly class TwigDocController { public function __construct( - private readonly Environment $twig, - private readonly ComponentService $componentService, - private readonly ?Profiler $profiler = null + private Environment $twig, + private ComponentService $componentService, + private ?Profiler $profiler = null ) { } diff --git a/src/DependencyInjection/Compiler/TwigDocCollectDocsPass.php b/src/DependencyInjection/Compiler/TwigDocCollectDocsPass.php index 7476460..a783adf 100644 --- a/src/DependencyInjection/Compiler/TwigDocCollectDocsPass.php +++ b/src/DependencyInjection/Compiler/TwigDocCollectDocsPass.php @@ -1,5 +1,7 @@ hasExtension('twig_doc')) { return; } + $config = $container->getParameter('twig_doc.config'); $directories = $this->resolveDirectories($container, $config['directories']); $container->getParameterBag()->remove('twig_doc.config'); @@ -51,9 +54,10 @@ public function process(ContainerBuilder $container): void $filename = $file->getFilename(); $componentName = substr($filename, 0, strpos($filename, '.')); - if (array_filter($componentConfig, fn (array $data) => $data['name'] === $componentName)) { - throw new InvalidConfigException(sprintf('component "%s" is configured twice, please configure either directly in the template or the general bundle configuration', $componentName)); + if (array_filter($componentConfig, static fn (array $data) => $data['name'] === $componentName)) { + throw new InvalidConfigException(sprintf('Component "%s" is configured twice, please configure either directly in the template or the general bundle configuration', $componentName)); } + $itemConfig = [ 'name' => $componentName, 'path' => str_replace($projectDir.'/', '', $file->getRealPath()), @@ -69,7 +73,6 @@ public function process(ContainerBuilder $container): void private function parseDoc(SplFileInfo $file, string $docIdentifier): ?array { $content = $file->getContents(); - $pattern = sprintf("/\{#%s\s(.*)%s#}/s", $docIdentifier, $docIdentifier); preg_match($pattern, $content, $matches); @@ -84,10 +87,10 @@ private function parseDoc(SplFileInfo $file, string $docIdentifier): ?array private function enrichComponentsConfig(ContainerBuilder $container, array $directories, array $components): array { foreach ($components as &$component) { - if (!isset($component['path'])) { - $component['path'] = str_replace($container->getParameter('kernel.project_dir').'/', '', $this->getTemplatePath($component['name'], $directories)); + if (!isset($component['path']) && $templatePath = $this->getTemplatePath($component['name'], $directories)) { + $component['path'] = str_replace($container->getParameter('kernel.project_dir').'/', '', $templatePath); } - if (!isset($component['renderPath'])) { + if (!isset($component['renderPath']) && isset($component['path'])) { $component['renderPath'] = str_replace($container->getParameter('twig.default_path').'/', '', $component['path']); } } @@ -98,8 +101,7 @@ private function enrichComponentsConfig(ContainerBuilder $container, array $dire private function resolveDirectories(ContainerBuilder $container, array $directories): array { $directories[] = $container->getParameter('twig.default_path').'/components'; - - $directories = array_map(fn (string $dir) => $container->getParameterBag()->resolveValue($dir), $directories); + $directories = array_map(static fn (string $dir) => $container->getParameterBag()->resolveValue($dir), $directories); foreach ($directories as $idx => $dir) { if (!is_dir($dir)) { @@ -113,9 +115,7 @@ private function resolveDirectories(ContainerBuilder $container, array $director private function getTemplatePath(string $name, array $directories): ?string { $template = sprintf('%s.html.twig', $name); - $finder = new Finder(); - $files = $finder->in($directories)->files()->filter(fn (SplFileInfo $file) => $file->getFilename() === $template); if ($files->count() > 1) { @@ -128,6 +128,6 @@ private function getTemplatePath(string $name, array $directories): ?string $files->getIterator()->rewind(); - return $files->getIterator()->current(); + return $files->getIterator()->current()?->__toString(); } } diff --git a/src/DependencyInjection/Configuration.php b/src/DependencyInjection/Configuration.php index 14ead37..a21aeb8 100644 --- a/src/DependencyInjection/Configuration.php +++ b/src/DependencyInjection/Configuration.php @@ -1,5 +1,7 @@ subCategories, fn (ComponentCategory $category) => $category->getParent() === $mainCategory); + return array_filter($this->subCategories, static fn (ComponentCategory $category) => $category->getParent() === $mainCategory); } return $this->subCategories; diff --git a/src/Service/ComponentService.php b/src/Service/ComponentService.php index 0f7be91..f45505a 100644 --- a/src/Service/ComponentService.php +++ b/src/Service/ComponentService.php @@ -12,14 +12,14 @@ use Qossmic\TwigDocBundle\Exception\InvalidComponentConfigurationException; use Symfony\Contracts\Cache\CacheInterface; -class ComponentService +readonly class ComponentService { public function __construct( - private readonly ComponentItemFactory $itemFactory, - private readonly array $componentsConfig, - private readonly CacheInterface $cache, - private readonly array $breakpointConfig, - private readonly int $configReadTime = 0 + private ComponentItemFactory $itemFactory, + private array $componentsConfig, + private CacheInterface $cache, + private array $breakpointConfig, + private int $configReadTime = 0 ) { } @@ -94,7 +94,7 @@ public function getInvalidComponents(): array public function getComponent(string $name): ?ComponentItem { - return array_values(array_filter((array) $this->getComponents(), fn (ComponentItem $c) => $c->getName() === $name))[0] ?? null; + return array_values(array_filter((array) $this->getComponents(), static fn (ComponentItem $c) => $c->getName() === $name))[0] ?? null; } public function getBreakpoints(): array diff --git a/templates/blocks/page_blocks.html.twig b/templates/blocks/page_blocks.html.twig index 9951789..e44f0fc 100644 --- a/templates/blocks/page_blocks.html.twig +++ b/templates/blocks/page_blocks.html.twig @@ -37,7 +37,6 @@ {% block body %}
- {% include '@TwigDoc/component/_search.html.twig' %} {% if not components %} diff --git a/templates/component/_invalid_component.html.twig b/templates/component/_invalid_component.html.twig index 68dc9b5..aa6fcee 100644 --- a/templates/component/_invalid_component.html.twig +++ b/templates/component/_invalid_component.html.twig @@ -2,7 +2,7 @@

{{ component.originalConfig.name }}

Path

{{ component.originalConfig.path ?? 'UNKNOWN PATH' }}

-

Error-Details:

+

Error-Details:

{{ component.violationList }}

@@ -24,20 +24,20 @@ {% for tag in component.originalConfig.tags %} {% if loop.first %}
    - {% endif %} + {% endif %}
  • {{ tag }}
  • {% if loop.last %} -
+ {% endif %} {% endfor %}

Variations:

{% for key, value in variation %} {% if loop.first %}
    - {% endif %} + {% endif %}
  • {{ key }}: {{ value }}
  • {% if loop.last %} -
+ {% endif %} {% endfor %}
diff --git a/templates/component/_parameter.html.twig b/templates/component/_parameter.html.twig index 074cc2c..a6f1a6f 100644 --- a/templates/component/_parameter.html.twig +++ b/templates/component/_parameter.html.twig @@ -1,7 +1,7 @@ {% if parameter is iterable %}
    {% for key, value in parameter %} -
  • {{ key }}: {% include '@TwigDoc/component/_parameter.html.twig' with {parameter: value} %}
  • +
  • {{ key }}: {% include '@TwigDoc/component/_parameter.html.twig' with {parameter: value} %}
  • {% endfor %}
{% else %} diff --git a/templates/component/_viewport.html.twig b/templates/component/_viewport.html.twig index e24cbd5..2c2b5a4 100644 --- a/templates/component/_viewport.html.twig +++ b/templates/component/_viewport.html.twig @@ -1,6 +1,7 @@
-
diff --git a/templates/pages/invalid_components.html.twig b/templates/pages/invalid_components.html.twig index f05bd7e..eb13d41 100644 --- a/templates/pages/invalid_components.html.twig +++ b/templates/pages/invalid_components.html.twig @@ -1,4 +1,4 @@ -{% extends'@TwigDoc/documentation.html.twig' %} +{% extends '@TwigDoc/documentation.html.twig' %} {% block body %}

Invalid Components

diff --git a/tests/Functional/Cache/ComponentsWarmerTest.php b/tests/Functional/Cache/ComponentsWarmerTest.php index 600e90a..edaeb9d 100644 --- a/tests/Functional/Cache/ComponentsWarmerTest.php +++ b/tests/Functional/Cache/ComponentsWarmerTest.php @@ -1,5 +1,7 @@ createMock(ContainerInterface::class)); static::assertTrue($warmer->isOptional()); } diff --git a/tests/Functional/Controller/TwigDocControllerTest.php b/tests/Functional/Controller/TwigDocControllerTest.php index 0158ae6..a6c080e 100644 --- a/tests/Functional/Controller/TwigDocControllerTest.php +++ b/tests/Functional/Controller/TwigDocControllerTest.php @@ -1,5 +1,7 @@ get('validator'), static::getContainer()->get('twig_doc.service.category') ); - self::expectException($expectedExceptionClass); + $this->expectException($expectedExceptionClass); $service->create($componentData); } diff --git a/tests/Functional/Service/ComponentServiceTest.php b/tests/Functional/Service/ComponentServiceTest.php index 56951f1..666a2e8 100644 --- a/tests/Functional/Service/ComponentServiceTest.php +++ b/tests/Functional/Service/ComponentServiceTest.php @@ -1,5 +1,7 @@ get(ComponentService::class); diff --git a/tests/Functional/Twig/TwigDocExtensionTest.php b/tests/Functional/Twig/TwigDocExtensionTest.php index cd17cd0..ac18fe3 100644 --- a/tests/Functional/Twig/TwigDocExtensionTest.php +++ b/tests/Functional/Twig/TwigDocExtensionTest.php @@ -1,5 +1,7 @@ getComponentCategoryMock($componentData['category'], $componentData['sub_category'] ?? null); - $categoryServiceMock = static::createMock(CategoryService::class); + $categoryServiceMock = $this->createMock(CategoryService::class); $categoryServiceMock ->method('getCategory') ->with($componentData['category']) ->willReturn($componentCategoryMock) ; - $validatorMock = static::createMock(ValidatorInterface::class); + $validatorMock = $this->createMock(ValidatorInterface::class); $validatorMock->method('validate') ->willReturn(new ConstraintViolationList()); @@ -42,14 +44,14 @@ public function testValidComponent(array $componentData): void public function testInvalidCategory() { - static::expectException(InvalidComponentConfigurationException::class); + $this->expectException(InvalidComponentConfigurationException::class); - $categoryServiceMock = static::createMock(CategoryService::class); + $categoryServiceMock = $this->createMock(CategoryService::class); $categoryServiceMock ->method('getCategory') ->willReturn(null) ; - $validatorMock = static::createMock(ValidatorInterface::class); + $validatorMock = $this->createMock(ValidatorInterface::class); $componentItemFactory = new ComponentItemFactory($validatorMock, $categoryServiceMock); @@ -65,8 +67,8 @@ public function testGetParamsFromVariables(): void ]; $componentItemFactory = new ComponentItemFactory( - static::createMock(ValidatorInterface::class), - static::createMock(CategoryService::class) + $this->createMock(ValidatorInterface::class), + $this->createMock(CategoryService::class) ); $result = $componentItemFactory->getParamsFromVariables($variables); @@ -147,14 +149,17 @@ public static function getValidComponents(): iterable private function getComponentCategoryMock(string $category, ?string $subCategory = null): ComponentCategory { - $componentCategoryMock = static::createMock(ComponentCategory::class); + $componentCategoryMock = $this->createMock(ComponentCategory::class); $componentCategoryMock->method('getName') ->willReturn($subCategory ?? $category); + $parentMock = null; + if ($subCategory) { - $parentMock = static::createMock(ComponentCategory::class); + $parentMock = $this->createMock(ComponentCategory::class); $parentMock->method('getName')->willReturn($category); } + $componentCategoryMock->method('getParent') ->willReturn($parentMock); diff --git a/tests/Unit/Component/ComponentItemListTest.php b/tests/Unit/Component/ComponentItemListTest.php index dce80e4..88ccc28 100644 --- a/tests/Unit/Component/ComponentItemListTest.php +++ b/tests/Unit/Component/ComponentItemListTest.php @@ -1,5 +1,7 @@ expectException(\InvalidArgumentException::class); $list = new ComponentItemList([]); diff --git a/tests/Unit/Configuration/YamlParserTest.php b/tests/Unit/Configuration/YamlParserTest.php index 5a76102..6345914 100644 --- a/tests/Unit/Configuration/YamlParserTest.php +++ b/tests/Unit/Configuration/YamlParserTest.php @@ -1,5 +1,7 @@ expectException(ParseException::class); $yaml = " key: \nyaml ain't markup language"; $parser = new YamlParser(); - $parser->parse($yaml); } diff --git a/tests/Unit/DependencyInjection/Compiler/TwigDocCollectDocsPassTest.php b/tests/Unit/DependencyInjection/Compiler/TwigDocCollectDocsPassTest.php index 8bacbfc..7572243 100644 --- a/tests/Unit/DependencyInjection/Compiler/TwigDocCollectDocsPassTest.php +++ b/tests/Unit/DependencyInjection/Compiler/TwigDocCollectDocsPassTest.php @@ -1,5 +1,7 @@ process($container); static::assertTrue(true); @@ -40,7 +41,7 @@ public function testProcess(): void static::assertCount(2, $service->getArgument('$componentsConfig')); } - public function testProcessNotEnrichingPathsForMissingTemplate() + public function testProcessNotEnrichingPathsForMissingTemplate(): void { $container = $this->getContainer(componentsConfig: [ [ @@ -49,7 +50,6 @@ public function testProcessNotEnrichingPathsForMissingTemplate() ]); $pass = new TwigDocCollectDocsPass(new YamlParser()); - $pass->process($container); $definition = $container->getDefinition('twig_doc.service.component'); @@ -58,7 +58,7 @@ public function testProcessNotEnrichingPathsForMissingTemplate() static::assertEmpty($definition->getArgument('$componentsConfig')[0]['renderPath']); } - public function testProcessNotEnrichingPathsForAmbiguousTemplate() + public function testProcessNotEnrichingPathsForAmbiguousTemplate(): void { $container = $this->getContainer(componentsConfig: [ [ @@ -72,7 +72,6 @@ public function testProcessNotEnrichingPathsForAmbiguousTemplate() ]); $pass = new TwigDocCollectDocsPass(new YamlParser()); - $pass->process($container); $definition = $container->getDefinition('twig_doc.service.component'); @@ -83,10 +82,11 @@ public function testProcessNotEnrichingPathsForAmbiguousTemplate() static::assertEmpty($definition->getArgument('$componentsConfig')[1]['renderPath']); } - public function testProcessThrowsExceptionForInvalidConfiguration() + public function testProcessThrowsExceptionForInvalidConfiguration(): void { - static::expectException(InvalidConfigException::class); - static::expectExceptionMessage(sprintf('component "%s" is configured twice, please configure either directly in the template or the general bundle configuration', 'Button')); + $this->expectException(InvalidConfigException::class); + $this->expectExceptionMessage(sprintf('Component "%s" is configured twice, please configure either directly in the template or the general bundle configuration', 'Button')); + $container = $this->getContainer([ [ 'name' => 'Button', diff --git a/tests/Unit/DependencyInjection/ConfigurationTest.php b/tests/Unit/DependencyInjection/ConfigurationTest.php index c6d9776..fff3fd9 100644 --- a/tests/Unit/DependencyInjection/ConfigurationTest.php +++ b/tests/Unit/DependencyInjection/ConfigurationTest.php @@ -1,5 +1,7 @@ expectException(InvalidConfigException::class); new CategoryService($config); } - public function testGetCategories() + public function testGetCategories(): void { $service = new CategoryService([['name' => 'Category']]); @@ -56,7 +58,7 @@ public function testGetCategories() static::assertContainsOnlyInstancesOf(ComponentCategory::class, $categories); } - public function testGetCategoryReturnsNullForUnknownCategory() + public function testGetCategoryReturnsNullForUnknownCategory(): void { $service = new CategoryService([['name' => 'Category']]);