16
16
use ApiPlatform \Core \Bridge \Doctrine \Orm \Util \QueryNameGenerator ;
17
17
use ApiPlatform \Metadata \GraphQl \Operation as GraphQlOperation ;
18
18
use ApiPlatform \Metadata \Link ;
19
+ use ApiPlatform \Tests \Fixtures \TestBundle \Entity \DummyProduct ;
20
+ use Doctrine \ORM \Mapping \ClassMetadataInfo ;
19
21
use Doctrine \ORM \QueryBuilder ;
20
22
use Doctrine \Persistence \Mapping \ClassMetadata ;
21
23
@@ -30,113 +32,110 @@ private function handleLinks(QueryBuilder $queryBuilder, array $identifiers, Que
30
32
31
33
$ links = $ operation instanceof GraphQlOperation ? $ operation ->getLinks () : $ operation ->getUriVariables ();
32
34
33
- if ($ linkClass = $ context ['linkClass ' ] ?? false ) {
34
- foreach ($ links as $ link ) {
35
- if ($ linkClass === $ link ->getTargetClass ()) {
36
- foreach ($ identifiers as $ identifier => $ value ) {
37
- $ this ->applyLink ($ queryBuilder , $ queryNameGenerator , $ doctrineClassMetadata , $ alias , $ link , $ identifier , $ value );
38
- }
39
-
40
- return ;
41
- }
42
- }
43
- }
44
-
45
- if (null === $ links ) {
35
+ // if ($linkClass = $context['linkClass'] ?? false) {
36
+ // foreach ($links as $link) {
37
+ // if ($linkClass === $link->getTargetClass()) {
38
+ // foreach ($identifiers as $identifier => $value) {
39
+ // $this->applyLink($queryBuilder, $queryNameGenerator, $doctrineClassMetadata, $alias, $link, $identifier, $value);
40
+ // }
41
+ //
42
+ // return;
43
+ // }
44
+ // }
45
+ // }
46
+
47
+ if (! $ links ) {
46
48
return ;
47
49
}
48
50
49
- dd ($ links )
50
- dump ($ operation ->getUriTemplate ());
51
- $ aliases = [];
52
- $ previousContext = [];
53
- $ conditions = [];
54
- foreach ($ links as $ parameterName => $ link ) {
55
- $ identifier = $ link ->getIdentifiers ()[0 ];
56
- if (!isset ($ aliases [$ link ->getTargetClass ()])) {
57
- $ aliases [$ link ->getTargetClass ()] = $ link ->getTargetClass () === $ operation ->getClass () ? $ alias : $ queryNameGenerator ->generateJoinAlias ($ alias );
58
- }
51
+ $ previousAlias = $ alias ;
52
+ $ previousIdentifier = end ($ links )->getIdentifiers ()[0 ] ?? 'id ' ;
53
+ $ expressions = [];
54
+ $ i = 0 ;
59
55
60
- $ currentAlias = $ aliases [$ link ->getTargetClass ()];
61
- $ placeholder = $ queryNameGenerator ->generateParameterName ($ parameterName );
62
- // inverse == prop de la targetClass
63
- if (!$ link ->getInverseProperty () && !$ link ->getProperty () && !$ link ->getExpandedValue ()) {
64
- $ conditions [] = $ aliases [$ link ->getTargetClass ()] . ". $ identifier = : $ placeholder " ;
65
- $ previousContext = ['alias ' => $ currentAlias , 'identifier ' => $ identifier ];
56
+ foreach (array_reverse ($ links ) as $ parameterName => $ link ) {
57
+ if ($ link ->getExpandedValue () || !$ link ->getFromClass ()) {
58
+ ++$ i ;
66
59
continue ;
67
60
}
68
61
62
+ $ identifierProperty = $ link ->getIdentifiers ()[0 ] ?? 'id ' ;
63
+ $ currentAlias = $ i === 0 ? $ alias : $ queryNameGenerator ->generateJoinAlias ($ alias );
64
+ $ placeholder = $ queryNameGenerator ->generateParameterName ($ parameterName );
65
+
66
+ if (!$ link ->getFromProperty () && !$ link ->getToProperty ()) {
67
+ $ doctrineClassMetadata = $ manager ->getClassMetadata ($ link ->getFromClass ());
69
68
70
- if ( $ inverseProperty = $ link -> getInverseProperty ()) {
71
- $ joinAlias = $ queryNameGenerator -> generateJoinAlias ( $ alias );
72
- $ inverseAlias = $ queryNameGenerator -> generateJoinAlias ( $ alias ) ;
73
- $ conditions [] = "{ $ previousContext [ ' alias ' ]} . { $ previousContext [ ' identifier ' ]} IN (SELECT $ inverseAlias . $ identifier FROM { $ link -> getTargetClass ()} $ joinAlias JOIN $ joinAlias . $ inverseProperty $ inverseAlias WHERE $ joinAlias . $ identifier = $ placeholder ) " ;
74
- $ previousContext = [ ' alias ' => $ currentAlias , ' identifier ' => $ identifier ] ;
69
+ $ queryBuilder -> andWhere ( "{ $ currentAlias } . $ identifierProperty = : $ placeholder " );
70
+ $ queryBuilder -> setParameter ( $ placeholder , $ identifiers [ $ parameterName ], $ doctrineClassMetadata -> getTypeOfField ( $ identifierProperty ) );
71
+ $ previousAlias = $ currentAlias ;
72
+ $ previousIdentifier = $ identifierProperty ;
73
+ ++ $ i ;
75
74
continue ;
76
75
}
77
76
78
- dump ($ conditions );
79
- dd ($ link );
80
- // dd($link);
81
- // if ($link->getExpandedValue()) {
82
- // dd($queryBuilder->getDQL());
83
- // dd('test');
84
- // continue;
85
- // }
77
+ if ($ link ->getFromProperty ()) {
78
+ $ doctrineClassMetadata = $ manager ->getClassMetadata ($ link ->getFromClass ());
79
+ $ joinAlias = $ queryNameGenerator ->generateJoinAlias ('m ' );
80
+ $ assocationMapping = $ doctrineClassMetadata ->getAssociationMappings ()[$ link ->getFromProperty ()];
81
+ $ relationType = $ assocationMapping ['type ' ];
86
82
87
- // $this->applyLink($queryBuilder, $queryNameGenerator, $doctrineClassMetadata, $alias, $link, $identifiers[$parameterName] ?? null);
88
- }
89
- }
83
+ if ($ relationType & ClassMetadataInfo::TO_MANY ) {
84
+ $ nextAlias = $ queryNameGenerator ->generateJoinAlias ($ alias );
85
+
86
+ $ expressions ["$ previousAlias. $ previousIdentifier " ] = "SELECT $ joinAlias. {$ previousIdentifier } FROM {$ link ->getFromClass ()} $ nextAlias INNER JOIN $ nextAlias. {$ link ->getFromProperty ()} $ joinAlias WHERE $ nextAlias. {$ identifierProperty } = : $ placeholder " ;
87
+
88
+ $ queryBuilder ->setParameter ($ placeholder , $ identifiers [$ parameterName ], $ doctrineClassMetadata ->getTypeOfField ($ identifierProperty ));
89
+ $ previousAlias = $ nextAlias ;
90
+ ++$ i ;
91
+ continue ;
92
+ }
93
+
94
+
95
+ // A single-valued association path expression to an inverse side is not supported in DQL queries.
96
+ if ($ relationType & ClassMetadataInfo::TO_ONE && !$ assocationMapping ['isOwningSide ' ]) {
97
+ $ queryBuilder ->innerJoin ("$ previousAlias. " .$ assocationMapping ['mappedBy ' ], $ joinAlias );
98
+ } else {
99
+ $ queryBuilder ->join (
100
+ $ link ->getFromClass (),
101
+ $ joinAlias ,
102
+ 'with ' ,
103
+ "{$ previousAlias }. {$ previousIdentifier } = $ joinAlias. {$ link ->getFromProperty ()}"
104
+ );
105
+ }
106
+
107
+ $ queryBuilder ->andWhere ("$ joinAlias. $ identifierProperty = : $ placeholder " );
108
+ $ queryBuilder ->setParameter ($ placeholder , $ identifiers [$ parameterName ], $ doctrineClassMetadata ->getTypeOfField ($ identifierProperty ));
109
+ $ previousAlias = $ joinAlias ;
110
+ $ previousIdentifier = $ identifierProperty ;
111
+ ++$ i ;
112
+ continue ;
113
+ }
90
114
91
- private function applyLink (QueryBuilder $ queryBuilder , QueryNameGenerator $ queryNameGenerator , ClassMetadata $ doctrineClassMetadata , string $ alias , Link $ link , $ value = null )
92
- {
93
- $ propertyIdentifier = $ link ->getIdentifiers ()[0 ];
94
- $ placeholder = ': ' . $ queryNameGenerator ->generateParameterName ($ propertyIdentifier );
95
- if ($ inverseProperty = $ link ->getInverseProperty ()) {
96
115
$ joinAlias = $ queryNameGenerator ->generateJoinAlias ($ alias );
97
- $ inverseAlias = $ queryNameGenerator ->generateJoinAlias ($ alias );
98
-
99
- // SELECT o FROM ApiPlatform\Tests\Fixtures\TestBundle\Entity\ThirdLevel o
100
- // WHERE o.id IN (
101
- // SELECT o_a3.id FROM
102
- // ApiPlatform\Tests\Fixtures\TestBundle\Entity\Dummy o_a1
103
- // JOIN o_a1.relatedDummies o_a2
104
- // JOIN o_a2.thirdLevel o_a3
105
- // WHERE o_a1.id = :id_id
106
- // ) AND o.id = :id_id
107
-
108
- // $queryBuilder->join(
109
- // $link->getTargetClass(),
110
- // $joinAlias,
111
- // 'with',
112
- // "$alias.$propertyIdentifier = $joinAlias.$inverseProperty"
113
- // );
114
-
115
- $ expression = "$ alias. $ propertyIdentifier IN (SELECT $ inverseAlias. $ propertyIdentifier FROM {$ link ->getTargetClass ()} $ joinAlias JOIN $ joinAlias. $ inverseProperty $ inverseAlias WHERE $ joinAlias. $ propertyIdentifier = $ placeholder) " ;
116
-
117
- // $expression = $queryBuilder->expr()->eq(
118
- // "{$joinAlias}.{$propertyIdentifier}",
119
- // $placeholder
120
- // );
121
- } elseif ($ property = $ link ->getProperty ()) {
122
- $ joinAlias = $ queryNameGenerator ->generateJoinAlias ($ property );
123
-
124
- $ queryBuilder ->join (
125
- "$ alias. $ property " ,
126
- $ joinAlias ,
127
- );
128
-
129
- $ expression = $ queryBuilder ->expr ()->eq (
130
- "{$ joinAlias }. {$ propertyIdentifier }" ,
131
- $ placeholder
132
- );
133
- } else {
134
- $ expression = $ queryBuilder ->expr ()->eq (
135
- "{$ alias }. {$ propertyIdentifier }" , $ placeholder
136
- );
116
+ $ queryBuilder ->join ("{$ previousAlias }. {$ link ->getToProperty ()}" , $ joinAlias );
117
+ $ queryBuilder ->andWhere ("$ joinAlias. $ identifierProperty = : $ placeholder " );
118
+ $ queryBuilder ->setParameter ($ placeholder , $ identifiers [$ parameterName ], $ doctrineClassMetadata ->getTypeOfField ($ identifierProperty ));
119
+ $ previousAlias = $ joinAlias ;
120
+ $ previousIdentifier = $ identifierProperty ;
121
+ ++$ i ;
137
122
}
138
123
139
- $ queryBuilder ->andWhere ($ expression );
140
- $ queryBuilder ->setParameter ($ placeholder , $ value , $ doctrineClassMetadata ->getTypeOfField ($ propertyIdentifier ));
124
+ if ($ expressions ) {
125
+ $ i = 0 ;
126
+ $ clause = '' ;
127
+ foreach ($ expressions as $ alias => $ expression ) {
128
+ if ($ i === 0 ) {
129
+ $ clause .= "$ alias IN ( " . $ expression ;
130
+ $ i ++;
131
+ continue ;
132
+ }
133
+
134
+ $ clause .= " AND $ alias IN ( " . $ expression ;
135
+ $ i ++;
136
+ }
137
+
138
+ $ queryBuilder ->andWhere ($ clause . str_repeat (') ' , $ i ));
139
+ }
141
140
}
142
141
}
0 commit comments