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

api-platform / core / 15133993414

20 May 2025 09:30AM UTC coverage: 26.313% (-1.2%) from 27.493%
15133993414

Pull #7161

github

web-flow
Merge e2c03d45f into 5459ba375
Pull Request #7161: fix(metadata): infer parameter string type from schema

0 of 2 new or added lines in 1 file covered. (0.0%)

11019 existing lines in 363 files now uncovered.

12898 of 49018 relevant lines covered (26.31%)

34.33 hits per line

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

92.31
/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
        /** @var ?ManagerRegistry $managerRegistry */
UNCOV
43
        $managerRegistry = $this->getManagerRegistry();
373✔
UNCOV
44
        $manager = $managerRegistry?->getManagerForClass($resourceClass);
373✔
45

UNCOV
46
        if ($manager) {
373✔
47
            return $manager->getClassMetadata($resourceClass);
372✔
48
        }
49

UNCOV
50
        return new MongoDbOdmClassMetadata($resourceClass);
134✔
51
    }
52

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

68
        foreach ($propertyParts['associations'] as $association) {
28✔
69
            $classMetadata = $this->getClassMetadata($resourceClass);
28✔
70

71
            if (!$classMetadata instanceof MongoDbOdmClassMetadata) {
28✔
72
                break;
×
73
            }
74

75
            if ($classMetadata->hasReference($association)) {
28✔
76
                $propertyAlias = "{$association}_lkup";
21✔
77
                // previous_association_lkup.association
78
                $localField = "$alias$association";
21✔
79
                // previous_association_lkup.association_lkup
80
                $alias .= $propertyAlias;
21✔
81
                $referenceMapping = $classMetadata->getFieldMapping($association);
21✔
82

83
                if (($isOwningSide = $referenceMapping['isOwningSide']) && MongoDbOdmClassMetadata::REFERENCE_STORE_AS_ID !== $referenceMapping['storeAs']) {
21✔
84
                    throw MappingException::cannotLookupDbRefReference($classMetadata->getReflectionClass()->getShortName(), $association);
1✔
85
                }
86
                if (!$isOwningSide) {
21✔
87
                    if (isset($referenceMapping['repositoryMethod']) || !isset($referenceMapping['mappedBy'])) {
3✔
88
                        throw MappingException::repositoryMethodLookupNotAllowed($classMetadata->getReflectionClass()->getShortName(), $association);
×
89
                    }
90

91
                    $targetClassMetadata = $this->getClassMetadata($referenceMapping['targetDocument']);
3✔
92
                    if ($targetClassMetadata instanceof MongoDbOdmClassMetadata && MongoDbOdmClassMetadata::REFERENCE_STORE_AS_ID !== $targetClassMetadata->getFieldMapping($referenceMapping['mappedBy'])['storeAs']) {
3✔
93
                        throw MappingException::cannotLookupDbRefReference($classMetadata->getReflectionClass()->getShortName(), $association);
1✔
94
                    }
95
                }
96

97
                $aggregationBuilder->lookup($classMetadata->getAssociationTargetClass($association))
21✔
98
                    ->localField($isOwningSide ? $localField : '_id')
21✔
99
                    ->foreignField($isOwningSide ? '_id' : $referenceMapping['mappedBy'])
21✔
100
                    ->alias($alias);
21✔
101
                $aggregationBuilder->unwind("\$$alias")
21✔
102
                    ->preserveNullAndEmptyArrays($preserveNullAndEmptyArrays);
21✔
103

104
                // association.property => association_lkup.property
105
                $property = substr_replace($property, $propertyAlias, strpos($property, (string) $association), \strlen((string) $association));
21✔
106
                $resourceClass = $classMetadata->getAssociationTargetClass($association);
21✔
107
                $alias .= '.';
21✔
108
            } elseif ($classMetadata->hasEmbed($association)) {
8✔
109
                $alias = "$association.";
8✔
110
                $resourceClass = $classMetadata->getAssociationTargetClass($association);
8✔
111
            }
112
        }
113

114
        if ('' === $alias) {
26✔
115
            throw new InvalidArgumentException(\sprintf('Cannot add lookups for property "%s" - property is not nested.', $property));
×
116
        }
117

118
        return [$property, $propertyParts['field'], $propertyParts['associations']];
26✔
119
    }
120
}
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

© 2025 Coveralls, Inc