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

api-platform / core / 18089937549

29 Sep 2025 07:56AM UTC coverage: 21.764% (-0.3%) from 22.093%
18089937549

Pull #7416

github

web-flow
Merge 061bcc790 into abe0438be
Pull Request #7416: fix(laravel): serializer attributes on Eloquent methods

0 of 151 new or added lines in 11 files covered. (0.0%)

5028 existing lines in 173 files now uncovered.

11889 of 54626 relevant lines covered (21.76%)

25.32 hits per line

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

0.0
/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\Persistence\ManagerRegistry;
24

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

33
    private ManagerRegistry $managerRegistry;
34

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

UNCOV
41
        $links = $this->getLinks($resourceClass, $operation, $context);
×
42

UNCOV
43
        if (!$links) {
×
44
            return;
×
45
        }
46

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

UNCOV
53
        $executeOptions = $operation->getExtraProperties()['doctrine_mongodb']['execute_options'] ?? [];
×
54

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

58
    /**
59
     * @throws RuntimeException
60
     */
61
    private function buildAggregation(string $toClass, array $links, array $identifiers, array $context, array $executeOptions, string $previousAggregationClass, Builder $previousAggregationBuilder, Operation $operation): Builder
62
    {
UNCOV
63
        if (\count($links) <= 0) {
×
64
            return $previousAggregationBuilder;
×
65
        }
66

67
        /** @var Link $link */
UNCOV
68
        $link = array_shift($links);
×
69

UNCOV
70
        $fromClass = $link->getFromClass();
×
71
        $fromProperty = $link->getFromProperty();
×
72
        $toProperty = $link->getToProperty();
×
73
        $identifierProperties = $link->getIdentifiers();
×
74
        $hasCompositeIdentifiers = 1 < \count($identifierProperties);
×
75

UNCOV
76
        $aggregationClass = $fromClass;
×
77
        if ($toProperty) {
×
78
            $aggregationClass = $toClass;
×
79
        }
80

UNCOV
81
        $lookupProperty = $toProperty ?? $fromProperty;
×
82
        $lookupPropertyAlias = $lookupProperty ? "{$lookupProperty}_lkup" : null;
×
83

UNCOV
84
        $manager = $this->managerRegistry->getManagerForClass($aggregationClass);
×
85
        if (!$manager instanceof DocumentManager) {
×
86
            $aggregationClass = $this->getLinkFromClass($link, $operation);
×
87
            $manager = $this->managerRegistry->getManagerForClass($aggregationClass);
×
88

UNCOV
89
            if (!$manager instanceof DocumentManager) {
×
90
                throw new RuntimeException(\sprintf('The manager for "%s" must be an instance of "%s".', $aggregationClass, DocumentManager::class));
×
91
            }
92
        }
93

UNCOV
94
        $classMetadata = $manager->getClassMetadata($aggregationClass);
×
95

UNCOV
96
        $aggregation = $previousAggregationBuilder;
×
97
        if ($aggregationClass !== $previousAggregationClass) {
×
98
            $aggregation = $manager->createAggregationBuilder($aggregationClass);
×
99
        }
100

101
        if ($lookupProperty && $classMetadata->hasAssociation($lookupProperty)) {
×
102
            $aggregation->lookup($lookupProperty)->alias($lookupPropertyAlias);
×
103
        }
104

UNCOV
105
        if ($toProperty) {
×
106
            foreach ($identifierProperties as $identifierProperty) {
×
107
                $aggregation->match()->field(\sprintf('%s.%s', $lookupPropertyAlias, 'id' === $identifierProperty ? '_id' : $identifierProperty))->equals($this->getIdentifierValue($identifiers, $hasCompositeIdentifiers ? $identifierProperty : null));
×
108
            }
109
        } else {
110
            foreach ($identifierProperties as $identifierProperty) {
×
111
                $aggregation->match()->field($identifierProperty)->equals($this->getIdentifierValue($identifiers, $hasCompositeIdentifiers ? $identifierProperty : null));
×
112
            }
113
        }
114

115
        // Recurse aggregations
116
        $aggregation = $this->buildAggregation($fromClass, $links, $identifiers, $context, $executeOptions, $aggregationClass, $aggregation, $operation);
×
117

UNCOV
118
        if (null === $fromProperty || null !== $toProperty) {
×
UNCOV
119
            return $aggregation;
×
120
        }
121

UNCOV
122
        $results = $aggregation->getAggregation($executeOptions)->getIterator()->toArray();
×
123
        $in = [];
×
124
        foreach ($results as $result) {
×
UNCOV
125
            foreach ($result[$lookupPropertyAlias] ?? [] as $lookupResult) {
×
UNCOV
126
                $in[] = $lookupResult['_id'];
×
127
            }
128
        }
129
        $previousAggregationBuilder->match()->field('_id')->in($in);
×
130

131
        return $previousAggregationBuilder;
×
132
    }
133

134
    private function getLinkFromClass(Link $link, Operation $operation): string
135
    {
136
        $documentClass = $this->getStateOptionsClass($operation, $operation->getClass(), Options::class);
×
UNCOV
137
        $fromClass = $link->getFromClass();
×
UNCOV
138
        if ($fromClass === $operation->getClass() && $documentClass) {
×
UNCOV
139
            return $documentClass;
×
140
        }
141

142
        $operation = $this->resourceMetadataCollectionFactory->create($fromClass)->getOperation();
×
143

144
        if ($documentClass = $this->getStateOptionsClass($operation, null, Options::class)) {
×
UNCOV
145
            return $documentClass;
×
146
        }
147

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