diff --git a/src/Filter/ArrayFilter.php b/src/Filter/ArrayFilter.php index 870bdf62ac..1b1c55a479 100644 --- a/src/Filter/ArrayFilter.php +++ b/src/Filter/ArrayFilter.php @@ -71,7 +71,9 @@ public function apply(QueryBuilder $queryBuilder, FilterDataDto $filterDataDto, $parameterName = $filterDataDto->getParameterName(); $value = $filterDataDto->getValue(); - $useQuotes = Types::SIMPLE_ARRAY === $fieldDto->getDoctrineMetadata()->get('type'); + // the filtered property is not necessarily configured as a displayed field + // of the current page, so $fieldDto can be null + $useQuotes = Types::SIMPLE_ARRAY === $fieldDto?->getDoctrineMetadata()->get('type'); if (null === $value || [] === $value) { $queryBuilder->andWhere(sprintf('%s.%s %s', $alias, $property, $comparison)); diff --git a/tests/Unit/Filter/ArrayFilterTest.php b/tests/Unit/Filter/ArrayFilterTest.php new file mode 100644 index 0000000000..b4a43bcddf --- /dev/null +++ b/tests/Unit/Filter/ArrayFilterTest.php @@ -0,0 +1,69 @@ +createQueryBuilder(); + $filterDataDto = $this->createFilterDataDto(['foo']); + + ArrayFilter::new('tags')->apply($queryBuilder, $filterDataDto, null, $this->createEntityDto()); + + $parameters = $queryBuilder->getParameters(); + $this->assertCount(1, $parameters); + $this->assertSame('%foo%', $parameters->first()->getValue()); + } + + public function testApplyWithSimpleArrayFieldUsesQuotedPattern(): void + { + $queryBuilder = $this->createQueryBuilder(); + $filterDataDto = $this->createFilterDataDto(['foo']); + + $fieldDto = TextField::new('tags')->getAsDto(); + $fieldDto->setDoctrineMetadata(['type' => Types::SIMPLE_ARRAY]); + + ArrayFilter::new('tags')->apply($queryBuilder, $filterDataDto, $fieldDto, $this->createEntityDto()); + + $parameters = $queryBuilder->getParameters(); + $this->assertCount(1, $parameters); + $this->assertSame('%"foo"%', $parameters->first()->getValue()); + } + + private function createQueryBuilder(): QueryBuilder + { + return new QueryBuilder($this->createMock(EntityManagerInterface::class)); + } + + /** + * @param list $value + */ + private function createFilterDataDto(array $value): FilterDataDto + { + $filterDto = ArrayFilter::new('tags')->getAsDto(); + + return FilterDataDto::new(0, $filterDto, 'entity', [ + 'comparison' => ComparisonType::CONTAINS, + 'value' => $value, + ]); + } + + private function createEntityDto(): EntityDto + { + return new EntityDto(\stdClass::class, new ClassMetadata(\stdClass::class)); + } +}