From bf7f42ac41609b50fa7dbc21cde8db3a08cdc066 Mon Sep 17 00:00:00 2001 From: Joanis Rouanet Date: Sun, 28 Nov 2021 17:16:42 +0100 Subject: [PATCH 01/15] First commit --- src/Dto/FilterDto.php | 8 ++++++ src/Factory/FormFactory.php | 49 ++++++++++++++++++++++++++++++++++++- src/Filter/FilterTrait.php | 2 +- 3 files changed, 57 insertions(+), 2 deletions(-) diff --git a/src/Dto/FilterDto.php b/src/Dto/FilterDto.php index 96e66633ae..0edf66640f 100644 --- a/src/Dto/FilterDto.php +++ b/src/Dto/FilterDto.php @@ -22,6 +22,14 @@ public function __construct() $this->formTypeOptions = KeyValueStore::new(); } + /** + * This method escapes dots from the property name. + */ + public function __toString(): string + { + return str_replace('.', '_', $this->propertyName); + } + public function getFqcn(): ?string { return $this->fqcn; diff --git a/src/Factory/FormFactory.php b/src/Factory/FormFactory.php index 8ba6934494..516023286e 100644 --- a/src/Factory/FormFactory.php +++ b/src/Factory/FormFactory.php @@ -63,9 +63,56 @@ public function createFiltersForm(FilterCollection $filters, Request $request): $filtersForm = $this->symfonyFormFactory->createNamed('filters', FiltersFormType::class, null, [ 'method' => 'GET', 'action' => $request->query->get(EA::REFERRER, ''), - 'ea_filters' => $filters, + 'ea_filters' => $this->normalizeFilters($filters), ]); return $filtersForm->handleRequest($request); } + + /** + * @internal + * + * This method is called to normalize embedded property filters. + */ + private function normalizeFilters(FilterCollection $filters): FilterCollection + { + $normalizedFilters = FilterCollection::new(); + + foreach($filters as $filterDto) { + $propertyName = $filterDto->getProperty(); + + // If the target property does NOT contain dots (no embedded property) + if(false === strpos($propertyName, '.')) { + // We change nothing. + $normalizedFilters[$propertyName] = $filterDto; + + continue; + } + + // We clone the filter just for the form + $normalizedFilterDto = clone $filterDto; + $propertyPath = $filterDto->getFormTypeOption('property_path'); + + if (!$propertyPath) { + // The property accessor sets values on array. + // So we must replace object path to array path. + $paths = explode('.', $filterDto->getProperty()); + foreach($paths as $key => $path) { + $paths[$key] = "[$path]"; + } + + // We set the property path as form option + $normalizedFilterDto->setFormTypeOption('property_path', implode('', $paths)); + } + + // For the property name, we must replace dots by underscore to be allowed from Symfony form + // AND match with normalized filter property name from the method FilterDto::__toString() + $propertyName = str_replace('.', '_', $filterDto->getProperty()); + $normalizedFilterDto->setProperty($propertyName); + + $normalizedFilters[$propertyName] = $normalizedFilterDto; + } + + return $normalizedFilters; + } } diff --git a/src/Filter/FilterTrait.php b/src/Filter/FilterTrait.php index c89c37344e..508215fcc2 100644 --- a/src/Filter/FilterTrait.php +++ b/src/Filter/FilterTrait.php @@ -28,7 +28,7 @@ private function __construct() public function __toString(): string { - return $this->dto->getProperty(); + return (string) $this->dto; } public function setFilterFqcn(string $fqcn): self From 12588bdc16b40d617570e919814147023cb13f77 Mon Sep 17 00:00:00 2001 From: Joanis Rouanet Date: Sun, 28 Nov 2021 18:01:52 +0100 Subject: [PATCH 02/15] CS fixer --- src/Factory/FormFactory.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Factory/FormFactory.php b/src/Factory/FormFactory.php index 516023286e..c6fa32110b 100644 --- a/src/Factory/FormFactory.php +++ b/src/Factory/FormFactory.php @@ -72,17 +72,17 @@ public function createFiltersForm(FilterCollection $filters, Request $request): /** * @internal * - * This method is called to normalize embedded property filters. + * This method is called to normalize embedded property filters */ private function normalizeFilters(FilterCollection $filters): FilterCollection { $normalizedFilters = FilterCollection::new(); - foreach($filters as $filterDto) { + foreach ($filters as $filterDto) { $propertyName = $filterDto->getProperty(); // If the target property does NOT contain dots (no embedded property) - if(false === strpos($propertyName, '.')) { + if (false === strpos($propertyName, '.')) { // We change nothing. $normalizedFilters[$propertyName] = $filterDto; @@ -97,7 +97,7 @@ private function normalizeFilters(FilterCollection $filters): FilterCollection // The property accessor sets values on array. // So we must replace object path to array path. $paths = explode('.', $filterDto->getProperty()); - foreach($paths as $key => $path) { + foreach ($paths as $key => $path) { $paths[$key] = "[$path]"; } From e92b2903e923ebdbf4015a7fbc5d1d4084f5094e Mon Sep 17 00:00:00 2001 From: Joanis Rouanet Date: Tue, 14 Dec 2021 15:56:18 +0100 Subject: [PATCH 03/15] Replaces changes by a configurator Simplify handling --- src/Dto/FilterDto.php | 8 --- src/Factory/FormFactory.php | 49 +------------------ .../EmbeddedFilterConfigurator.php | 35 +++++++++++++ src/Filter/FilterTrait.php | 2 +- 4 files changed, 37 insertions(+), 57 deletions(-) create mode 100644 src/Filter/Configurator/EmbeddedFilterConfigurator.php diff --git a/src/Dto/FilterDto.php b/src/Dto/FilterDto.php index 0edf66640f..96e66633ae 100644 --- a/src/Dto/FilterDto.php +++ b/src/Dto/FilterDto.php @@ -22,14 +22,6 @@ public function __construct() $this->formTypeOptions = KeyValueStore::new(); } - /** - * This method escapes dots from the property name. - */ - public function __toString(): string - { - return str_replace('.', '_', $this->propertyName); - } - public function getFqcn(): ?string { return $this->fqcn; diff --git a/src/Factory/FormFactory.php b/src/Factory/FormFactory.php index c6fa32110b..8ba6934494 100644 --- a/src/Factory/FormFactory.php +++ b/src/Factory/FormFactory.php @@ -63,56 +63,9 @@ public function createFiltersForm(FilterCollection $filters, Request $request): $filtersForm = $this->symfonyFormFactory->createNamed('filters', FiltersFormType::class, null, [ 'method' => 'GET', 'action' => $request->query->get(EA::REFERRER, ''), - 'ea_filters' => $this->normalizeFilters($filters), + 'ea_filters' => $filters, ]); return $filtersForm->handleRequest($request); } - - /** - * @internal - * - * This method is called to normalize embedded property filters - */ - private function normalizeFilters(FilterCollection $filters): FilterCollection - { - $normalizedFilters = FilterCollection::new(); - - foreach ($filters as $filterDto) { - $propertyName = $filterDto->getProperty(); - - // If the target property does NOT contain dots (no embedded property) - if (false === strpos($propertyName, '.')) { - // We change nothing. - $normalizedFilters[$propertyName] = $filterDto; - - continue; - } - - // We clone the filter just for the form - $normalizedFilterDto = clone $filterDto; - $propertyPath = $filterDto->getFormTypeOption('property_path'); - - if (!$propertyPath) { - // The property accessor sets values on array. - // So we must replace object path to array path. - $paths = explode('.', $filterDto->getProperty()); - foreach ($paths as $key => $path) { - $paths[$key] = "[$path]"; - } - - // We set the property path as form option - $normalizedFilterDto->setFormTypeOption('property_path', implode('', $paths)); - } - - // For the property name, we must replace dots by underscore to be allowed from Symfony form - // AND match with normalized filter property name from the method FilterDto::__toString() - $propertyName = str_replace('.', '_', $filterDto->getProperty()); - $normalizedFilterDto->setProperty($propertyName); - - $normalizedFilters[$propertyName] = $normalizedFilterDto; - } - - return $normalizedFilters; - } } diff --git a/src/Filter/Configurator/EmbeddedFilterConfigurator.php b/src/Filter/Configurator/EmbeddedFilterConfigurator.php new file mode 100644 index 0000000000..ff2ecde834 --- /dev/null +++ b/src/Filter/Configurator/EmbeddedFilterConfigurator.php @@ -0,0 +1,35 @@ +isEmbeddedClassProperty($filterDto->getProperty()); + } + + public function configure(FilterDto $filterDto, ?FieldDto $fieldDto, EntityDto $entityDto, AdminContext $context): void + { + $filterDto->setProperty(str_replace('.', '_', $filterDto->getProperty())); + $propertyPath = $filterDto->getFormTypeOption('property_path'); + + if (!$propertyPath) { + // The property accessor sets values on array. + // So we must replace object path to array path. + $paths = explode('.', $filterDto->getProperty()); + foreach ($paths as $key => $path) { + $paths[$key] = "[$path]"; + } + + // We set the property path as form option + $filterDto->setFormTypeOption('property_path', implode('', $paths)); + } + } +} \ No newline at end of file diff --git a/src/Filter/FilterTrait.php b/src/Filter/FilterTrait.php index 508215fcc2..c89c37344e 100644 --- a/src/Filter/FilterTrait.php +++ b/src/Filter/FilterTrait.php @@ -28,7 +28,7 @@ private function __construct() public function __toString(): string { - return (string) $this->dto; + return $this->dto->getProperty(); } public function setFilterFqcn(string $fqcn): self From 8a7d1766d2f7eb06a1edcf6eb649839414fb3d51 Mon Sep 17 00:00:00 2001 From: Joanis Rouanet Date: Tue, 14 Dec 2021 15:58:10 +0100 Subject: [PATCH 04/15] CS fixer --- src/Filter/Configurator/EmbeddedFilterConfigurator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Filter/Configurator/EmbeddedFilterConfigurator.php b/src/Filter/Configurator/EmbeddedFilterConfigurator.php index ff2ecde834..09803eb5db 100644 --- a/src/Filter/Configurator/EmbeddedFilterConfigurator.php +++ b/src/Filter/Configurator/EmbeddedFilterConfigurator.php @@ -32,4 +32,4 @@ public function configure(FilterDto $filterDto, ?FieldDto $fieldDto, EntityDto $ $filterDto->setFormTypeOption('property_path', implode('', $paths)); } } -} \ No newline at end of file +} From 9ae9ecf0393396519b7f0e607ea20ced79f7eb84 Mon Sep 17 00:00:00 2001 From: Joanis Rouanet Date: Tue, 14 Dec 2021 16:21:29 +0100 Subject: [PATCH 05/15] Fix filter factory --- src/Dto/EntityDto.php | 11 +++++++++++ src/Factory/FilterFactory.php | 24 ++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 2 deletions(-) diff --git a/src/Dto/EntityDto.php b/src/Dto/EntityDto.php index 1850059045..5a9f44006c 100644 --- a/src/Dto/EntityDto.php +++ b/src/Dto/EntityDto.php @@ -192,6 +192,17 @@ public function isToManyAssociation(string $propertyName): bool return \in_array($associationType, [ClassMetadataInfo::ONE_TO_MANY, ClassMetadataInfo::MANY_TO_MANY], true); } + public function getEmbeddedTargetClassName(string $propertyName): bool + { + if (!$this->isEmbeddedClassProperty($propertyName)) { + throw new \LogicException(sprintf('The property "%s" is not an embedded class property of class "%s".', $propertyName, $this->getFqcn())); + } + + $propertyNameParts = explode('.', $propertyName, 2); + + return $this->metadata->embeddedClasses[$propertyNameParts[0]]['class']; + } + public function isEmbeddedClassProperty(string $propertyName): bool { $propertyNameParts = explode('.', $propertyName, 2); diff --git a/src/Factory/FilterFactory.php b/src/Factory/FilterFactory.php index 99052fe6ce..018eab8557 100644 --- a/src/Factory/FilterFactory.php +++ b/src/Factory/FilterFactory.php @@ -24,6 +24,7 @@ final class FilterFactory { private $adminContextProvider; + private $entityFactory; private $filterConfigurators; private static $doctrineTypeToFilterClass = [ 'json_array' => ArrayFilter::class, @@ -52,9 +53,10 @@ final class FilterFactory Types::TEXT => TextFilter::class, ]; - public function __construct(AdminContextProvider $adminContextProvider, iterable $filterConfigurators) + public function __construct(AdminContextProvider $adminContextProvider, EntityFactory $entityFactory, iterable $filterConfigurators) { $this->adminContextProvider = $adminContextProvider; + $this->entityFactory = $entityFactory; $this->filterConfigurators = $filterConfigurators; } @@ -63,6 +65,10 @@ public function create(FilterConfigDto $filterConfig, FieldCollection $fields, E $builtFilters = []; /** @var FilterInterface|string $filter */ foreach ($filterConfig->all() as $property => $filter) { + if (\is_array($filter)) { + $filter = implode('.', $filter); + } + if (\is_string($filter)) { $guessedFilterClass = $this->guessFilterClass($entityDto, $property); /** @var FilterInterface $filter */ @@ -86,12 +92,26 @@ public function create(FilterConfigDto $filterConfig, FieldCollection $fields, E return FilterCollection::new($builtFilters); } - private function guessFilterClass(EntityDto $entityDto, string $propertyName): string + private function guessFilterClass(EntityDto $entityDto, string $propertyName, array $context = []): string { if ($entityDto->isAssociation($propertyName)) { return EntityFilter::class; } + if ($entityDto->isEmbeddedClassProperty($propertyName)) { + $properties = explode('.', $propertyName, 2); + $context['root_entity'] = $context['root_entity'] ?? $entityDto; + $context['root_property'] = $context['root_property'] ?? $propertyName; + $embeddedEntity = $this->entityFactory->create($entityDto->getEmbeddedTargetClassName($propertyName)); + $embeddedProperty = $properties[1] ?? null; + + if (!$embeddedProperty) { + throw new \LogicException(sprintf('Missing embedded property name for the property "%s" in entity class "%s".', $context['root_property'], $context['root_entity']->getFqcn())); + } + + return $this->guessFilterClass($embeddedEntity, $properties, $context); + } + $metadata = $entityDto->getPropertyMetadata($propertyName); if ($metadata->isEmpty()) { From 4039ae7a8a07233cae3717263a901d4a01afd986 Mon Sep 17 00:00:00 2001 From: Joanis Rouanet Date: Tue, 14 Dec 2021 16:24:28 +0100 Subject: [PATCH 06/15] Update services.php --- src/Resources/config/services.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Resources/config/services.php b/src/Resources/config/services.php index e463fec2db..6e4b568c7b 100644 --- a/src/Resources/config/services.php +++ b/src/Resources/config/services.php @@ -257,7 +257,8 @@ ->set(FilterFactory::class) ->arg(0, new Reference(AdminContextProvider::class)) - ->arg(1, \function_exists('tagged') + ->arg(1, new Reference(EntityFactory::class)) + ->arg(2, \function_exists('tagged') ? tagged(EasyAdminExtension::TAG_FILTER_CONFIGURATOR) : tagged_iterator(EasyAdminExtension::TAG_FILTER_CONFIGURATOR)) From ca0cbe7330a67f6606e2d3a7ef1fb8372f0305ff Mon Sep 17 00:00:00 2001 From: Joanis Rouanet Date: Tue, 14 Dec 2021 16:44:25 +0100 Subject: [PATCH 07/15] Fixed filter factory and renamed embedded filter configurator --- src/Factory/FilterFactory.php | 29 +++++++++++++++++-- ...figurator.php => EmbeddedConfigurator.php} | 2 +- src/Resources/config/services.php | 3 ++ 3 files changed, 31 insertions(+), 3 deletions(-) rename src/Filter/Configurator/{EmbeddedFilterConfigurator.php => EmbeddedConfigurator.php} (94%) diff --git a/src/Factory/FilterFactory.php b/src/Factory/FilterFactory.php index 018eab8557..036892a76e 100644 --- a/src/Factory/FilterFactory.php +++ b/src/Factory/FilterFactory.php @@ -63,12 +63,17 @@ public function __construct(AdminContextProvider $adminContextProvider, EntityFa public function create(FilterConfigDto $filterConfig, FieldCollection $fields, EntityDto $entityDto): FilterCollection { $builtFilters = []; + $filters = $filterConfig->all(); /** @var FilterInterface|string $filter */ - foreach ($filterConfig->all() as $property => $filter) { + + foreach ($filters as $key => $filter) { if (\is_array($filter)) { - $filter = implode('.', $filter); + $filters = array_merge($filters, $this->normalizeEmbeddedFilters($filter)); + unset($filters[$key]); } + } + foreach ($filters as $property => $filter) { if (\is_string($filter)) { $guessedFilterClass = $this->guessFilterClass($entityDto, $property); /** @var FilterInterface $filter */ @@ -120,4 +125,24 @@ private function guessFilterClass(EntityDto $entityDto, string $propertyName, ar return self::$doctrineTypeToFilterClass[$metadata->get('type')] ?? TextFilter::class; } + + private function normalizeEmbeddedFilters(array $embeddedFilters = [], array $context = []): array + { + $filters = []; + $context['parent_properties'] = $context['parent_properties'] ?? []; + + foreach ($embeddedFilters as $property => $embeddedFilter) { + if(\is_array($embeddedFilter)) { + $context['parent_properties'][] = $property; + $filters = array_merge($this->normalizeEmbeddedFilters($embeddedFilter, $context)); + + continue; + } + + $properties = array_merge($context['parent_properties'], [$property]); + $filters[implode('.', $properties)] = $embeddedFilter; + } + + return $filters; + } } diff --git a/src/Filter/Configurator/EmbeddedFilterConfigurator.php b/src/Filter/Configurator/EmbeddedConfigurator.php similarity index 94% rename from src/Filter/Configurator/EmbeddedFilterConfigurator.php rename to src/Filter/Configurator/EmbeddedConfigurator.php index 09803eb5db..02e9542cea 100644 --- a/src/Filter/Configurator/EmbeddedFilterConfigurator.php +++ b/src/Filter/Configurator/EmbeddedConfigurator.php @@ -8,7 +8,7 @@ use EasyCorp\Bundle\EasyAdminBundle\Dto\FieldDto; use EasyCorp\Bundle\EasyAdminBundle\Dto\FilterDto; -class EmbeddedFilterConfigurator implements FilterConfiguratorInterface +class EmbeddedConfigurator implements FilterConfiguratorInterface { public function supports(FilterDto $filterDto, ?FieldDto $fieldDto, EntityDto $entityDto, AdminContext $context): bool { diff --git a/src/Resources/config/services.php b/src/Resources/config/services.php index 6e4b568c7b..3b3c19de8c 100644 --- a/src/Resources/config/services.php +++ b/src/Resources/config/services.php @@ -54,6 +54,7 @@ use EasyCorp\Bundle\EasyAdminBundle\Filter\Configurator\CommonConfigurator as CommonFilterConfigurator; use EasyCorp\Bundle\EasyAdminBundle\Filter\Configurator\ComparisonConfigurator as ComparisonFilterConfigurator; use EasyCorp\Bundle\EasyAdminBundle\Filter\Configurator\DateTimeConfigurator as DateTimeFilterConfigurator; +use EasyCorp\Bundle\EasyAdminBundle\Filter\Configurator\EmbeddedConfigurator as EmbeddedFilterConfigurator; use EasyCorp\Bundle\EasyAdminBundle\Filter\Configurator\EntityConfigurator as EntityFilterConfigurator; use EasyCorp\Bundle\EasyAdminBundle\Filter\Configurator\NullConfigurator as NullFilterConfigurator; use EasyCorp\Bundle\EasyAdminBundle\Filter\Configurator\NumericConfigurator as NumericFilterConfigurator; @@ -278,6 +279,8 @@ ->set(DateTimeFilterConfigurator::class) + ->set(EmbeddedFilterConfigurator::class) + ->set(EntityFilterConfigurator::class) ->set(NullFilterConfigurator::class) From a210ff7123f73b637835e4186be1210767459c25 Mon Sep 17 00:00:00 2001 From: Joanis Rouanet Date: Tue, 14 Dec 2021 17:57:57 +0100 Subject: [PATCH 08/15] Fixed filter factory --- src/Dto/EntityDto.php | 8 +++++++- src/Factory/FilterFactory.php | 17 ++++++++--------- src/Factory/FormFactory.php | 5 +++++ .../Configurator/EmbeddedConfigurator.php | 1 - 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/src/Dto/EntityDto.php b/src/Dto/EntityDto.php index 5a9f44006c..75cdfedb52 100644 --- a/src/Dto/EntityDto.php +++ b/src/Dto/EntityDto.php @@ -8,6 +8,7 @@ use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection; use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore; use Symfony\Component\PropertyAccess\PropertyAccess; +use function _PHPStan_76800bfb5\RingCentral\Psr7\str; /** * @author Javier Eguiluz @@ -193,6 +194,11 @@ public function isToManyAssociation(string $propertyName): bool } public function getEmbeddedTargetClassName(string $propertyName): bool + { + return $this->getEmbeddedPropertyMetadata($propertyName)['class']; + } + + public function getEmbeddedPropertyMetadata(string $propertyName): array { if (!$this->isEmbeddedClassProperty($propertyName)) { throw new \LogicException(sprintf('The property "%s" is not an embedded class property of class "%s".', $propertyName, $this->getFqcn())); @@ -200,7 +206,7 @@ public function getEmbeddedTargetClassName(string $propertyName): bool $propertyNameParts = explode('.', $propertyName, 2); - return $this->metadata->embeddedClasses[$propertyNameParts[0]]['class']; + return $this->metadata->embeddedClasses[$propertyNameParts[0]]; } public function isEmbeddedClassProperty(string $propertyName): bool diff --git a/src/Factory/FilterFactory.php b/src/Factory/FilterFactory.php index 036892a76e..135178bb9e 100644 --- a/src/Factory/FilterFactory.php +++ b/src/Factory/FilterFactory.php @@ -68,7 +68,7 @@ public function create(FilterConfigDto $filterConfig, FieldCollection $fields, E foreach ($filters as $key => $filter) { if (\is_array($filter)) { - $filters = array_merge($filters, $this->normalizeEmbeddedFilters($filter)); + $filters = array_merge($filters, $this->normalizeEmbeddedFilters($key, $filter)); unset($filters[$key]); } } @@ -126,21 +126,20 @@ private function guessFilterClass(EntityDto $entityDto, string $propertyName, ar return self::$doctrineTypeToFilterClass[$metadata->get('type')] ?? TextFilter::class; } - private function normalizeEmbeddedFilters(array $embeddedFilters = [], array $context = []): array + private function normalizeEmbeddedFilters(string $rootPropertyName, array $embeddedFilters = []): array { $filters = []; - $context['parent_properties'] = $context['parent_properties'] ?? []; - foreach ($embeddedFilters as $property => $embeddedFilter) { - if(\is_array($embeddedFilter)) { - $context['parent_properties'][] = $property; - $filters = array_merge($this->normalizeEmbeddedFilters($embeddedFilter, $context)); + foreach ($embeddedFilters as $propertyName => $embeddedFilter) { + if (\is_array($embeddedFilter)) { + $filters = array_merge($filters, $this->normalizeEmbeddedFilters("$rootPropertyName.$propertyName", $embeddedFilter)); continue; } - $properties = array_merge($context['parent_properties'], [$property]); - $filters[implode('.', $properties)] = $embeddedFilter; + /** @var FilterInterface $embeddedFilter */ + $embeddedFilter->getAsDto()->setProperty("$rootPropertyName.$propertyName"); + $filters["$rootPropertyName.$propertyName"] = $embeddedFilter; } return $filters; diff --git a/src/Factory/FormFactory.php b/src/Factory/FormFactory.php index 8ba6934494..0f4e74c37f 100644 --- a/src/Factory/FormFactory.php +++ b/src/Factory/FormFactory.php @@ -60,6 +60,11 @@ public function createNewForm(EntityDto $entityDto, KeyValueStore $formOptions, public function createFiltersForm(FilterCollection $filters, Request $request): FormInterface { + // To avoid errors on embedded class property fields + foreach ($filters as $filter) { + $filter->setProperty(str_replace('.', '_', $filter->getProperty())); + } + $filtersForm = $this->symfonyFormFactory->createNamed('filters', FiltersFormType::class, null, [ 'method' => 'GET', 'action' => $request->query->get(EA::REFERRER, ''), diff --git a/src/Filter/Configurator/EmbeddedConfigurator.php b/src/Filter/Configurator/EmbeddedConfigurator.php index 02e9542cea..36663281e1 100644 --- a/src/Filter/Configurator/EmbeddedConfigurator.php +++ b/src/Filter/Configurator/EmbeddedConfigurator.php @@ -17,7 +17,6 @@ public function supports(FilterDto $filterDto, ?FieldDto $fieldDto, EntityDto $e public function configure(FilterDto $filterDto, ?FieldDto $fieldDto, EntityDto $entityDto, AdminContext $context): void { - $filterDto->setProperty(str_replace('.', '_', $filterDto->getProperty())); $propertyPath = $filterDto->getFormTypeOption('property_path'); if (!$propertyPath) { From ed54f40fa43a5bbfe6110925802a2a6b617a9e58 Mon Sep 17 00:00:00 2001 From: Joanis Rouanet Date: Tue, 14 Dec 2021 18:00:44 +0100 Subject: [PATCH 09/15] CS fixer --- src/Dto/EntityDto.php | 1 - src/Factory/FilterFactory.php | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Dto/EntityDto.php b/src/Dto/EntityDto.php index 75cdfedb52..74e1777d5a 100644 --- a/src/Dto/EntityDto.php +++ b/src/Dto/EntityDto.php @@ -8,7 +8,6 @@ use EasyCorp\Bundle\EasyAdminBundle\Collection\FieldCollection; use EasyCorp\Bundle\EasyAdminBundle\Config\KeyValueStore; use Symfony\Component\PropertyAccess\PropertyAccess; -use function _PHPStan_76800bfb5\RingCentral\Psr7\str; /** * @author Javier Eguiluz diff --git a/src/Factory/FilterFactory.php b/src/Factory/FilterFactory.php index 135178bb9e..d3edaccb8f 100644 --- a/src/Factory/FilterFactory.php +++ b/src/Factory/FilterFactory.php @@ -64,8 +64,8 @@ public function create(FilterConfigDto $filterConfig, FieldCollection $fields, E { $builtFilters = []; $filters = $filterConfig->all(); - /** @var FilterInterface|string $filter */ + /** @var FilterInterface|string $filter */ foreach ($filters as $key => $filter) { if (\is_array($filter)) { $filters = array_merge($filters, $this->normalizeEmbeddedFilters($key, $filter)); @@ -73,6 +73,7 @@ public function create(FilterConfigDto $filterConfig, FieldCollection $fields, E } } + /** @var FilterInterface|string $filter */ foreach ($filters as $property => $filter) { if (\is_string($filter)) { $guessedFilterClass = $this->guessFilterClass($entityDto, $property); @@ -137,7 +138,6 @@ private function normalizeEmbeddedFilters(string $rootPropertyName, array $embed continue; } - /** @var FilterInterface $embeddedFilter */ $embeddedFilter->getAsDto()->setProperty("$rootPropertyName.$propertyName"); $filters["$rootPropertyName.$propertyName"] = $embeddedFilter; } From 3eec7addc67326756fbc50e92a78bc3e0bca2f12 Mon Sep 17 00:00:00 2001 From: Joanis Rouanet Date: Tue, 14 Dec 2021 18:37:00 +0100 Subject: [PATCH 10/15] Fixed entity repository --- src/Orm/EntityRepository.php | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/src/Orm/EntityRepository.php b/src/Orm/EntityRepository.php index 11dc2515fa..49214433ad 100644 --- a/src/Orm/EntityRepository.php +++ b/src/Orm/EntityRepository.php @@ -9,6 +9,7 @@ use EasyCorp\Bundle\EasyAdminBundle\Contracts\Orm\EntityRepositoryInterface; use EasyCorp\Bundle\EasyAdminBundle\Dto\EntityDto; use EasyCorp\Bundle\EasyAdminBundle\Dto\FilterDataDto; +use EasyCorp\Bundle\EasyAdminBundle\Dto\FilterDto; use EasyCorp\Bundle\EasyAdminBundle\Dto\SearchDto; use EasyCorp\Bundle\EasyAdminBundle\Factory\EntityFactory; use EasyCorp\Bundle\EasyAdminBundle\Factory\FormFactory; @@ -186,7 +187,7 @@ private function addFilterClause(QueryBuilder $queryBuilder, SearchDto $searchDt foreach ($filtersForm as $filterForm) { $propertyName = $filterForm->getName(); - $filter = $configuredFilters->get($propertyName); + $filter = $this->resolveFilterDto($configuredFilters, $propertyName); // this filter is not defined or not applied if (null === $filter || !isset($appliedFilters[$propertyName])) { continue; @@ -211,4 +212,21 @@ private function addFilterClause(QueryBuilder $queryBuilder, SearchDto $searchDt ++$i; } } + + private function resolveFilterDto(FilterCollection $configuredFilters, string $propertyName): ?FilterDto + { + $filter = $configuredFilters->get($propertyName); + + if (!$filter) { + foreach ($configuredFilters as $filteredPropertyName => $filter) { + if ($propertyName === $filter->getProperty()) { + $filter->setProperty($filteredPropertyName); + + return $filter; + } + } + } + + return null; + } } From fb75685412888d6c8aae3a28fcb3c81636e3b539 Mon Sep 17 00:00:00 2001 From: Joanis Rouanet Date: Tue, 14 Dec 2021 18:42:19 +0100 Subject: [PATCH 11/15] Deleted embedded filter configurator --- src/Factory/FormFactory.php | 13 +++++++ .../Configurator/EmbeddedConfigurator.php | 34 ------------------- src/Resources/config/services.php | 3 -- 3 files changed, 13 insertions(+), 37 deletions(-) delete mode 100644 src/Filter/Configurator/EmbeddedConfigurator.php diff --git a/src/Factory/FormFactory.php b/src/Factory/FormFactory.php index 0f4e74c37f..23aa3bd96c 100644 --- a/src/Factory/FormFactory.php +++ b/src/Factory/FormFactory.php @@ -63,6 +63,19 @@ public function createFiltersForm(FilterCollection $filters, Request $request): // To avoid errors on embedded class property fields foreach ($filters as $filter) { $filter->setProperty(str_replace('.', '_', $filter->getProperty())); + $propertyPath = $filter->getFormTypeOption('property_path'); + + if (!$propertyPath) { + // The property accessor sets values on array. + // So we must replace object path to array path. + $paths = explode('.', $filter->getProperty()); + foreach ($paths as $key => $path) { + $paths[$key] = "[$path]"; + } + + // We set the property path as form option + $filter->setFormTypeOption('property_path', implode('', $paths)); + } } $filtersForm = $this->symfonyFormFactory->createNamed('filters', FiltersFormType::class, null, [ diff --git a/src/Filter/Configurator/EmbeddedConfigurator.php b/src/Filter/Configurator/EmbeddedConfigurator.php deleted file mode 100644 index 36663281e1..0000000000 --- a/src/Filter/Configurator/EmbeddedConfigurator.php +++ /dev/null @@ -1,34 +0,0 @@ -isEmbeddedClassProperty($filterDto->getProperty()); - } - - public function configure(FilterDto $filterDto, ?FieldDto $fieldDto, EntityDto $entityDto, AdminContext $context): void - { - $propertyPath = $filterDto->getFormTypeOption('property_path'); - - if (!$propertyPath) { - // The property accessor sets values on array. - // So we must replace object path to array path. - $paths = explode('.', $filterDto->getProperty()); - foreach ($paths as $key => $path) { - $paths[$key] = "[$path]"; - } - - // We set the property path as form option - $filterDto->setFormTypeOption('property_path', implode('', $paths)); - } - } -} diff --git a/src/Resources/config/services.php b/src/Resources/config/services.php index 3b3c19de8c..6e4b568c7b 100644 --- a/src/Resources/config/services.php +++ b/src/Resources/config/services.php @@ -54,7 +54,6 @@ use EasyCorp\Bundle\EasyAdminBundle\Filter\Configurator\CommonConfigurator as CommonFilterConfigurator; use EasyCorp\Bundle\EasyAdminBundle\Filter\Configurator\ComparisonConfigurator as ComparisonFilterConfigurator; use EasyCorp\Bundle\EasyAdminBundle\Filter\Configurator\DateTimeConfigurator as DateTimeFilterConfigurator; -use EasyCorp\Bundle\EasyAdminBundle\Filter\Configurator\EmbeddedConfigurator as EmbeddedFilterConfigurator; use EasyCorp\Bundle\EasyAdminBundle\Filter\Configurator\EntityConfigurator as EntityFilterConfigurator; use EasyCorp\Bundle\EasyAdminBundle\Filter\Configurator\NullConfigurator as NullFilterConfigurator; use EasyCorp\Bundle\EasyAdminBundle\Filter\Configurator\NumericConfigurator as NumericFilterConfigurator; @@ -279,8 +278,6 @@ ->set(DateTimeFilterConfigurator::class) - ->set(EmbeddedFilterConfigurator::class) - ->set(EntityFilterConfigurator::class) ->set(NullFilterConfigurator::class) From f37c96d4e8f891da9044ad80fd0ab61cd4401239 Mon Sep 17 00:00:00 2001 From: Joanis Rouanet Date: Tue, 14 Dec 2021 18:44:22 +0100 Subject: [PATCH 12/15] Fixed phpdoc in filter factory --- src/Factory/FilterFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Factory/FilterFactory.php b/src/Factory/FilterFactory.php index d3edaccb8f..ab787e87ba 100644 --- a/src/Factory/FilterFactory.php +++ b/src/Factory/FilterFactory.php @@ -65,7 +65,7 @@ public function create(FilterConfigDto $filterConfig, FieldCollection $fields, E $builtFilters = []; $filters = $filterConfig->all(); - /** @var FilterInterface|string $filter */ + /** @var FilterInterface|string|array $filter */ foreach ($filters as $key => $filter) { if (\is_array($filter)) { $filters = array_merge($filters, $this->normalizeEmbeddedFilters($key, $filter)); From 9a9252e409c54fd49b4d1fbce20a9b9be1e36fa6 Mon Sep 17 00:00:00 2001 From: Joanis Rouanet Date: Wed, 15 Dec 2021 10:49:54 +0100 Subject: [PATCH 13/15] Fixed form factory --- src/Factory/FormFactory.php | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/src/Factory/FormFactory.php b/src/Factory/FormFactory.php index 23aa3bd96c..a2adaf9d53 100644 --- a/src/Factory/FormFactory.php +++ b/src/Factory/FormFactory.php @@ -62,19 +62,22 @@ public function createFiltersForm(FilterCollection $filters, Request $request): { // To avoid errors on embedded class property fields foreach ($filters as $filter) { - $filter->setProperty(str_replace('.', '_', $filter->getProperty())); - $propertyPath = $filter->getFormTypeOption('property_path'); + if (false !== strpos($filter->getProperty(), '.')) { + $normalizedFilterName = str_replace('.', '_', $filter->getProperty()); + $propertyPath = $filter->getFormTypeOption('property_path'); - if (!$propertyPath) { - // The property accessor sets values on array. - // So we must replace object path to array path. - $paths = explode('.', $filter->getProperty()); - foreach ($paths as $key => $path) { - $paths[$key] = "[$path]"; - } + if (!$propertyPath) { + // The property accessor sets values on array. + // So we must replace object path to array path. + $paths = explode('.', $filter->getProperty()); + foreach ($paths as $key => $path) { + $paths[$key] = "[$path]"; + } - // We set the property path as form option - $filter->setFormTypeOption('property_path', implode('', $paths)); + // We set the property path as form option + $filter->setFormTypeOption('property_path', implode('', $paths)); + $filter->setProperty($normalizedFilterName); + } } } From 7f7197e6ea0b25a4a74d4cd45b7a76bd9fde8db7 Mon Sep 17 00:00:00 2001 From: Joanis Rouanet Date: Wed, 15 Dec 2021 10:53:55 +0100 Subject: [PATCH 14/15] Update FormFactory.php --- src/Factory/FormFactory.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Factory/FormFactory.php b/src/Factory/FormFactory.php index a2adaf9d53..6ad2301ad8 100644 --- a/src/Factory/FormFactory.php +++ b/src/Factory/FormFactory.php @@ -76,8 +76,9 @@ public function createFiltersForm(FilterCollection $filters, Request $request): // We set the property path as form option $filter->setFormTypeOption('property_path', implode('', $paths)); - $filter->setProperty($normalizedFilterName); } + + $filter->setProperty($normalizedFilterName); } } From ce8027c597a40539fdf096be71da9915f97dd997 Mon Sep 17 00:00:00 2001 From: Joanis Rouanet Date: Wed, 15 Dec 2021 10:55:03 +0100 Subject: [PATCH 15/15] Fixed code --- src/Factory/FormFactory.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Factory/FormFactory.php b/src/Factory/FormFactory.php index 6ad2301ad8..a31cc555c3 100644 --- a/src/Factory/FormFactory.php +++ b/src/Factory/FormFactory.php @@ -77,7 +77,7 @@ public function createFiltersForm(FilterCollection $filters, Request $request): // We set the property path as form option $filter->setFormTypeOption('property_path', implode('', $paths)); } - + $filter->setProperty($normalizedFilterName); } }