Open speller opened 1 year ago
We're using the following workaround patch to be able using filters on embeddable fields:
--- a/src/Form/Type/FiltersFormType.php
+++ b/src/Form/Type/FiltersFormType.php
@@ -17,7 +17,12 @@
{
/** @var FilterDto $filter */
foreach ($options['ea_filters'] as $filter) {
- $builder->add($filter->getProperty(), $filter->getFormType(), $filter->getFormTypeOptions());
+ // Convert the dots in filter names to colons to pass Symfony forms validation (e.g. 'foo.bar' => 'foo:bar').
+ $builder->add(
+ str_replace('.', ':', $filter->getProperty()),
+ $filter->getFormType(),
+ $filter->getFormTypeOptions(),
+ );
}
}
--- a/src/Orm/EntityRepository.php
+++ b/src/Orm/EntityRepository.php
@@ -193,7 +193,8 @@
$appliedFilters = $searchDto->getAppliedFilters();
$i = 0;
foreach ($filtersForm as $filterForm) {
- $propertyName = $filterForm->getName();
+ // Forms have property names with dots converted to colons. Need to match them here.
+ $propertyName = str_replace(':', '.', $filterForm->getName());
$filter = $configuredFilters->get($propertyName);
// this filter is not defined or not applied
--- a/src/Factory/AdminContextFactory.php
+++ a/src/Factory/AdminContextFactory.php
@@ -214,7 +214,11 @@
$query = $queryParams[EA::QUERY] ?? null;
$defaultSort = $crudDto->getDefaultSort();
$customSort = $queryParams[EA::SORT] ?? [];
- $appliedFilters = $queryParams[EA::FILTERS] ?? [];
+ // Convert filter names back from colons to dots (e.g. 'foo:bar' => 'foo.bar').
+ $appliedFilters = [];
+ foreach ($queryParams[EA::FILTERS] ?? [] as $name => $data) {
+ $appliedFilters[str_replace(':', '.', $name)] = $data;
+ }
return new SearchDto($request, $searchableProperties, $query, $defaultSort, $customSort, $appliedFilters);
}
--- a/src/Factory/FilterFactory.php
+++ b/src/Factory/FilterFactory.php
@@ -61,8 +61,19 @@
public function create(FilterConfigDto $filterConfig, FieldCollection $fields, EntityDto $entityDto): FilterCollection
{
$builtFilters = [];
+ // Fix bug with nested filters converted to arrays
+ $filters = [];
/** @var FilterInterface|string $filter */
foreach ($filterConfig->all() as $property => $filter) {
+ if (\is_array($filter)) {
+ foreach ($filter as $key => $value) {
+ $filters["$property.$key"] = $value;
+ }
+ } else {
+ $filters[$property] = $filter;
+ }
+ }
+ foreach ($filters as $property => $filter) {
if (\is_string($filter)) {
$guessedFilterClass = $this->guessFilterClass($entityDto, $property);
/** @var FilterInterface $filter */
This patch is doing two simple things:
.
in filter field names into colons :
to pass Symfony Forms field name validation. And the reverse conversion on parsing an HTTP request.Use https://github.com/cweagans/composer-patches to apply this patch easily over EA.
Related:
Hi,
Thank you for your feedback. Issue known since 2021. PR's since 2021. No news. Ping? Pong? Explanation? Useless? Entities should have 10000 lines? Doctrine will remove embedded classes concept? What's going on with this feature? Please, at least an answer from the staff would be appreciate...
Here is an updated version of the patch @speller provided above.
--- a/src/Form/Type/FiltersFormType.php
+++ b/src/Form/Type/FiltersFormType.php
@@ -17,7 +17,12 @@
{
/** @var FilterDto $filter */
foreach ($options['ea_filters'] as $filter) {
- $builder->add($filter->getProperty(), $filter->getFormType(), $filter->getFormTypeOptions());
+ // Convert the dots in filter names to colons to pass Symfony forms validation (e.g. 'foo.bar' => 'foo:bar').
+ $builder->add(
+ str_replace('.', ':', $filter->getProperty()),
+ $filter->getFormType(),
+ $filter->getFormTypeOptions(),
+ );
}
}
--- a/src/Orm/EntityRepository.php
+++ b/src/Orm/EntityRepository.php
@@ -210,7 +210,8 @@
$appliedFilters = $searchDto->getAppliedFilters();
$i = 0;
foreach ($filtersForm as $filterForm) {
- $propertyName = $filterForm->getName();
+ // Forms have property names with dots converted to colons. Need to match them here.
+ $propertyName = str_replace(':', '.', $filterForm->getName());
$filter = $configuredFilters->get($propertyName);
// this filter is not defined or not applied
@@ -316,8 +316,16 @@
? $associatedEntityDto->getFqcn()
: $entityDto->getFqcn()
;
- /** @var \ReflectionNamedType|\ReflectionUnionType|null $idClassType */
- $idClassType = (new \ReflectionProperty($entityFqcn, $propertyName))->getType();
+
+ if (str_contains($propertyName, '.')) {
+ $propertyNameEmbedded = explode('.', $propertyName);
+ $embeddedPropertyClass = (new \ReflectionProperty($entityFqcn, $propertyNameEmbedded[0]))->getType();
+ /** @var \ReflectionNamedType|\ReflectionUnionType|null $idClassType */
+ $idClassType = (new \ReflectionProperty($embeddedPropertyClass->getName(), $propertyNameEmbedded[1]))->getType();
+ } else {
+ /** @var \ReflectionNamedType|\ReflectionUnionType|null $idClassType */
+ $idClassType = (new \ReflectionProperty($entityFqcn, $propertyName))->getType();
+ }
if (null !== $idClassType) {
$idClassName = $idClassType->getName();
--- a/src/Factory/AdminContextFactory.php
+++ a/src/Factory/AdminContextFactory.php
@@ -215,7 +215,11 @@
$query = $queryParams[EA::QUERY] ?? null;
$defaultSort = $crudDto->getDefaultSort();
$customSort = $queryParams[EA::SORT] ?? [];
- $appliedFilters = $queryParams[EA::FILTERS] ?? [];
$searchMode = $crudDto->getSearchMode();
+ // Convert filter names back from colons to dots (e.g. 'foo:bar' => 'foo.bar').
+ $appliedFilters = [];
+ foreach ($queryParams[EA::FILTERS] ?? [] as $name => $data) {
+ $appliedFilters[str_replace(':', '.', $name)] = $data;
+ }
return new SearchDto($request, $searchableProperties, $query, $defaultSort, $customSort, $appliedFilters, $searchMode);
}
--- a/src/Factory/FilterFactory.php
+++ b/src/Factory/FilterFactory.php
@@ -61,8 +61,19 @@
public function create(FilterConfigDto $filterConfig, FieldCollection $fields, EntityDto $entityDto): FilterCollection
{
$builtFilters = [];
+ // Fix bug with nested filters converted to arrays
+ $filters = [];
/** @var FilterInterface|string $filter */
foreach ($filterConfig->all() as $property => $filter) {
+ if (\is_array($filter)) {
+ foreach ($filter as $key => $value) {
+ $filters["$property.$key"] = $value;
+ }
+ } else {
+ $filters[$property] = $filter;
+ }
+ }
+ foreach ($filters as $property => $filter) {
if (\is_string($filter)) {
$guessedFilterClass = $this->guessFilterClass($entityDto, $property);
/** @var FilterInterface $filter */
I use it in composer json like this with cweagans/composer-patches version ^1.7
"config": {
"allow-plugins": {
"cweagans/composer-patches": true
}
},
"extra": {
"patches": {
"easycorp/easyadmin-bundle": {
"Filter on embedded": "patches/easyadmin/filter_on_embedded.patch",
}
}
}
Describe the bug Can not add a filter on an embedded field.
To Reproduce
$filters->add('embeddable_field.embedded_field')
Expected result: I see a filter for the field.
Actual result: Exception