Skip to content

Commit

Permalink
bug #2781 Fixed ArrayFilterType issue and add support for multiple =>…
Browse files Browse the repository at this point in the history
… false (yceruto)

This PR was merged into the 2.0.x-dev branch.

Discussion
----------

Fixed ArrayFilterType issue and add support for multiple => false

By default, this filter does not provide any choices list, they are dynamic (tags-style).
Now you can configure your own choices list for array filters:
```yaml
easy_admin:
    entities:
        Products:
            # ...
            list:
                filters:
                    - property: 'fieldname'
                      type: 'array' # use this filter for `array`, `simple_array` and `json_array` types only.
                      type_options:
                          value_type_options:
                              multiple: true # or false
                              choices: { foo: 'foo', bar: 'bar' }
                              attr: { data-widget: 'select2' }
```

Commits
-------

562995a Fix ArrayFilterType and add support for multiple => false
  • Loading branch information
javiereguiluz committed Jun 21, 2019
2 parents b27c3fc + 562995a commit 62e9661
Show file tree
Hide file tree
Showing 2 changed files with 58 additions and 17 deletions.
17 changes: 10 additions & 7 deletions src/Form/Filter/Type/ArrayFilterType.php
Expand Up @@ -24,16 +24,19 @@ class ArrayFilterType extends FilterType
*/
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('value', $options['value_type'], $options['value_type_options'] + [
'label' => false,
'choice_loader' => new DynamicChoiceLoader(),
]);
$defaultOptions = ['label' => false];
if (!isset($options['value_type_options']['choices']) || [] === $options['value_type_options']['choices']) {
$defaultOptions += ['choice_loader' => new DynamicChoiceLoader()];
}
$builder->add('value', $options['value_type'], $options['value_type_options'] + $defaultOptions);

$builder->addModelTransformer(new CallbackTransformer(
static function ($data) { return $data; },
static function ($data) {
if ([] === $data['value']) {
if (null === $data['value'] || [] === $data['value']) {
$data['comparison'] = ComparisonType::CONTAINS === $data['comparison'] ? 'IS NULL' : 'IS NOT NULL';
} else {
$data['value'] = (array) $data['value'];
}

return $data;
Expand Down Expand Up @@ -74,15 +77,15 @@ public function filter(QueryBuilder $queryBuilder, FormInterface $form, array $m
{
$alias = \current($queryBuilder->getRootAliases());
$property = $metadata['property'];
$paramName = static::createAlias($property);
$useQuotes = 'simple_array' !== $metadata['dataType'];
$data = $form->getData();

if ([] === $data['value']) {
if (null === $data['value'] || [] === $data['value']) {
$queryBuilder->andWhere(\sprintf('%s.%s %s', $alias, $property, $data['comparison']));
} else {
$orX = new Expr\Orx();
foreach ($data['value'] as $value) {
$paramName = static::createAlias($property);
$orX->add(\sprintf('%s.%s %s :%s', $alias, $property, $data['comparison'], $paramName));
$queryBuilder->setParameter($paramName, $useQuotes ? '%"'.$value.'"%' : '%'.$value.'%');
}
Expand Down
58 changes: 48 additions & 10 deletions tests/Form/Filter/Type/ArrayFilterTypeTest.php
Expand Up @@ -9,12 +9,22 @@

class ArrayFilterTypeTest extends FilterTypeTest
{
protected function setUp(): void
{
parent::setUp();

// reset counter (only for test purpose)
$m = new \ReflectionProperty(ArrayFilterType::class, 'uniqueAliasId');
$m->setAccessible(true);
$m->setValue(0);
}

/**
* @dataProvider getDataProvider
*/
public function testSubmit($submittedData, $data)
public function testSubmit($submittedData, $data, array $options = [])
{
$form = $this->factory->create(ArrayFilterType::class);
$form = $this->factory->create(ArrayFilterType::class, null, $options);
$form->submit($submittedData);

$this->assertSame($data, $form->getData());
Expand All @@ -26,7 +36,7 @@ public function testSubmit($submittedData, $data)
/**
* @dataProvider getDataProvider
*/
public function testFilter($submittedData, $data, $paramName)
public function testFilter($submittedData, $data, array $options = [])
{
$qb = $this->getMockBuilder(QueryBuilder::class)
->disableOriginalConstructor()
Expand All @@ -36,15 +46,15 @@ public function testFilter($submittedData, $data, $paramName)
->method('getRootAliases')
->willReturn(['o'])
;
if ([] === $data['value']) {
if (null === $data['value'] || [] === $data['value']) {
$qb->expects($this->once())
->method('andWhere')
->with(\sprintf('o.foo %s', $data['comparison']))
->willReturn($qb)
;
} else {
$orX = new Expr\Orx();
$orX->add(\sprintf('o.foo %s :%s', $data['comparison'], $paramName));
$orX->add(\sprintf('o.foo %s :foo_1', $data['comparison']));
if (ComparisonType::NOT_CONTAINS === $data['comparison']) {
$orX->add('o.foo IS NULL');
}
Expand All @@ -55,11 +65,11 @@ public function testFilter($submittedData, $data, $paramName)
;
$qb->expects($this->once())
->method('setParameter')
->with($paramName, '%"'.$data['value'][0].'"%')
->with('foo_1', '%"'.$data['value'][0].'"%')
;
}

$form = $this->factory->create(ArrayFilterType::class);
$form = $this->factory->create(ArrayFilterType::class, null, $options);
$form->submit($submittedData);

$filter = $this->filterRegistry->resolveType($form);
Expand All @@ -73,19 +83,47 @@ public function getDataProvider(): iterable
yield [
['comparison' => ComparisonType::CONTAINS, 'value' => ['bar']],
['comparison' => 'like', 'value' => ['bar']],
'foo_1',
];

yield [
['comparison' => ComparisonType::NOT_CONTAINS, 'value' => ['bar']],
['comparison' => 'not like', 'value' => ['bar']],
'foo_2',
];

yield [
['comparison' => ComparisonType::CONTAINS, 'value' => []],
['comparison' => 'IS NULL', 'value' => []],
'foo_3',
];

yield [
['comparison' => ComparisonType::CONTAINS, 'value' => null],
['comparison' => 'IS NULL', 'value' => null],
[
'value_type_options' => [
'choices' => ['a' => 'a', 'b' => 'b', 'c' => 'c'],
],
],
];

yield [
['comparison' => ComparisonType::CONTAINS, 'value' => 'b'],
['comparison' => 'like', 'value' => ['b']],
[
'value_type_options' => [
'choices' => ['a' => 'a', 'b' => 'b', 'c' => 'c'],
],
],
];

yield [
['comparison' => ComparisonType::NOT_CONTAINS, 'value' => ['c']],
['comparison' => 'not like', 'value' => ['c']],
[
'value_type_options' => [
'multiple' => true,
'choices' => ['a' => 'a', 'b' => 'b', 'c' => 'c'],
],
],
];
}
}

0 comments on commit 62e9661

Please sign in to comment.