Passed
Push — master ( 8bd912...d93388 )
by Alan
06:58 queued 02:20
created

DataProvider/Extension/SortExtension.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\Extension;
15
16
use ApiPlatform\Core\Api\ResourceClassResolverInterface;
17
use ApiPlatform\Core\Bridge\Elasticsearch\Api\IdentifierExtractorInterface;
18
use ApiPlatform\Core\Bridge\Elasticsearch\Util\FieldDatatypeTrait;
19
use ApiPlatform\Core\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
20
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
21
use Symfony\Component\Serializer\NameConverter\NameConverterInterface;
22
23
/**
24
 * Applies selected sorting while querying resource collection.
25
 *
26
 * @see https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html
27
 *
28
 * @experimental
29
 *
30
 * @author Baptiste Meyer <[email protected]>
31
 */
32
final class SortExtension implements RequestBodySearchCollectionExtensionInterface
33
{
34
    use FieldDatatypeTrait;
35
36
    private $defaultDirection;
37
    private $identifierExtractor;
38
    private $resourceMetadataFactory;
39
    private $nameConverter;
40
41
    public function __construct(ResourceMetadataFactoryInterface $resourceMetadataFactory, IdentifierExtractorInterface $identifierExtractor, PropertyMetadataFactoryInterface $propertyMetadataFactory, ResourceClassResolverInterface $resourceClassResolver, ?NameConverterInterface $nameConverter = null, ?string $defaultDirection = null)
42
    {
43
        $this->resourceMetadataFactory = $resourceMetadataFactory;
44
        $this->identifierExtractor = $identifierExtractor;
45
        $this->propertyMetadataFactory = $propertyMetadataFactory;
46
        $this->resourceClassResolver = $resourceClassResolver;
47
        $this->nameConverter = $nameConverter;
48
        $this->defaultDirection = $defaultDirection;
49
    }
50
51
    /**
52
     * {@inheritdoc}
53
     */
54
    public function applyToCollection(array $requestBody, string $resourceClass, ?string $operationName = null, array $context = []): array
55
    {
56
        $orders = [];
57
58
        if (
59
            null !== ($defaultOrder = $this->resourceMetadataFactory->create($resourceClass)->getAttribute('order'))
60
            && \is_array($defaultOrder)
61
        ) {
62
            foreach ($defaultOrder as $property => $direction) {
63
                if (\is_int($property)) {
64
                    $property = $direction;
65
                    $direction = 'asc';
66
                }
67
68
                $orders[] = $this->getOrder($resourceClass, $property, $direction);
69
            }
70
        } elseif (null !== $this->defaultDirection) {
71
            $orders[] = $this->getOrder(
72
                $resourceClass,
73
                $this->identifierExtractor->getIdentifierFromResourceClass($resourceClass),
74
                $this->defaultDirection
75
            );
76
        }
77
78
        if (!$orders) {
79
            return $requestBody;
80
        }
81
82
        $requestBody['sort'] = array_merge_recursive($requestBody['sort'] ?? [], $orders);
83
84
        return $requestBody;
85
    }
86
87
    private function getOrder(string $resourceClass, string $property, string $direction): array
88
    {
89
        $order = ['order' => strtolower($direction)];
90
91
        if (null !== $nestedPath = $this->getNestedFieldPath($resourceClass, $property)) {
92
            $nestedPath = null === $this->nameConverter ? $nestedPath : $this->nameConverter->normalize($nestedPath, $resourceClass);
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

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

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...
93
            $order['nested'] = ['path' => $nestedPath];
94
        }
95
96
        $property = null === $this->nameConverter ? $property : $this->nameConverter->normalize($property, $resourceClass);
97
98
        return [$property => $order];
99
    }
100
}
101