Skip to content

feat(doctrine): new iri search filters #7121

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 11 commits into
base: main
Choose a base branch
from
Draft
52 changes: 52 additions & 0 deletions src/Doctrine/Odm/Filter/ExactFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Doctrine\Odm\Filter;

use ApiPlatform\Metadata\OpenApiParameterFilterInterface;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\Metadata\Parameter;
use ApiPlatform\OpenApi\Model\Parameter as OpenApiParameter;
use Doctrine\ODM\MongoDB\Aggregation\Builder;

final class ExactFilter implements FilterInterface, OpenApiParameterFilterInterface
{
public function apply(Builder $aggregationBuilder, string $resourceClass, ?Operation $operation = null, array &$context = []): void

Check warning on line 24 in src/Doctrine/Odm/Filter/ExactFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/ExactFilter.php#L24

Added line #L24 was not covered by tests
{
if (!$parameter = $context['parameter'] ?? null) {
return;

Check warning on line 27 in src/Doctrine/Odm/Filter/ExactFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/ExactFilter.php#L26-L27

Added lines #L26 - L27 were not covered by tests
}

\assert($parameter instanceof Parameter);

Check warning on line 30 in src/Doctrine/Odm/Filter/ExactFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/ExactFilter.php#L30

Added line #L30 was not covered by tests

$values = (array) $parameter->getValue();

Check warning on line 32 in src/Doctrine/Odm/Filter/ExactFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/ExactFilter.php#L32

Added line #L32 was not covered by tests

//TODO: handle nested properties
$property = $parameter->getProperty();

Check warning on line 35 in src/Doctrine/Odm/Filter/ExactFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/ExactFilter.php#L35

Added line #L35 was not covered by tests

$aggregationBuilder
->match()
->field($property)
->in($values);

Check warning on line 40 in src/Doctrine/Odm/Filter/ExactFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/ExactFilter.php#L37-L40

Added lines #L37 - L40 were not covered by tests
}

public function getOpenApiParameters(Parameter $parameter): OpenApiParameter|array|null

Check warning on line 43 in src/Doctrine/Odm/Filter/ExactFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/ExactFilter.php#L43

Added line #L43 was not covered by tests
{
return new OpenApiParameter(name: $parameter->getKey().'[]', in: 'query', style: 'deepObject', explode: true);

Check warning on line 45 in src/Doctrine/Odm/Filter/ExactFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/ExactFilter.php#L45

Added line #L45 was not covered by tests
}

public function getDescription(string $resourceClass): array

Check warning on line 48 in src/Doctrine/Odm/Filter/ExactFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/ExactFilter.php#L48

Added line #L48 was not covered by tests
{
return [];

Check warning on line 50 in src/Doctrine/Odm/Filter/ExactFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/ExactFilter.php#L50

Added line #L50 was not covered by tests
}
}
62 changes: 62 additions & 0 deletions src/Doctrine/Odm/Filter/IriFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Doctrine\Odm\Filter;

use ApiPlatform\Metadata\OpenApiParameterFilterInterface;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\Metadata\Parameter;
use ApiPlatform\Metadata\ParameterProviderFilterInterface;
use ApiPlatform\OpenApi\Model\Parameter as OpenApiParameter;
use ApiPlatform\State\Provider\IriConverterParameterProvider;
use Doctrine\ODM\MongoDB\Aggregation\Builder;

final class IriFilter implements FilterInterface, OpenApiParameterFilterInterface, ParameterProviderFilterInterface
{
public function apply(Builder $aggregationBuilder, string $resourceClass, ?Operation $operation = null, array &$context = []): void

Check warning on line 26 in src/Doctrine/Odm/Filter/IriFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/IriFilter.php#L26

Added line #L26 was not covered by tests
{
if (!$parameter = $context['parameter'] ?? null) {
return;

Check warning on line 29 in src/Doctrine/Odm/Filter/IriFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/IriFilter.php#L28-L29

Added lines #L28 - L29 were not covered by tests
}

\assert($parameter instanceof Parameter);

Check warning on line 32 in src/Doctrine/Odm/Filter/IriFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/IriFilter.php#L32

Added line #L32 was not covered by tests

$value = $parameter->getValue();
if (!\is_array($value)) {
$value = [$value];

Check warning on line 36 in src/Doctrine/Odm/Filter/IriFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/IriFilter.php#L34-L36

Added lines #L34 - L36 were not covered by tests
}

//TODO: handle nested properties
$property = $parameter->getProperty();

Check warning on line 40 in src/Doctrine/Odm/Filter/IriFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/IriFilter.php#L40

Added line #L40 was not covered by tests

$aggregationBuilder
->match()
->field($property)
->in($value);

Check warning on line 45 in src/Doctrine/Odm/Filter/IriFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/IriFilter.php#L42-L45

Added lines #L42 - L45 were not covered by tests
}

public static function getParameterProvider(): string

Check warning on line 48 in src/Doctrine/Odm/Filter/IriFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/IriFilter.php#L48

Added line #L48 was not covered by tests
{
return IriConverterParameterProvider::class;

Check warning on line 50 in src/Doctrine/Odm/Filter/IriFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/IriFilter.php#L50

Added line #L50 was not covered by tests
}

public function getOpenApiParameters(Parameter $parameter): OpenApiParameter|array|null

Check warning on line 53 in src/Doctrine/Odm/Filter/IriFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/IriFilter.php#L53

Added line #L53 was not covered by tests
{
return new OpenApiParameter(name: $parameter->getKey().'[]', in: 'query', style: 'deepObject', explode: true);

Check warning on line 55 in src/Doctrine/Odm/Filter/IriFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/IriFilter.php#L55

Added line #L55 was not covered by tests
}

public function getDescription(string $resourceClass): array

Check warning on line 58 in src/Doctrine/Odm/Filter/IriFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/IriFilter.php#L58

Added line #L58 was not covered by tests
{
return [];

Check warning on line 60 in src/Doctrine/Odm/Filter/IriFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/IriFilter.php#L60

Added line #L60 was not covered by tests
}
}
57 changes: 57 additions & 0 deletions src/Doctrine/Odm/Filter/PartialSearchFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Doctrine\Odm\Filter;

