• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

api-platform / core / 6545986262

17 Oct 2023 10:35AM UTC coverage: 37.305% (+0.02%) from 37.285%
6545986262

push

github

web-flow
feat(elasticsearch): filtering on nested fields (#5835)

* feat(elasticsearch): filtering on nested fields

* Add additional checks and function doc for less confusion

* Fixing tests

56 of 56 new or added lines in 4 files covered. (100.0%)

10266 of 27519 relevant lines covered (37.31%)

19.99 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/src/Elasticsearch/Util/FieldDatatypeTrait.php
1
<?php
2

3
/*
4
 * This file is part of the API Platform project.
5
 *
6
 * (c) Kévin Dunglas <dunglas@gmail.com>
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\Elasticsearch\Util;
15

16
use ApiPlatform\Metadata\Exception\PropertyNotFoundException;
17
use ApiPlatform\Metadata\Property\Factory\PropertyMetadataFactoryInterface;
18
use ApiPlatform\Metadata\ResourceClassResolverInterface;
19
use Symfony\Component\PropertyInfo\Type;
20

21
/**
22
 * Field datatypes helpers.
23
 *
24
 * @internal
25
 *
26
 * @experimental
27
 *
28
 * @author Baptiste Meyer <baptiste.meyer@gmail.com>
29
 */
30
trait FieldDatatypeTrait
31
{
32
    private readonly PropertyMetadataFactoryInterface $propertyMetadataFactory;
33

34
    private readonly ResourceClassResolverInterface $resourceClassResolver;
35

36
    /**
37
     * Is the decomposed given property of the given resource class potentially mapped as a nested field in Elasticsearch?
38
     */
39
    private function isNestedField(string $resourceClass, string $property): bool
40
    {
41
        return null !== $this->getNestedFieldPath($resourceClass, $property);
×
42
    }
43

44
    /**
45
     * Get the nested path to the decomposed given property (e.g.: foo.bar.baz => foo.bar).
46
     *
47
     * Elasticsearch can save arrays of Objects as nested documents.
48
     * In the case of foo.bar.baz
49
     *   foo.bar will be returned if foo.bar is an array of objects.
50
     *   If neither foo nor bar is an array, it is not a nested property and will return null.
51
     */
52
    private function getNestedFieldPath(string $resourceClass, string $property): ?string
53
    {
54
        $properties = explode('.', $property);
×
55
        $currentProperty = array_shift($properties);
×
56

57
        if (!$properties) {
×
58
            return null;
×
59
        }
60

61
        try {
62
            $propertyMetadata = $this->propertyMetadataFactory->create($resourceClass, $currentProperty);
×
63
        } catch (PropertyNotFoundException) {
×
64
            return null;
×
65
        }
66

67
        $types = $propertyMetadata->getBuiltinTypes() ?? [];
×
68

69
        foreach ($types as $type) {
×
70
            if (
71
                Type::BUILTIN_TYPE_OBJECT === $type->getBuiltinType()
×
72
                && null !== ($nextResourceClass = $type->getClassName())
×
73
                && $this->resourceClassResolver->isResourceClass($nextResourceClass)
×
74
            ) {
75
                $nestedPath = $this->getNestedFieldPath($nextResourceClass, implode('.', $properties));
×
76

77
                return null === $nestedPath ? $nestedPath : "$currentProperty.$nestedPath";
×
78
            }
79

80
            if (
81
                null !== ($type = $type->getCollectionValueTypes()[0] ?? null)
×
82
                && Type::BUILTIN_TYPE_OBJECT === $type->getBuiltinType()
×
83
                && null !== ($className = $type->getClassName())
×
84
                && $this->resourceClassResolver->isResourceClass($className)
×
85
            ) {
86
                $nestedPath = $this->getNestedFieldPath($className, implode('.', $properties));
×
87

88
                return null === $nestedPath ? $currentProperty : "$currentProperty.$nestedPath";
×
89
            }
90
        }
91

92
        return null;
×
93
    }
94
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc