Completed
Push — master ( ac8ec4...1a57ac )
by Kévin
04:37 queued 11s
created

Elasticsearch/DataProvider/Filter/OrderFilter.php (1 issue)

1
<?php
2
3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
12
declare(strict_types=1);
13
14
namespace ApiPlatform\Core\Bridge\Elasticsearch\DataProvider\Filter;
15
16
use ApiPlatform\Core\Api\ResourceClassResolverInterface;
17
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
18
use ApiPlatform\Core\Metadata\Property\Factory\PropertyNameCollectionFactoryInterface;
19
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
20
21
/**
22
 * Order the collection by given properties.
23
 *
24
 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html
25
 *
26
 * @experimental
27
 *
28
 * @author Baptiste Meyer <[email protected]>
29
 */
30
final class OrderFilter extends AbstractFilter implements SortFilterInterface
31
{
32
    private $orderParameterName;
33
34
    /**
35
     * {@inheritdoc}
36
     */
37
    public function __construct(PropertyNameCollectionFactoryInterface $propertyNameCollectionFactory, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, ?NameConverterInterface $nameConverter = null, string $orderParameterName = 'order', ?array $properties = null)
38
    {
39
        parent::__construct($propertyNameCollectionFactory, $propertyMetadataFactory, $resourceClassResolver, $nameConverter, $properties);
40
41
        $this->orderParameterName = $orderParameterName;
42
    }
43
44
    /**
45
     * {@inheritdoc}
46
     */
47
    public function apply(array $clauseBody, string $resourceClass, ?string $operationName = null, array $context = []): array
48
    {
49
        if (!\is_array($properties = $context['filters'][$this->orderParameterName] ?? [])) {
50
            return $clauseBody;
51
        }
52
53
        $orders = [];
54
55
        foreach ($properties as $property => $direction) {
56
            [$type] = $this->getMetadata($resourceClass, $property);
57
58
            if (!$type) {
59
                continue;
60
            }
61
62
            if (empty($direction) && null !== $defaultDirection = $this->properties[$property] ?? null) {
63
                $direction = $defaultDirection;
64
            }
65
66
            if (!\in_array($direction = strtolower($direction), ['asc', 'desc'], true)) {
67
                continue;
68
            }
69
70
            $order = ['order' => $direction];
71
72
            if (null !== $nestedPath = $this->getNestedFieldPath($resourceClass, $property)) {
73
                $nestedPath = null === $this->nameConverter ? $nestedPath : $this->nameConverter->normalize($nestedPath, $resourceClass, null, $context);
0 ignored issues
show
The call to Symfony\Component\Serial...rInterface::normalize() has too many arguments starting with $resourceClass. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-call  annotation

73
                $nestedPath = null === $this->nameConverter ? $nestedPath : $this->nameConverter->/** @scrutinizer ignore-call */ normalize($nestedPath, $resourceClass, null, $context);

This check compares calls to functions or methods with their respective definitions. If the call has more arguments than are defined, it raises an issue.

If a function is defined several times with a different number of parameters, the check may pick up the wrong definition and report false positives. One codebase where this has been known to happen is Wordpress. Please note the @ignore annotation hint above.

Loading history...
74
                $order['nested'] = ['path' => $nestedPath];
75
            }
76
77
            $property = null === $this->nameConverter ? $property : $this->nameConverter->normalize($property, $resourceClass, null, $context);
78
            $orders[] = [$property => $order];
79
        }
80
81
        if (!$orders) {
82
            return $clauseBody;
83
        }
84
85
        return array_merge_recursive($clauseBody, $orders);
86
    }
87
88
    /**
89
     * {@inheritdoc}
90
     */
91
    public function getDescription(string $resourceClass): array
92
    {
93
        $description = [];
94
95
        foreach ($this->getProperties($resourceClass) as $property) {
96
            [$type] = $this->getMetadata($resourceClass, $property);
97
98
            if (!$type) {
99
                continue;
100
            }
101
102
            $description["$this->orderParameterName[$property]"] = [
103
                'property' => $property,
104
                'type' => 'string',
105
                'required' => false,
106
            ];
107
        }
108
109
        return $description;
110
    }
111
}
112