use ApiPlatform\Metadata\OpenApiParameterFilterInterface;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\Metadata\Parameter;
use ApiPlatform\OpenApi\Model\Parameter as OpenApiParameter;
use Doctrine\ODM\MongoDB\Aggregation\Builder;
use MongoDB\BSON\Regex;

final class PartialSearchFilter implements FilterInterface, OpenApiParameterFilterInterface
{
public function apply(Builder $aggregationBuilder, string $resourceClass, ?Operation $operation = null, array &$context = []): void

Check warning on line 25 in src/Doctrine/Odm/Filter/PartialSearchFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/PartialSearchFilter.php#L25

Added line #L25 was not covered by tests
{
if (!$parameter = $context['parameter'] ?? null) {
return;

Check warning on line 28 in src/Doctrine/Odm/Filter/PartialSearchFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/PartialSearchFilter.php#L27-L28

Added lines #L27 - L28 were not covered by tests
}

\assert($parameter instanceof Parameter);

Check warning on line 31 in src/Doctrine/Odm/Filter/PartialSearchFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/PartialSearchFilter.php#L31

Added line #L31 was not covered by tests

$value = $parameter->getValue();
if (!\is_string($value) || '' === $value) {
return;

Check warning on line 35 in src/Doctrine/Odm/Filter/PartialSearchFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/PartialSearchFilter.php#L33-L35

Added lines #L33 - L35 were not covered by tests
}

//TODO: handle nested properties
$property = $parameter->getProperty();
$escapedValue = preg_quote($value, '/');

Check warning on line 40 in src/Doctrine/Odm/Filter/PartialSearchFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/PartialSearchFilter.php#L39-L40

Added lines #L39 - L40 were not covered by tests

$aggregationBuilder
->match()
->field($property)
->equals(new Regex($escapedValue, 'i'));

Check warning on line 45 in src/Doctrine/Odm/Filter/PartialSearchFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/PartialSearchFilter.php#L42-L45

Added lines #L42 - L45 were not covered by tests
}

public function getOpenApiParameters(Parameter $parameter): OpenApiParameter|array|null

Check warning on line 48 in src/Doctrine/Odm/Filter/PartialSearchFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/PartialSearchFilter.php#L48

Added line #L48 was not covered by tests
{
return new OpenApiParameter(name: $parameter->getKey().'[]', in: 'query', style: 'deepObject', explode: true);

Check warning on line 50 in src/Doctrine/Odm/Filter/PartialSearchFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/PartialSearchFilter.php#L50

Added line #L50 was not covered by tests
}

public function getDescription(string $resourceClass): array

Check warning on line 53 in src/Doctrine/Odm/Filter/PartialSearchFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/PartialSearchFilter.php#L53

Added line #L53 was not covered by tests
{
return [];

Check warning on line 55 in src/Doctrine/Odm/Filter/PartialSearchFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Odm/Filter/PartialSearchFilter.php#L55

Added line #L55 was not covered by tests
}
}
54 changes: 54 additions & 0 deletions src/Doctrine/Orm/Filter/ExactFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Doctrine\Orm\Filter;

use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\OpenApiParameterFilterInterface;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\Metadata\Parameter;
use ApiPlatform\OpenApi\Model\Parameter as OpenApiParameter;
use Doctrine\ORM\QueryBuilder;

final class ExactFilter implements FilterInterface, OpenApiParameterFilterInterface
{
public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, ?Operation $operation = null, array $context = []): void
{
if (!$parameter = $context['parameter'] ?? null) {
return;

Check warning on line 28 in src/Doctrine/Orm/Filter/ExactFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Orm/Filter/ExactFilter.php#L28

Added line #L28 was not covered by tests
}

$value = $parameter->getValue();
if (!\is_array($value)) {
$value = [$value];
}

$property = $parameter->getProperty();
$alias = $queryBuilder->getRootAliases()[0];
$parameterName = $queryNameGenerator->generateParameterName($property);

$queryBuilder
->andWhere(\sprintf('%s.%s = :%s', $alias, $property, $parameterName))
->setParameter($parameterName, $value);
}

public function getOpenApiParameters(Parameter $parameter): OpenApiParameter|array|null
{
return new OpenApiParameter(name: $parameter->getKey().'[]', in: 'query', style: 'deepObject', explode: true);
}

public function getDescription(string $resourceClass): array
{
return [];
}
}
62 changes: 62 additions & 0 deletions src/Doctrine/Orm/Filter/IriFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Doctrine\Orm\Filter;

use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\OpenApiParameterFilterInterface;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\Metadata\Parameter;
use ApiPlatform\Metadata\ParameterProviderFilterInterface;
use ApiPlatform\OpenApi\Model\Parameter as OpenApiParameter;
use ApiPlatform\State\Provider\IriConverterParameterProvider;
use Doctrine\ORM\QueryBuilder;

final class IriFilter implements FilterInterface, OpenApiParameterFilterInterface, ParameterProviderFilterInterface
{
public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, ?Operation $operation = null, array $context = []): void
{
if (!$parameter = $context['parameter'] ?? null) {
return;

Check warning on line 30 in src/Doctrine/Orm/Filter/IriFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Orm/Filter/IriFilter.php#L30

Added line #L30 was not covered by tests
}

$value = $parameter->getValue();
if (!\is_array($value)) {
$value = [$value];

Check warning on line 35 in src/Doctrine/Orm/Filter/IriFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Orm/Filter/IriFilter.php#L35

Added line #L35 was not covered by tests
}

$property = $parameter->getProperty();
$alias = $queryBuilder->getRootAliases()[0];
$parameterName = $queryNameGenerator->generateParameterName($property);

$queryBuilder
->join(\sprintf('%s.%s', $alias, $property), $parameterName)
->andWhere(\sprintf('%s IN(:%s)', $parameterName, $parameterName))
->setParameter($parameterName, $value);
}

public static function getParameterProvider(): string
{
return IriConverterParameterProvider::class;
}

public function getOpenApiParameters(Parameter $parameter): OpenApiParameter|array|null
{
return new OpenApiParameter(name: $parameter->getKey().'[]', in: 'query', style: 'deepObject', explode: true);
}

public function getDescription(string $resourceClass): array
{
return [];
}
}
58 changes: 58 additions & 0 deletions src/Doctrine/Orm/Filter/PartialSearchFilter.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
<?php

/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

declare(strict_types=1);

namespace ApiPlatform\Doctrine\Orm\Filter;

use ApiPlatform\Doctrine\Orm\Util\QueryNameGeneratorInterface;
use ApiPlatform\Metadata\OpenApiParameterFilterInterface;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\Metadata\Parameter;
use ApiPlatform\OpenApi\Model\Parameter as OpenApiParameter;
use Doctrine\ORM\QueryBuilder;

final class PartialSearchFilter implements FilterInterface, OpenApiParameterFilterInterface
{
public function apply(QueryBuilder $queryBuilder, QueryNameGeneratorInterface $queryNameGenerator, string $resourceClass, ?Operation $operation = null, array $context = []): void
{
if (!$parameter = $context['parameter'] ?? null) {
return;

Check warning on line 28 in src/Doctrine/Orm/Filter/PartialSearchFilter.php

View check run for this annotation

Codecov / codecov/patch

src/Doctrine/Orm/Filter/PartialSearchFilter.php#L28

Added line #L28 was not covered by tests
}

$value = $parameter->getValue();

$property = $parameter->getProperty();
$alias = $queryBuilder->getRootAliases()[0];
$field = $alias.'.'.$property;

$parameterName = $queryNameGenerator->generateParameterName($property);

$likeExpression = $queryBuilder->expr()->like(
'LOWER('.$field.')',
':'.$parameterName
);

$queryBuilder
->andWhere($likeExpression)
->setParameter($parameterName, '%'.strtolower($value).'%');
}

public function getOpenApiParameters(Parameter $parameter): OpenApiParameter|array|null
{
return new OpenApiParameter(name: $parameter->getKey().'[]', in: 'query', style: 'deepObject', explode: true);
}

public function getDescription(string $resourceClass): array
{
return [];
}
}
Loading
Loading