Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 23 additions & 6 deletions doc/filters.rst
Original file line number Diff line number Diff line change
Expand Up @@ -189,14 +189,30 @@ You can now use this custom filter in any of your dashboards and CRUD controller
}
}

Filters on associated entities
-------------------------------
(starting from version 3.x)
If you need to filter by the property of a related entity (e.g.
an ``order`` is associated with a ``customer`` and you want to filter orders by
the ``last_visit`` property of the ``customer``), just use the dot notation to get to the property

public function configureFilters(Filters $filters): Filters
{
return $filters
// just as a string
->add('customer.last_visit_date')
// or with an explicit type, either built-in or custom*
->add(DateTimeFilter::new('customer.last_visit_date')
;
}

* Please note that, if you have pre-3.x custom filters, you'll have to update them to be able
to work like this.

Unmapped Filters
----------------

By default, each filter must be associated with a property of the entity.
However, sometimes you need to filter by the property of a related entity (e.g.
an ``order`` is associated with a ``customer`` and you want to filter orders by
the ``country`` property of the ``customer``). In those cases, set the
``mapped`` option to ``false`` in the filter or you'll see an exception::
In more complex cases, set the ``mapped`` option to ``false`` in the filter or you'll see an exception::

namespace App\Controller\Admin;

Expand All @@ -214,9 +230,10 @@ the ``country`` property of the ``customer``). In those cases, set the
return $filters
// 'country' doesn't exist as a property of 'Order' so it's
// defined as 'not mapped' to avoid errors
->add(CustomerCountryFilter::new('country')->mapped(false))
->add(CustomerCountryFilter::new('country')->setFormTypeOptions('mapped', false))
;
}
}

.. TODO: explain and show an example of compound filter forms
.. TODO : separate how filter is rendered (the filter form) and how it will go get the property
5 changes: 5 additions & 0 deletions src/Dto/FilterDataDto.php
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,11 @@ public function getProperty(): string
return $this->filterDto->getProperty();
}

public function getName(): string
{
return $this->filterDto->getName();
}

