diff --git a/psalm.xml b/psalm.xml index 81de9bc5f..2f64f6e27 100644 --- a/psalm.xml +++ b/psalm.xml @@ -116,6 +116,13 @@ + + + + + + + @@ -179,6 +186,13 @@ + + + + + + + @@ -320,6 +334,13 @@ + + + + + + + diff --git a/src/Bundle/DependencyInjection/Configuration.php b/src/Bundle/DependencyInjection/Configuration.php index 6de235407..7da7477d5 100644 --- a/src/Bundle/DependencyInjection/Configuration.php +++ b/src/Bundle/DependencyInjection/Configuration.php @@ -39,6 +39,9 @@ public function getConfigTreeBuilder(): TreeBuilder ->arrayNode('mapping') ->addDefaultsIfNotSet() ->children() + ->arrayNode('imports') + ->prototype('scalar')->end() + ->end() ->arrayNode('paths') ->prototype('scalar')->end() ->end() diff --git a/src/Bundle/Resources/config/services/metadata/resource_class_list.xml b/src/Bundle/Resources/config/services/metadata/resource_class_list.xml index c03112a2a..2f2a293eb 100644 --- a/src/Bundle/Resources/config/services/metadata/resource_class_list.xml +++ b/src/Bundle/Resources/config/services/metadata/resource_class_list.xml @@ -22,5 +22,15 @@ %sylius.resource.mapping% + + + + + + diff --git a/src/Bundle/Resources/config/services/metadata/resource_metadata_collection.xml b/src/Bundle/Resources/config/services/metadata/resource_metadata_collection.xml index 49d85ba0a..b171853d9 100644 --- a/src/Bundle/Resources/config/services/metadata/resource_metadata_collection.xml +++ b/src/Bundle/Resources/config/services/metadata/resource_metadata_collection.xml @@ -17,12 +17,43 @@ - + + %sylius.resource.mapping% + + + + + %sylius.resource.mapping% + + + + + + + + + + + + + + + + + + + - - getWrappedObject(), new OperationRouteNameFactory(), - 'symfony', ), ); } diff --git a/src/Component/src/Metadata/Extractor/MetadataExtractorInterface.php b/src/Component/src/Metadata/Extractor/MetadataExtractorInterface.php new file mode 100644 index 000000000..4c8dd48b2 --- /dev/null +++ b/src/Component/src/Metadata/Extractor/MetadataExtractorInterface.php @@ -0,0 +1,24 @@ +getResourceFilePaths() as $filePath) { + if (!is_readable($filePath)) { + continue; + } + + $resource = $this->getPHPFileClosure($filePath)(); + + if (!$resource instanceof ResourceMetadata) { + continue; + } + + $resourceReflection = new \ReflectionClass($resource); + + foreach ($resourceReflection->getProperties() as $property) { + $property->setAccessible(true); + $resolvedValue = $this->resolve($property->getValue($resource)); + $property->setValue($resource, $resolvedValue); + } + + $metadata[] = $resource; + } + + return $metadata; + } + + private function getResourceFilePaths(): iterable + { + foreach ($this->createFinder() as $file) { + yield $file->getPathname(); + } + } + + private function createFinder(): Finder + { + $finder = (new Finder())->files(); + + foreach ($this->resourceMapping['imports'] ?? [] as $path) { + $finder->in($path); + } + + return $finder->files(); + } + + /** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ + private function getPHPFileClosure(string $filePath): \Closure + { + return \Closure::bind(function () use ($filePath): mixed { + return require $filePath; + }, null, null); + } + + /** + * Recursively replaces placeholders with the service container parameters. + * + * @see https://github.com/symfony/symfony/blob/6fec32c/src/Symfony/Bundle/FrameworkBundle/Routing/Router.php + * + * @param mixed $value The source which might contain "%placeholders%" + * + * @throws \RuntimeException When a container value is not a string or a numeric value + * + * @return mixed The source with the placeholders replaced by the container + * parameters. Arrays are resolved recursively. + */ + private function resolve(mixed $value): mixed + { + $container = $this->container; + + if (null === $container) { + return $value; + } + + if (\is_array($value)) { + foreach ($value as $key => $val) { + $value[$key] = $this->resolve($val); + } + + return $value; + } + + if (!\is_string($value)) { + return $value; + } + + $escapedValue = preg_replace_callback('/%%|%([^%\s]++)%/', function ($match) use ($value, $container) { + $parameter = $match[1] ?? null; + + // skip %% + if (!isset($parameter)) { + return '%%'; + } + + if (preg_match('/^env\(\w+\)$/', $parameter)) { + throw new \RuntimeException(\sprintf('Using "%%%s%%" is not allowed in routing configuration.', $parameter)); + } + + if (\array_key_exists($parameter, $this->collectedParameters)) { + return $this->collectedParameters[$parameter]; + } + + if ($container instanceof SymfonyContainerInterface) { + $resolved = $container->getParameter($parameter); + } else { + $resolved = $container->get($parameter); + } + + if (\is_string($resolved) || is_numeric($resolved)) { + $this->collectedParameters[$parameter] = $resolved; + + return (string) $resolved; + } + + throw new \RuntimeException(\sprintf('The container parameter "%s", used in the resource configuration value "%s", must be a string or numeric, but it is of type %s.', $parameter, $value, \gettype($resolved))); + }, $value); + + return str_replace('%%', '%', $escapedValue ?? ''); + } +} diff --git a/src/Component/src/Metadata/Operation/CustomPhpFileOperationUpdater.php b/src/Component/src/Metadata/Operation/CustomPhpFileOperationUpdater.php new file mode 100644 index 000000000..faf8df833 --- /dev/null +++ b/src/Component/src/Metadata/Operation/CustomPhpFileOperationUpdater.php @@ -0,0 +1,94 @@ +getResourceFilePaths() as $filePath) { + if (!is_readable($filePath)) { + continue; + } + + $resource = $this->getPHPFileClosure($filePath)(); + + if (!$resource instanceof \Closure) { + continue; + } + + $resourceReflection = new \ReflectionFunction($resource); + + if (1 !== $resourceReflection->getNumberOfParameters()) { + continue; + } + + $firstParameterType = ($resourceReflection->getParameters()[0] ?? null)?->getType(); + + if (!$firstParameterType instanceof \ReflectionNamedType) { + continue; + } + + // Check if the closure parameter is an operation + if (!is_a($firstParameterType->getName(), Operation::class, true)) { + continue; + } + + $operation = $resource($operation); + } + + return $operation; + } + + private function getResourceFilePaths(): iterable + { + foreach ($this->createFinder() as $file) { + yield $file->getPathname(); + } + } + + private function createFinder(): Finder + { + $finder = (new Finder())->files(); + + foreach ($this->resourceMapping['imports'] ?? [] as $path) { + $finder->in($path); + } + + return $finder->files(); + } + + /** + * Scope isolated include. + * + * Prevents access to $this/self from included files. + */ + private function getPHPFileClosure(string $filePath): \Closure + { + return \Closure::bind(function () use ($filePath): mixed { + return require $filePath; + }, null, null); + } +} diff --git a/src/Component/src/Metadata/Operation/OperationUpdaterInterface.php b/src/Component/src/Metadata/Operation/OperationUpdaterInterface.php new file mode 100644 index 000000000..1855c7cd0 --- /dev/null +++ b/src/Component/src/Metadata/Operation/OperationUpdaterInterface.php @@ -0,0 +1,21 @@ +decorated) { + $resourceMetadataCollection = $this->decorated->create($resourceClass); + } $attributes = ClassReflection::getClassAttributes($resourceClass); @@ -77,7 +80,7 @@ private function buildResourceOperations(array $attributes, string $resourceClas /** @var Operation $operation */ foreach ($resource->getOperations() ?? new Operations() as $operation) { - [$key, $operation] = $this->getOperationWithDefaults($resources[$index], $operation); + [$key, $operation] = $this->getOperationWithDefaults($this->operationRouteNameFactory, $this->resourceRegistry, $resources[$index], $operation); $operations[$key] = $operation; } @@ -107,7 +110,7 @@ private function buildResourceOperations(array $attributes, string $resourceClas /** @var Operation $operationAttribute */ $operationAttribute = $attribute->newInstance(); - [$key, $operation] = $this->getOperationWithDefaults($resources[$index], $operationAttribute); + [$key, $operation] = $this->getOperationWithDefaults($this->operationRouteNameFactory, $this->resourceRegistry, $resources[$index], $operationAttribute); $operations = $resources[$index]->getOperations() ?? new Operations(); @@ -117,111 +120,4 @@ private function buildResourceOperations(array $attributes, string $resourceClas return $resources; } - - private function getResourceWithDefaults(string $resourceClass, ResourceMetadata $resource, MetadataInterface $resourceConfiguration): ResourceMetadata - { - $resource = $resource->withClass($resourceClass); - - if (null === $resource->getAlias()) { - $resource = $resource->withAlias($resourceConfiguration->getAlias()); - } - - if (null === $resource->getApplicationName()) { - $resource = $resource->withApplicationName($resourceConfiguration->getApplicationName()); - } - - if (null === $resource->getName()) { - $resource = $resource->withName($resourceConfiguration->getName()); - } - - return $resource; - } - - private function getOperationWithDefaults(ResourceMetadata $resource, Operation $operation): array - { - $resourceConfiguration = $this->resourceRegistry->get($resource->getAlias() ?? ''); - - $operation = $operation->withResource($resource); - - if (null === $resource->getName()) { - $resourceName = $resourceConfiguration->getName(); - - $resource = $resource->withName($resourceName); - $operation = $operation->withResource($resource); - } - - if (null === $resource->getPluralName()) { - $resourcePluralName = $resourceConfiguration->getPluralName(); - - $resource = $resource->withPluralName($resourcePluralName); - $operation = $operation->withResource($resource); - } - - if (null === $operation->getNormalizationContext()) { - $operation = $operation->withNormalizationContext($resource->getNormalizationContext()); - } - - if (null === $operation->getDenormalizationContext()) { - $operation = $operation->withDenormalizationContext($resource->getDenormalizationContext()); - } - - if (null === $operation->getValidationContext()) { - $operation = $operation->withValidationContext($resource->getValidationContext()); - } - - $operation = $operation->withResource($resource); - - if (null === $operation->getRepository()) { - $operation = $operation->withRepository($resourceConfiguration->getServiceId('repository')); - } - - if (null === $operation->getFormType()) { - $formType = $resource->getFormType() ?? $resourceConfiguration->getClass('form'); - $operation = $operation->withFormType($formType); - } - - $formOptions = $this->buildFormOptions($operation, $resourceConfiguration); - $operation = $operation->withFormOptions($formOptions); - - if ($operation instanceof HttpOperation) { - if (null === $operation->getRoutePrefix()) { - $operation = $operation->withRoutePrefix($resource->getRoutePrefix() ?? null); - } - - if (null === $operation->getTwigContextFactory()) { - $operation = $operation->withTwigContextFactory('sylius.twig.context.factory.default'); - } - - if (null === $routeName = $operation->getRouteName()) { - $routeName = $this->operationRouteNameFactory->createRouteName($operation); - $operation = $operation->withRouteName($routeName); - } - - if (null === $operation->getResponder()) { - $operation = $operation->withResponder(Responder::class); - } - - $operation = $operation->withName($routeName); - } - - $operationName = $operation->getName(); - - return [$operationName, $operation]; - } - - private function buildFormOptions(Operation $operation, MetadataInterface $resourceConfiguration): array - { - $formOptions = array_merge( - ['data_class' => $resourceConfiguration->getClass('model')], - $operation->getFormOptions() ?? [], - ); - - $validationGroups = $operation->getValidationContext()['groups'] ?? null; - - if (null !== $validationGroups) { - $formOptions = array_merge(['validation_groups' => $validationGroups], $formOptions); - } - - return $formOptions; - } } diff --git a/src/Component/src/Metadata/Resource/Factory/CustomResourceMetadataCollectionFactory.php b/src/Component/src/Metadata/Resource/Factory/CustomResourceMetadataCollectionFactory.php new file mode 100644 index 000000000..52feaeac1 --- /dev/null +++ b/src/Component/src/Metadata/Resource/Factory/CustomResourceMetadataCollectionFactory.php @@ -0,0 +1,58 @@ +decorated) { + $resourceMetadataCollection = $this->decorated->create($resourceClass); + } + + $newMetadataCollection = new ResourceMetadataCollection(); + + /** @var ResourceMetadata $resourceMetadata */ + foreach ($resourceMetadataCollection as $resourceMetadata) { + $operations = $resourceMetadata->getOperations() ?? new Operations(); + + /** @var Operation $operation */ + foreach ($operations as $operation) { + $operationName = $operation->getName(); + Assert::notNull($operationName); + $operations->add($operationName, $this->metadataUpdater->update($operation)); + } + + $newMetadataCollection[] = $resourceMetadata->withOperations($operations); + } + + return $newMetadataCollection; + } +} diff --git a/src/Component/src/Metadata/Resource/Factory/OperationDefaultsTrait.php b/src/Component/src/Metadata/Resource/Factory/OperationDefaultsTrait.php new file mode 100644 index 000000000..3591f0984 --- /dev/null +++ b/src/Component/src/Metadata/Resource/Factory/OperationDefaultsTrait.php @@ -0,0 +1,142 @@ +withClass($resourceClass); + + if (null === $resource->getAlias()) { + $resource = $resource->withAlias($resourceConfiguration->getAlias()); + } + + if (null === $resource->getApplicationName()) { + $resource = $resource->withApplicationName($resourceConfiguration->getApplicationName()); + } + + if (null === $resource->getName()) { + $resource = $resource->withName($resourceConfiguration->getName()); + } + + return $resource; + } + + private function getOperationWithDefaults( + OperationRouteNameFactory $operationRouteNameFactory, + RegistryInterface $resourceRegistry, + ResourceMetadata $resource, + Operation $operation, + ): array { + $resourceConfiguration = $resourceRegistry->get($resource->getAlias() ?? ''); + + $operation = $operation->withResource($resource); + + if (null === $resource->getName()) { + $resourceName = $resourceConfiguration->getName(); + + $resource = $resource->withName($resourceName); + $operation = $operation->withResource($resource); + } + + if (null === $resource->getPluralName()) { + $resourcePluralName = $resourceConfiguration->getPluralName(); + + $resource = $resource->withPluralName($resourcePluralName); + $operation = $operation->withResource($resource); + } + + if (null === $operation->getNormalizationContext()) { + $operation = $operation->withNormalizationContext($resource->getNormalizationContext()); + } + + if (null === $operation->getDenormalizationContext()) { + $operation = $operation->withDenormalizationContext($resource->getDenormalizationContext()); + } + + if (null === $operation->getValidationContext()) { + $operation = $operation->withValidationContext($resource->getValidationContext()); + } + + $operation = $operation->withResource($resource); + + if (null === $operation->getRepository()) { + $operation = $operation->withRepository($resourceConfiguration->getServiceId('repository')); + } + + if (null === $operation->getFormType()) { + $formType = $resource->getFormType() ?? $resourceConfiguration->getClass('form'); + $operation = $operation->withFormType($formType); + } + + $formOptions = $this->buildFormOptions($operation, $resourceConfiguration); + $operation = $operation->withFormOptions($formOptions); + + if ($operation instanceof HttpOperation) { + if (null === $operation->getRoutePrefix()) { + $operation = $operation->withRoutePrefix($resource->getRoutePrefix() ?? null); + } + + if (null === $operation->getTwigContextFactory()) { + $operation = $operation->withTwigContextFactory('sylius.twig.context.factory.default'); + } + + if (null === $routeName = $operation->getRouteName()) { + $routeName = $operationRouteNameFactory->createRouteName($operation); + $operation = $operation->withRouteName($routeName); + } + + if (null === $operation->getResponder()) { + $operation = $operation->withResponder(Responder::class); + } + + $operation = $operation->withName($routeName); + } + + $operationName = $operation->getName(); + + return [$operationName, $operation]; + } + + private function buildFormOptions(Operation $operation, MetadataInterface $resourceConfiguration): array + { + $formOptions = array_merge( + ['data_class' => $resourceConfiguration->getClass('model')], + $operation->getFormOptions() ?? [], + ); + + $validationGroups = $operation->getValidationContext()['groups'] ?? null; + + if (null !== $validationGroups) { + $formOptions = array_merge(['validation_groups' => $validationGroups], $formOptions); + } + + return $formOptions; + } +} diff --git a/src/Component/src/Metadata/Resource/Factory/PhpFileResourceClassListFactory.php b/src/Component/src/Metadata/Resource/Factory/PhpFileResourceClassListFactory.php new file mode 100644 index 000000000..24d860751 --- /dev/null +++ b/src/Component/src/Metadata/Resource/Factory/PhpFileResourceClassListFactory.php @@ -0,0 +1,51 @@ +decorated) { + foreach ($this->decorated->create() as $resourceClass) { + $classes[$resourceClass] = true; + } + } + + foreach ($this->metadataExtractor->extract() as $resource) { + $resourceClass = $resource->getClass(); + + if (null === $resourceClass) { + continue; + } + + $classes[$resourceClass] = true; + } + + return new ResourceClassList(array_keys($classes)); + } +} diff --git a/src/Component/src/Metadata/Resource/Factory/PhpFileResourceMetadataCollectionFactory.php b/src/Component/src/Metadata/Resource/Factory/PhpFileResourceMetadataCollectionFactory.php new file mode 100644 index 000000000..97acb87f7 --- /dev/null +++ b/src/Component/src/Metadata/Resource/Factory/PhpFileResourceMetadataCollectionFactory.php @@ -0,0 +1,73 @@ +decorated) { + $resourceMetadataCollection = $this->decorated->create($resourceClass); + } + + foreach ($this->metadataExtractor->extract() as $resource) { + if ($resourceClass !== $resource->getClass()) { + continue; + } + + $resourceAlias = $resource->getAlias(); + + if (null !== $resourceAlias) { + $resourceConfiguration = $this->resourceRegistry->get($resource->getAlias() ?? ''); + } else { + $resourceConfiguration = $this->resourceRegistry->getByClass($resourceClass); + } + + $resource = $this->getResourceWithDefaults($resourceClass, $resource, $resourceConfiguration); + + $operations = []; + /** @var Operation $operation */ + foreach ($resource->getOperations() ?? new Operations() as $operation) { + [$key, $operation] = $this->getOperationWithDefaults($this->operationRouteNameFactory, $this->resourceRegistry, $resource, $operation); + $operations[$key] = $operation; + } + + if ($operations) { + $resource = $resource->withOperations(new Operations($operations)); + } + + $resourceMetadataCollection[] = $resource; + } + + return $resourceMetadataCollection; + } +} diff --git a/src/Component/src/Symfony/Routing/Factory/Resource/ResourceRouteCollectionFactory.php b/src/Component/src/Symfony/Routing/Factory/Resource/ResourceRouteCollectionFactory.php index 3c6ee67a0..fee9f6253 100644 --- a/src/Component/src/Symfony/Routing/Factory/Resource/ResourceRouteCollectionFactory.php +++ b/src/Component/src/Symfony/Routing/Factory/Resource/ResourceRouteCollectionFactory.php @@ -39,10 +39,11 @@ public function __construct( public function createRouteCollectionForClass(string $className): RouteCollection { $routeCollection = new RouteCollection(); - $resourceMetadata = $this->resourceMetadataFactory->create($className); + + $resourceMetadataCollection = $this->resourceMetadataFactory->create($className); /** @var ResourceMetadata $resource */ - foreach ($resourceMetadata->getIterator() as $resource) { + foreach ($resourceMetadataCollection->getIterator() as $resource) { $this->createRoutesForResource($routeCollection, $resource); } diff --git a/tests/Application/config/packages/doctrine.yaml b/tests/Application/config/packages/doctrine.yaml index 5c208b673..1ab04b5e0 100644 --- a/tests/Application/config/packages/doctrine.yaml +++ b/tests/Application/config/packages/doctrine.yaml @@ -19,6 +19,11 @@ doctrine: type: attribute dir: '%kernel.project_dir%/src/BoardGameBlog/Domain' prefix: 'App\BoardGameBlog\Domain' + Conference: + is_bundle: false + type: attribute + dir: '%kernel.project_dir%/src/Conference/Entity' + prefix: 'App\Conference\Entity' Subscription: is_bundle: false type: attribute diff --git a/tests/Application/config/services.yaml b/tests/Application/config/services.yaml index e688256a7..b40951a25 100644 --- a/tests/Application/config/services.yaml +++ b/tests/Application/config/services.yaml @@ -96,6 +96,9 @@ services: App\BoardGameBlog\: resource: '../src/BoardGameBlog' + App\Conference\: + resource: '../src/Conference' + App\Subscription\: resource: '../src/Subscription' diff --git a/tests/Application/config/sylius/resources.yaml b/tests/Application/config/sylius/resources.yaml index e4f291993..08b41c935 100644 --- a/tests/Application/config/sylius/resources.yaml +++ b/tests/Application/config/sylius/resources.yaml @@ -1,5 +1,7 @@ sylius_resource: mapping: + imports: + - '%kernel.project_dir%/config/sylius/resources' paths: - '%kernel.project_dir%/src/BoardGameBlog/Infrastructure/Sylius/Resource' - '%kernel.project_dir%/src/Subscription/Entity' @@ -61,3 +63,7 @@ sylius_resource: classes: model: App\Entity\Zone\ZoneMember interface: App\Entity\Zone\ZoneMemberInterface + + app.speaker: + classes: + model: App\Conference\Entity\Speaker diff --git a/tests/Application/config/sylius/resources/custom_speaker_create.php b/tests/Application/config/sylius/resources/custom_speaker_create.php new file mode 100644 index 000000000..c075807e5 --- /dev/null +++ b/tests/Application/config/sylius/resources/custom_speaker_create.php @@ -0,0 +1,26 @@ +getName() + ) { + return $operation; + } + + return $operation->withPath('speakers/register'); +}; diff --git a/tests/Application/config/sylius/resources/speaker.php b/tests/Application/config/sylius/resources/speaker.php new file mode 100644 index 000000000..dff5519be --- /dev/null +++ b/tests/Application/config/sylius/resources/speaker.php @@ -0,0 +1,30 @@ +withRoutePrefix('/admin') + ->withClass(Speaker::class) + ->withSection('admin') + ->withTemplatesDir('crud') + ->withOperations(new Operations([ + new Create(), + new Index(grid: SpeakerGrid::class), + ])) +; diff --git a/tests/Application/config/sylius/resources/speaker_update.php b/tests/Application/config/sylius/resources/speaker_update.php new file mode 100644 index 000000000..5743ce6bd --- /dev/null +++ b/tests/Application/config/sylius/resources/speaker_update.php @@ -0,0 +1,27 @@ +withRoutePrefix('/admin') + ->withClass(Speaker::class) + ->withSection('admin') + ->withTemplatesDir('crud') + ->withOperations(new Operations([ + new Update(), + ])) +; diff --git a/tests/Application/src/Conference/Entity/Speaker.php b/tests/Application/src/Conference/Entity/Speaker.php new file mode 100644 index 000000000..8c8367e2a --- /dev/null +++ b/tests/Application/src/Conference/Entity/Speaker.php @@ -0,0 +1,46 @@ +id; + } + + public function getFullName(): ?string + { + return $this->firstName . ' ' . $this->lastName; + } +} diff --git a/tests/Application/src/Conference/Grid/SpeakerGrid.php b/tests/Application/src/Conference/Grid/SpeakerGrid.php new file mode 100644 index 000000000..b7da216e8 --- /dev/null +++ b/tests/Application/src/Conference/Grid/SpeakerGrid.php @@ -0,0 +1,53 @@ +orderBy('fullName', 'asc') + ->setLimits([10, 25, 50]) + ->addField( + StringField::create('fullName') + ->setLabel('Name') + ->setSortable(true, 'firstName'), + ) + ->addActionGroup( + MainActionGroup::create( + CreateAction::create(), + ), + ) + ; + } + + public function getResourceClass(): string + { + return Speaker::class; + } +} diff --git a/tests/Application/templates/crud/index.html.twig b/tests/Application/templates/crud/index.html.twig index 7e26ad5c0..afc4851ba 100644 --- a/tests/Application/templates/crud/index.html.twig +++ b/tests/Application/templates/crud/index.html.twig @@ -30,11 +30,13 @@ {% for field in definition.enabledFields %} {{ sylius_grid_render_field(grid, field, resource) }} - - {% for action in definition.getEnabledActions('item') %} - {{ sylius_grid_render_action(grid, action, resource) }} - {% endfor %} - + {% if definition.actionGroups.item is defined and definition.getEnabledActions('item')|length > 0 %} + + {% for action in definition.getEnabledActions('item') %} + {{ sylius_grid_render_action(grid, action, resource) }} + {% endfor %} + + {% endif %} {% endfor %} {% endfor %} diff --git a/tests/Bundle/Configuration/ConfigurationTest.php b/tests/Bundle/Configuration/ConfigurationTest.php index 54865c590..0ba04f7ed 100644 --- a/tests/Bundle/Configuration/ConfigurationTest.php +++ b/tests/Bundle/Configuration/ConfigurationTest.php @@ -72,6 +72,7 @@ public function it_has_no_default_mapping_paths(): void [ 'mapping' => [ 'paths' => [], + 'imports' => [], ], ], 'mapping', @@ -92,6 +93,7 @@ public function its_mapping_paths_can_be_customized(): void 'paths' => [ 'path/to/resources', ], + 'imports' => [], ], ], 'mapping', diff --git a/tests/Bundle/DependencyInjection/SyliusResourceExtensionTest.php b/tests/Bundle/DependencyInjection/SyliusResourceExtensionTest.php index 11a4e2c50..021631cc4 100644 --- a/tests/Bundle/DependencyInjection/SyliusResourceExtensionTest.php +++ b/tests/Bundle/DependencyInjection/SyliusResourceExtensionTest.php @@ -126,6 +126,7 @@ public function it_registers_parameter_for_paths(): void 'paths' => [ __DIR__ . '/Dummy', ], + 'imports' => [], ]); }