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

api-platform / core / 14837364288

05 May 2025 01:16PM UTC coverage: 8.457% (-0.002%) from 8.459%
14837364288

Pull #7122

github

web-flow
Merge 6606a9d5c into f55606b01
Pull Request #7122: Cherry picks from main (deprecations)

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

2030 existing lines in 147 files now uncovered.

13397 of 158416 relevant lines covered (8.46%)

22.88 hits per line

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

87.3
/src/Doctrine/Odm/State/LinksHandlerTrait.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\State;
15

16
use ApiPlatform\Doctrine\Common\State\LinksHandlerTrait as CommonLinksHandlerTrait;
17
use ApiPlatform\Metadata\Exception\RuntimeException;
18
use ApiPlatform\Metadata\Link;
19
use ApiPlatform\Metadata\Operation;
20
use ApiPlatform\State\Util\StateOptionsTrait;
21
use Doctrine\ODM\MongoDB\Aggregation\Builder;
22
use Doctrine\ODM\MongoDB\DocumentManager;
23
use Doctrine\ODM\MongoDB\Mapping\ClassMetadata;
24
use Doctrine\Persistence\ManagerRegistry;
25

26
/**
27
 * @internal
28
 */
29
trait LinksHandlerTrait
30
{
31
    use CommonLinksHandlerTrait;
32
    use StateOptionsTrait;
33

34
    private ManagerRegistry $managerRegistry;
35

36
    private function handleLinks(Builder $aggregationBuilder, array $identifiers, array $context, string $resourceClass, ?Operation $operation = null): void
37
    {
UNCOV
38
        if (!$identifiers) {
469✔
UNCOV
39
            return;
241✔
40
        }
41

UNCOV
42
        $links = $this->getLinks($resourceClass, $operation, $context);
241✔
43

UNCOV
44
        if (!$links) {
241✔
45
            return;
×
46
        }
47

UNCOV
48
        foreach ($links as $i => $link) {
241✔
UNCOV
49
            if (null !== $link->getExpandedValue()) {
241✔
UNCOV
50
                unset($links[$i]);
2✔
51
            }
52
        }
53

UNCOV
54
        $executeOptions = $operation->getExtraProperties()['doctrine_mongodb']['execute_options'] ?? [];
241✔
55

UNCOV
56
        $this->buildAggregation($resourceClass, array_reverse($links), array_reverse($identifiers), $context, $executeOptions, $resourceClass, $aggregationBuilder, $operation);
241✔
57
    }
58

59
    /**
60
     * @throws RuntimeException
61
     */
62
    private function buildAggregation(string $toClass, array $links, array $identifiers, array $context, array $executeOptions, string $previousAggregationClass, Builder $previousAggregationBuilder, ?Operation $operation = null): Builder
63
    {
UNCOV
64
        if (!$operation) {
241✔
65
            trigger_deprecation('api-platform/core', '3.2', 'In API Platform 4 the last argument "operation" will be required and this trait will be internal. Use the "handleLinks" feature instead.');
×
66
        }
67

UNCOV
68
        if (\count($links) <= 0) {
241✔
UNCOV
69
            return $previousAggregationBuilder;
241✔
70
        }
71

72
        /** @var Link $link */
UNCOV
73
        $link = array_shift($links);
241✔
74

UNCOV
75
        $fromClass = $link->getFromClass();
241✔
UNCOV
76
        $fromProperty = $link->getFromProperty();
241✔
UNCOV
77
        $toProperty = $link->getToProperty();
241✔
UNCOV
78
        $identifierProperties = $link->getIdentifiers();
241✔
UNCOV
79
        $hasCompositeIdentifiers = 1 < \count($identifierProperties);
241✔
80

UNCOV
81
        $aggregationClass = $fromClass;
241✔
UNCOV
82
        if ($toProperty) {
241✔
UNCOV
83
            $aggregationClass = $toClass;
22✔
84
        }
85

UNCOV
86
        $lookupProperty = $toProperty ?? $fromProperty;
241✔
UNCOV
87
        $lookupPropertyAlias = $lookupProperty ? "{$lookupProperty}_lkup" : null;
241✔
88

UNCOV
89
        $manager = $this->managerRegistry->getManagerForClass($aggregationClass);
241✔
UNCOV
90
        if (!$manager instanceof DocumentManager) {
241✔
UNCOV
91
            if ($operation) {
1✔
UNCOV
92
                $aggregationClass = $this->getLinkFromClass($link, $operation);
1✔
UNCOV
93
                $manager = $this->managerRegistry->getManagerForClass($aggregationClass);
1✔
94
            }
95

UNCOV
96
            if (!$manager instanceof DocumentManager) {
1✔
97
                throw new RuntimeException(\sprintf('The manager for "%s" must be an instance of "%s".', $aggregationClass, DocumentManager::class));
×
98
            }
99
        }
100

UNCOV
101
        $classMetadata = $manager->getClassMetadata($aggregationClass);
241✔
102

UNCOV
103
        if (!$classMetadata instanceof ClassMetadata) {
241✔
104
            throw new RuntimeException(\sprintf('The class metadata for "%s" must be an instance of "%s".', $aggregationClass, ClassMetadata::class));
×
105
        }
106

UNCOV
107
        $aggregation = $previousAggregationBuilder;
241✔
UNCOV
108
        if ($aggregationClass !== $previousAggregationClass) {
241✔
UNCOV
109
            $aggregation = $manager->createAggregationBuilder($aggregationClass);
34✔
110
        }
111

UNCOV
112
        if ($lookupProperty && $classMetadata->hasAssociation($lookupProperty)) {
241✔
UNCOV
113
            $aggregation->lookup($lookupProperty)->alias($lookupPropertyAlias);
56✔
114
        }
115

UNCOV
116
        if ($toProperty) {
241✔
UNCOV
117
            foreach ($identifierProperties as $identifierProperty) {
22✔
UNCOV
118
                $aggregation->match()->field(\sprintf('%s.%s', $lookupPropertyAlias, 'id' === $identifierProperty ? '_id' : $identifierProperty))->equals($this->getIdentifierValue($identifiers, $hasCompositeIdentifiers ? $identifierProperty : null));
22✔
119
            }
120
        } else {
UNCOV
121
            foreach ($identifierProperties as $identifierProperty) {
228✔
UNCOV
122
                $aggregation->match()->field($identifierProperty)->equals($this->getIdentifierValue($identifiers, $hasCompositeIdentifiers ? $identifierProperty : null));
228✔
123
            }
124
        }
125

126
        // Recurse aggregations
UNCOV
127
        $aggregation = $this->buildAggregation($fromClass, $links, $identifiers, $context, $executeOptions, $aggregationClass, $aggregation, $operation);
241✔
128

UNCOV
129
        if (null === $fromProperty || null !== $toProperty) {
241✔
UNCOV
130
            return $aggregation;
221✔
131
        }
132

UNCOV
133
        $results = $aggregation->getAggregation($executeOptions)->getIterator()->toArray();
34✔
UNCOV
134
        $in = [];
34✔
UNCOV
135
        foreach ($results as $result) {
34✔
UNCOV
136
            foreach ($result[$lookupPropertyAlias] ?? [] as $lookupResult) {
33✔
UNCOV
137
                $in[] = $lookupResult['_id'];
32✔
138
            }
139
        }
UNCOV
140
        $previousAggregationBuilder->match()->field('_id')->in($in);
34✔
141

UNCOV
142
        return $previousAggregationBuilder;
34✔
143
    }
144

145
    private function getLinkFromClass(Link $link, Operation $operation): string
146
    {
UNCOV
147
        $documentClass = $this->getStateOptionsClass($operation, $operation->getClass(), Options::class);
1✔
UNCOV
148
        $fromClass = $link->getFromClass();
1✔
UNCOV
149
        if ($fromClass === $operation->getClass() && $documentClass) {
1✔
UNCOV
150
            return $documentClass;
1✔
151
        }
152

153
        $operation = $this->resourceMetadataCollectionFactory->create($fromClass)->getOperation();
×
154

155
        if ($documentClass = $this->getStateOptionsClass($operation, null, Options::class)) {
×
156
            return $documentClass;
×
157
        }
158

159
        throw new \Exception('Can not found a doctrine class for this link.');
×
160
    }
161
}
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