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

api-platform / core / 16053734897

03 Jul 2025 02:52PM UTC coverage: 22.132% (-0.4%) from 22.566%
16053734897

Pull #7274

github

web-flow
Merge 459b4021a into 828b62a4e
Pull Request #7274: fix(symfony): restore graphql_playground option

3 of 3 new or added lines in 1 file covered. (100.0%)

3831 existing lines in 106 files now uncovered.

11560 of 52232 relevant lines covered (22.13%)

23.34 hits per line

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

10.26
/src/Doctrine/Odm/PropertyHelperTrait.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\Doctrine\Odm;
15

16
use ApiPlatform\Metadata\Exception\InvalidArgumentException;
17
use Doctrine\ODM\MongoDB\Aggregation\Builder;
18
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata as MongoDbOdmClassMetadata;
19
use Doctrine\ODM\MongoDB\Mapping\MappingException;
20
use Doctrine\Persistence\ManagerRegistry;
21
use Doctrine\Persistence\Mapping\ClassMetadata;
22

23
/**
24
 * Helper trait regarding a property in a MongoDB document using the resource metadata.
25
 *
26
 * @author Alan Poulain <contact@alanpoulain.eu>
27
 */
28
trait PropertyHelperTrait
29
{
30
    abstract protected function getManagerRegistry(): ?ManagerRegistry;
31

32
    /**
33
     * Splits the given property into parts.
34
     */
35
    abstract protected function splitPropertyParts(string $property, string $resourceClass): array;
36

37
    /**
38
     * Gets class metadata for the given resource.
39
     */
40
    protected function getClassMetadata(string $resourceClass): ClassMetadata
41
    {
42
        /**
43
         * @var ?ManagerRegistry $managerRegistry
44
         *
45
         * @phpstan-ignore varTag.nativeType (https://github.com/phpstan/phpstan/issues/9515)
46
         */
47
        $managerRegistry = $this->getManagerRegistry();
2✔
48
        $manager = $managerRegistry?->getManagerForClass($resourceClass);
2✔
49

50
        if ($manager) {
2✔
UNCOV
51
            return $manager->getClassMetadata($resourceClass);
×
52
        }
53

54
        return new MongoDbOdmClassMetadata($resourceClass);
2✔
55
    }
56

57
    /**
58
     * Adds the necessary lookups for a nested property.
59
     *
60
     * @throws InvalidArgumentException If property is not nested
61
     * @throws MappingException
62
     *
63
     * @return array An array where the first element is the $alias of the lookup,
64
     *               the second element is the $field name
65
     *               the third element is the $associations array
66
     */
67
    protected function addLookupsForNestedProperty(string $property, Builder $aggregationBuilder, string $resourceClass, bool $preserveNullAndEmptyArrays = false): array
68
    {
69
        $propertyParts = $this->splitPropertyParts($property, $resourceClass);
×
UNCOV
70
        $alias = '';
×
71

72
        foreach ($propertyParts['associations'] as $association) {
×
UNCOV
73
            $classMetadata = $this->getClassMetadata($resourceClass);
×
74

75
            if (!$classMetadata instanceof MongoDbOdmClassMetadata) {
×
76
                break;
×
77
            }
78

UNCOV
79
            if ($classMetadata->hasReference($association)) {
×
80
                $propertyAlias = "{$association}_lkup";
×
81
                // previous_association_lkup.association
UNCOV
82
                $localField = "$alias$association";
×
83
                // previous_association_lkup.association_lkup
84
                $alias .= $propertyAlias;
×
UNCOV
85
                $referenceMapping = $classMetadata->getFieldMapping($association);
×
86

87
                if (($isOwningSide = $referenceMapping['isOwningSide']) && MongoDbOdmClassMetadata::REFERENCE_STORE_AS_ID !== $referenceMapping['storeAs']) {
×
88
                    throw MappingException::cannotLookupDbRefReference($classMetadata->getReflectionClass()->getShortName(), $association);
×
89
                }
UNCOV
90
                if (!$isOwningSide) {
×
91
                    if (isset($referenceMapping['repositoryMethod']) || !isset($referenceMapping['mappedBy'])) {
×
92
                        throw MappingException::repositoryMethodLookupNotAllowed($classMetadata->getReflectionClass()->getShortName(), $association);
×
93
                    }
94

UNCOV
95
                    $targetClassMetadata = $this->getClassMetadata($referenceMapping['targetDocument']);
×
UNCOV
96
                    if ($targetClassMetadata instanceof MongoDbOdmClassMetadata && MongoDbOdmClassMetadata::REFERENCE_STORE_AS_ID !== $targetClassMetadata->getFieldMapping($referenceMapping['mappedBy'])['storeAs']) {
×
97
                        throw MappingException::cannotLookupDbRefReference($classMetadata->getReflectionClass()->getShortName(), $association);
×
98
                    }
99
                }
100

101
                $aggregationBuilder->lookup($classMetadata->getAssociationTargetClass($association))
×
102
                    ->localField($isOwningSide ? $localField : '_id')
×
UNCOV
103
                    ->foreignField($isOwningSide ? '_id' : $referenceMapping['mappedBy'])
×
UNCOV
104
                    ->alias($alias);
×
105
                $aggregationBuilder->unwind("\$$alias")
×
106
                    ->preserveNullAndEmptyArrays($preserveNullAndEmptyArrays);
×
107

108
                // association.property => association_lkup.property
109
                $property = substr_replace($property, $propertyAlias, strpos($property, (string) $association), \strlen((string) $association));
×
110
                $resourceClass = $classMetadata->getAssociationTargetClass($association);
×
UNCOV
111
                $alias .= '.';
×
UNCOV
112
            } elseif ($classMetadata->hasEmbed($association)) {
×
UNCOV
113
                $alias = "$association.";
×
114
                $resourceClass = $classMetadata->getAssociationTargetClass($association);
×
115
            }
116
        }
117

118
        if ('' === $alias) {
×
UNCOV
119
            throw new InvalidArgumentException(\sprintf('Cannot add lookups for property "%s" - property is not nested.', $property));
×
120
        }
121

UNCOV
122
        return [$property, $propertyParts['field'], $propertyParts['associations']];
×
123
    }
124
}
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