-
-
Notifications
You must be signed in to change notification settings - Fork 963
Expand file tree
/
Copy pathParameterExtension.php
More file actions
118 lines (99 loc) · 4.36 KB
/
ParameterExtension.php
File metadata and controls
118 lines (99 loc) · 4.36 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
<?php
/*
* This file is part of the API Platform project.
*
* (c) Kévin Dunglas <dunglas@gmail.com>
*
* 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\Extension;
use ApiPlatform\Doctrine\Common\Filter\LoggerAwareInterface;
use ApiPlatform\Doctrine\Common\Filter\ManagerRegistryAwareInterface;
use ApiPlatform\Doctrine\Common\ParameterValueExtractorTrait;
use ApiPlatform\Doctrine\Odm\Filter\AbstractFilter;
use ApiPlatform\Doctrine\Odm\Filter\FilterInterface;
use ApiPlatform\Metadata\Operation;
use ApiPlatform\State\ParameterNotFound;
use Doctrine\Bundle\MongoDBBundle\ManagerRegistry;
use Doctrine\ODM\MongoDB\Aggregation\Builder;
use Psr\Container\ContainerInterface;
use Psr\Log\LoggerInterface;
/**
* Reads operation parameters and execute its filter.
*
* @author Antoine Bluchet <soyuka@gmail.com>
*/
final class ParameterExtension implements AggregationCollectionExtensionInterface, AggregationItemExtensionInterface
{
use ParameterValueExtractorTrait;
public function __construct(
private readonly ContainerInterface $filterLocator,
private readonly ?ManagerRegistry $managerRegistry = null,
private readonly ?LoggerInterface $logger = null,
) {
}
/**
* @param array<string, mixed> $context
*/
private function applyFilter(Builder $aggregationBuilder, ?string $resourceClass = null, ?Operation $operation = null, array &$context = []): void
{
foreach ($operation->getParameters() ?? [] as $parameter) {
if (null === ($v = $parameter->getValue()) || $v instanceof ParameterNotFound) {
continue;
}
$values = $this->extractParameterValue($parameter, $v);
if (null === ($filterId = $parameter->getFilter())) {
continue;
}
$filter = match (true) {
$filterId instanceof FilterInterface => $filterId,
\is_string($filterId) && $this->filterLocator->has($filterId) => $this->filterLocator->get($filterId),
default => null,
};
if (!$filter instanceof FilterInterface) {
continue;
}
if ($this->managerRegistry && $filter instanceof ManagerRegistryAwareInterface && !$filter->hasManagerRegistry()) {
$filter->setManagerRegistry($this->managerRegistry);
}
if ($this->logger && $filter instanceof LoggerAwareInterface && !$filter->hasLogger()) {
$filter->setLogger($this->logger);
}
if ($filter instanceof AbstractFilter && !$filter->getProperties()) {
$propertyKey = $parameter->getProperty() ?? $parameter->getKey();
if (str_contains($propertyKey, ':property')) {
$extraProperties = $parameter->getExtraProperties()['_properties'] ?? [];
foreach (array_keys($extraProperties) as $property) {
$properties[$property] = $parameter->getFilterContext();
}
} else {
$properties = [$propertyKey => $parameter->getFilterContext()];
}
$filter->setProperties($properties ?? []);
}
$specificContext = ['filters' => $values, 'parameter' => $parameter];
$filterContext = array_replace($context, $specificContext);
$filter->apply($aggregationBuilder, $resourceClass, $operation, $filterContext);
$context = array_replace($context, array_diff_key($filterContext, $specificContext));
}
if (isset($context['match'])) {
$aggregationBuilder->match()->addAnd($context['match']);
}
}
/**
* {@inheritdoc}
*/
public function applyToCollection(Builder $aggregationBuilder, string $resourceClass, ?Operation $operation = null, array &$context = []): void
{
$this->applyFilter($aggregationBuilder, $resourceClass, $operation, $context);
}
/**
* {@inheritdoc}
*/
public function applyToItem(Builder $aggregationBuilder, string $resourceClass, array $identifiers, ?Operation $operation = null, array &$context = []): void
{
$this->applyFilter($aggregationBuilder, $resourceClass, $operation, $context);
}
}