public function getFormTypeOption(string $optionName)
{
return $this->filterDto->getFormTypeOption($optionName);
Expand Down
17 changes: 17 additions & 0 deletions src/Dto/FilterDto.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ final class FilterDto
private $propertyName;
private $label;
private $applyCallable;
private $name;

public function __construct()
{
Expand Down Expand Up @@ -75,6 +76,10 @@ public function getProperty(): string
public function setProperty(string $propertyName): void
{
$this->propertyName = $propertyName;
if (is_null($this->name)) {
$parts = explode('.', $propertyName);
$this->name = end($parts);
}
}

/**
Expand All @@ -85,6 +90,18 @@ public function getLabel()
return $this->label;
}

public function getName(): string
{
return $this->name;
}

public function setName(string $name)
{
$this->name = $name;
return $this;
}


/**
* @param string|false|null $label
*/
Expand Down
1 change: 1 addition & 0 deletions src/Filter/ArrayFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ public function canSelectMultiple(bool $selectMultiple = true): self
public function apply(QueryBuilder $queryBuilder, FilterDataDto $filterDataDto, ?FieldDto $fieldDto, EntityDto $entityDto): void
{
$alias = $filterDataDto->getEntityAlias();
// TODO : if filter property is compound, traverse the main property to get to the good one
$property = $filterDataDto->getProperty();
$comparison = $filterDataDto->getComparison();
$parameterName = $filterDataDto->getParameterName();
Expand Down
1 change: 1 addition & 0 deletions src/Filter/BooleanFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public static function new(string $propertyName, $label = null): self

public function apply(QueryBuilder $queryBuilder, FilterDataDto $filterDataDto, ?FieldDto $fieldDto, EntityDto $entityDto): void
{
// TODO : if filter property is compound, traverse the main property to get to the good one
$queryBuilder
->andWhere(sprintf('%s.%s %s :%s', $filterDataDto->getEntityAlias(), $filterDataDto->getProperty(), $filterDataDto->getComparison(), $filterDataDto->getParameterName()))
->setParameter($filterDataDto->getParameterName(), $filterDataDto->getValue());
Expand Down
1 change: 1 addition & 0 deletions src/Filter/ChoiceFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,7 @@ public function canSelectMultiple(bool $selectMultiple = true): self

public function apply(QueryBuilder $queryBuilder, FilterDataDto $filterDataDto, ?FieldDto $fieldDto, EntityDto $entityDto): void
{
// TODO : if filter property is compound, traverse the main property to get to the good one
$alias = $filterDataDto->getEntityAlias();
$property = $filterDataDto->getProperty();
$comparison = $filterDataDto->getComparison();
Expand Down
1 change: 1 addition & 0 deletions src/Filter/ComparisonFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public static function new(string $propertyName, $label = null): self

public function apply(QueryBuilder $queryBuilder, FilterDataDto $filterDataDto, ?FieldDto $fieldDto, EntityDto $entityDto): void
{
// TODO : if filter property is compound, traverse the main property to get to the good one
$alias = $filterDataDto->getEntityAlias();
$property = $filterDataDto->getProperty();
$comparison = $filterDataDto->getComparison();
Expand Down
1 change: 1 addition & 0 deletions src/Filter/Configurator/ComparisonConfigurator.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public function supports(FilterDto $filterDto, ?FieldDto $fieldDto, EntityDto $e

public function configure(FilterDto $filterDto, ?FieldDto $fieldDto, EntityDto $entityDto, AdminContext $context): void
{
// TODO : if filter property is compound, traverse the main property to get to the good one
$propertyType = $entityDto->getPropertyMetadata($filterDto->getProperty())->get('type');

if (Types::DATEINTERVAL === $propertyType) {
Expand Down
1 change: 1 addition & 0 deletions src/Filter/Configurator/DateTimeConfigurator.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ public function supports(FilterDto $filterDto, ?FieldDto $fieldDto, EntityDto $e

public function configure(FilterDto $filterDto, ?FieldDto $fieldDto, EntityDto $entityDto, AdminContext $context): void
{
// TODO : if filter property is compound, traverse the main property to get to the good one
$propertyType = $entityDto->getPropertyMetadata($filterDto->getProperty())->get('type');

if (Types::DATE_MUTABLE === $propertyType) {
Expand Down
1 change: 1 addition & 0 deletions src/Filter/Configurator/EntityConfigurator.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ public function supports(FilterDto $filterDto, ?FieldDto $fieldDto, EntityDto $e

public function configure(FilterDto $filterDto, ?FieldDto $fieldDto, EntityDto $entityDto, AdminContext $context): void
{
// TODO : if filter property is compound, traverse the main property to get to the good one
$propertyName = $filterDto->getProperty();
if (!$entityDto->isAssociation($propertyName)) {
return;
Expand Down
1 change: 1 addition & 0 deletions src/Filter/Configurator/NumericConfigurator.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public function supports(FilterDto $filterDto, ?FieldDto $fieldDto, EntityDto $e

public function configure(FilterDto $filterDto, ?FieldDto $fieldDto, EntityDto $entityDto, AdminContext $context): void
{
// TODO : if filter property is compound, traverse the main property to get to the good one
$propertyType = $entityDto->getPropertyMetadata($filterDto->getProperty())->get('type');

if (Types::DECIMAL === $propertyType) {
Expand Down
1 change: 1 addition & 0 deletions src/Filter/Configurator/TextConfigurator.php
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ public function supports(FilterDto $filterDto, ?FieldDto $fieldDto, EntityDto $e

public function configure(FilterDto $filterDto, ?FieldDto $fieldDto, EntityDto $entityDto, AdminContext $context): void
{
// TODO : if filter property is compound, traverse the main property to get to the good one
$propertyType = $entityDto->getPropertyMetadata($filterDto->getProperty())->get('type');

if (Types::JSON === $propertyType) {
Expand Down
1 change: 1 addition & 0 deletions src/Filter/DateTimeFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public static function new(string $propertyName, $label = null): self

public function apply(QueryBuilder $queryBuilder, FilterDataDto $filterDataDto, ?FieldDto $fieldDto, EntityDto $entityDto): void
{
// TODO : if filter property is compound, traverse the main property to get to the good one
$alias = $filterDataDto->getEntityAlias();
$property = $filterDataDto->getProperty();
$comparison = $filterDataDto->getComparison();
Expand Down
1 change: 1 addition & 0 deletions src/Filter/EntityFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public static function new(string $propertyName, $label = null): self

public function apply(QueryBuilder $queryBuilder, FilterDataDto $filterDataDto, ?FieldDto $fieldDto, EntityDto $entityDto): void
{
// TODO : if filter property is compound, traverse the main property to get to the good one
$alias = $filterDataDto->getEntityAlias();
$property = $filterDataDto->getProperty();
$comparison = $filterDataDto->getComparison();
Expand Down
8 changes: 7 additions & 1 deletion src/Filter/FilterTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ private function __construct()

public function __toString(): string
{
return $this->dto->getProperty();
return $this->dto->getName();
}

public function setFilterFqcn(string $fqcn): self
Expand All @@ -38,6 +38,12 @@ public function setFilterFqcn(string $fqcn): self
return $this;
}

public function setName(string $name): self {
$this->dto->setName($name);

return $this;
}

public function setProperty(string $propertyName): self
{
$this->dto->setProperty($propertyName);
Expand Down
1 change: 1 addition & 0 deletions src/Filter/NumericFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public static function new(string $propertyName, $label = null): self

public function apply(QueryBuilder $queryBuilder, FilterDataDto $filterDataDto, ?FieldDto $fieldDto, EntityDto $entityDto): void
{
// TODO : if filter property is compound, traverse the main property to get to the good one
$alias = $filterDataDto->getEntityAlias();
$property = $filterDataDto->getProperty();
$comparison = $filterDataDto->getComparison();
Expand Down
1 change: 1 addition & 0 deletions src/Filter/TextFilter.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public static function new(string $propertyName, $label = null): self

public function apply(QueryBuilder $queryBuilder, FilterDataDto $filterDataDto, ?FieldDto $fieldDto, EntityDto $entityDto): void
{
// TODO : if filter property is compound, traverse the main property to get to the good one
$alias = $filterDataDto->getEntityAlias();
$property = $filterDataDto->getProperty();
$comparison = $filterDataDto->getComparison();
Expand Down
2 changes: 1 addition & 1 deletion src/Form/Type/FiltersFormType.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public function buildForm(FormBuilderInterface $builder, array $options)
{
/** @var FilterDto $filter */
foreach ($options['ea_filters'] as $filter) {
$builder->add($filter->getProperty(), $filter->getFormType(), $filter->getFormTypeOptions());
$builder->add($filter->getName(), $filter->getFormType(), $filter->getFormTypeOptions());
}
}

Expand Down