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

api-platform / core / 3713134090

pending completion
3713134090

Pull #5254

github

GitHub
Merge b2ec54b3c into ac711530f
Pull Request #5254: [OpenApi] Add ApiResource::openapi and deprecate openapiContext

197 of 197 new or added lines in 5 files covered. (100.0%)

10372 of 12438 relevant lines covered (83.39%)

11.97 hits per line

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

59.49
/src/Doctrine/Orm/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\Orm\State;
15

16
use ApiPlatform\Doctrine\Common\State\LinksHandlerTrait as CommonLinksHandlerTrait;
17
use ApiPlatform\Doctrine\Orm\Util\QueryNameGenerator;
18
use ApiPlatform\Metadata\Operation;
19
use Doctrine\ORM\Mapping\ClassMetadataInfo;
20
use Doctrine\ORM\QueryBuilder;
21

22
trait LinksHandlerTrait
23
{
24
    use CommonLinksHandlerTrait;
25

26
    private function handleLinks(QueryBuilder $queryBuilder, array $identifiers, QueryNameGenerator $queryNameGenerator, array $context, string $resourceClass, Operation $operation): void
27
    {
28
        if (!$identifiers) {
14✔
29
            return;
8✔
30
        }
31

32
        $manager = $this->managerRegistry->getManagerForClass($resourceClass);
6✔
33
        $doctrineClassMetadata = $manager->getClassMetadata($resourceClass);
6✔
34
        $alias = $queryBuilder->getRootAliases()[0];
6✔
35

36
        $links = $this->getLinks($resourceClass, $operation, $context);
6✔
37

38
        if (!$links) {
6✔
39
            return;
×
40
        }
41

42
        $previousAlias = $alias;
6✔
43
        $previousJoinProperties = $doctrineClassMetadata->getIdentifierFieldNames();
6✔
44
        $expressions = [];
6✔
45
        $identifiers = array_reverse($identifiers);
6✔
46

47
        foreach (array_reverse($links) as $link) {
6✔
48
            if (null !== $link->getExpandedValue() || !$link->getFromClass()) {
6✔
49
                continue;
×
50
            }
51

52
            $identifierProperties = $link->getIdentifiers();
6✔
53
            $hasCompositeIdentifiers = 1 < \count($identifierProperties);
6✔
54

55
            if (!$link->getFromProperty() && !$link->getToProperty()) {
6✔
56
                $doctrineClassMetadata = $manager->getClassMetadata($link->getFromClass());
5✔
57
                $currentAlias = $link->getFromClass() === $resourceClass ? $alias : $queryNameGenerator->generateJoinAlias($alias);
5✔
58

59
                foreach ($identifierProperties as $identifierProperty) {
5✔
60
                    $placeholder = $queryNameGenerator->generateParameterName($identifierProperty);
5✔
61
                    $queryBuilder->andWhere("$currentAlias.$identifierProperty = :$placeholder");
5✔
62
                    $queryBuilder->setParameter($placeholder, $this->getIdentifierValue($identifiers, $hasCompositeIdentifiers ? $identifierProperty : null), $doctrineClassMetadata->getTypeOfField($identifierProperty));
5✔
63
                }
64

65
                $previousAlias = $currentAlias;
5✔
66
                $previousJoinProperties = $doctrineClassMetadata->getIdentifierFieldNames();
5✔
67
                continue;
5✔
68
            }
69

70
            $joinProperties = $doctrineClassMetadata->getIdentifierFieldNames();
1✔
71

72
            if ($link->getFromProperty() && !$link->getToProperty()) {
1✔
73
                $doctrineClassMetadata = $manager->getClassMetadata($link->getFromClass());
1✔
74
                $joinAlias = $queryNameGenerator->generateJoinAlias('m');
1✔
75
                $associationMapping = $doctrineClassMetadata->getAssociationMapping($link->getFromProperty()); // @phpstan-ignore-line
1✔
76
                $relationType = $associationMapping['type'];
1✔
77

78
                if ($relationType & ClassMetadataInfo::TO_MANY) {
1✔
79
                    $nextAlias = $queryNameGenerator->generateJoinAlias($alias);
×
80
                    $whereClause = [];
×
81
                    foreach ($identifierProperties as $identifierProperty) {
×
82
                        $placeholder = $queryNameGenerator->generateParameterName($identifierProperty);
×
83
                        $whereClause[] = "$nextAlias.{$identifierProperty} = :$placeholder";
×
84
                        $queryBuilder->setParameter($placeholder, $this->getIdentifierValue($identifiers, $hasCompositeIdentifiers ? $identifierProperty : null), $doctrineClassMetadata->getTypeOfField($identifierProperty));
×
85
                    }
86

87
                    $property = $associationMapping['mappedBy'] ?? $joinProperties[0];
×
88
                    $select = isset($associationMapping['mappedBy']) ? "IDENTITY($joinAlias.$property)" : "$joinAlias.$property";
×
89
                    $expressions["$previousAlias.{$property}"] = "SELECT $select FROM {$link->getFromClass()} $nextAlias INNER JOIN $nextAlias.{$associationMapping['fieldName']} $joinAlias WHERE ".implode(' AND ', $whereClause);
×
90
                    $previousAlias = $nextAlias;
×
91
                    continue;
×
92
                }
93

94
                // A single-valued association path expression to an inverse side is not supported in DQL queries.
95
                if ($relationType & ClassMetadataInfo::TO_ONE && !($associationMapping['isOwningSide'] ?? true)) {
1✔
96
                    $queryBuilder->innerJoin("$previousAlias.".$associationMapping['mappedBy'], $joinAlias);
×
97
                } else {
98
                    $queryBuilder->join(
1✔
99
                        $link->getFromClass(),
1✔
100
                        $joinAlias,
1✔
101
                        'WITH',
1✔
102
                        "$previousAlias.{$previousJoinProperties[0]} = $joinAlias.{$associationMapping['fieldName']}"
1✔
103
                    );
1✔
104
                }
105

106
                foreach ($identifierProperties as $identifierProperty) {
1✔
107
                    $placeholder = $queryNameGenerator->generateParameterName($identifierProperty);
1✔
108
                    $queryBuilder->andWhere("$joinAlias.$identifierProperty = :$placeholder");
1✔
109
                    $queryBuilder->setParameter($placeholder, $this->getIdentifierValue($identifiers, $hasCompositeIdentifiers ? $identifierProperty : null), $doctrineClassMetadata->getTypeOfField($identifierProperty));
1✔
110
                }
111

112
                $previousAlias = $joinAlias;
1✔
113
                $previousJoinProperties = $joinProperties;
1✔
114
                continue;
1✔
115
            }
116

117
            $joinAlias = $queryNameGenerator->generateJoinAlias($alias);
×
118
            $queryBuilder->join("{$previousAlias}.{$link->getToProperty()}", $joinAlias);
×
119

120
            foreach ($identifierProperties as $identifierProperty) {
×
121
                $placeholder = $queryNameGenerator->generateParameterName($identifierProperty);
×
122
                $queryBuilder->andWhere("$joinAlias.$identifierProperty = :$placeholder");
×
123
                $queryBuilder->setParameter($placeholder, $this->getIdentifierValue($identifiers, $hasCompositeIdentifiers ? $identifierProperty : null), $doctrineClassMetadata->getTypeOfField($identifierProperty));
×
124
            }
125

126
            $previousAlias = $joinAlias;
×
127
            $previousJoinProperties = $joinProperties;
×
128
        }
129

130
        if ($expressions) {
6✔
131
            $i = 0;
×
132
            $clause = '';
×
133
            foreach ($expressions as $alias => $expression) {
×
134
                if (0 === $i) {
×
135
                    $clause .= "$alias IN (".$expression;
×
136
                    ++$i;
×
137
                    continue;
×
138
                }
139

140
                $clause .= " AND $alias IN (".$expression;
×
141
                ++$i;
×
142
            }
143

144
            $queryBuilder->andWhere($clause.str_repeat(')', $i));
×
145
        }
146
    }
147
}
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