13
13
14
14
namespace ApiPlatform \Laravel \Eloquent \State ;
15
15
16
+ use ApiPlatform \Metadata \Exception \OperationNotFoundException ;
17
+ use ApiPlatform \Metadata \GraphQl \Operation ;
18
+ use ApiPlatform \Metadata \GraphQl \Query ;
16
19
use ApiPlatform \Metadata \HttpOperation ;
20
+ use ApiPlatform \Metadata \Link ;
21
+ use ApiPlatform \Metadata \Resource \Factory \ResourceMetadataCollectionFactoryInterface ;
17
22
use Illuminate \Contracts \Foundation \Application ;
18
23
use Illuminate \Database \Eloquent \Builder ;
19
24
use Illuminate \Database \Eloquent \Model ;
@@ -25,6 +30,7 @@ final class LinksHandler implements LinksHandlerInterface
25
30
{
26
31
public function __construct (
27
32
private readonly Application $ application ,
33
+ private readonly ResourceMetadataCollectionFactoryInterface $ resourceMetadataCollectionFactory ,
28
34
) {
29
35
}
30
36
@@ -34,27 +40,72 @@ public function handleLinks(Builder $builder, array $uriVariables, array $contex
34
40
35
41
if ($ operation instanceof HttpOperation) {
36
42
foreach (array_reverse ($ operation ->getUriVariables () ?? []) as $ uriVariable => $ link ) {
37
- $ identifier = $ uriVariables [$ uriVariable ];
43
+ $ builder = $ this ->buildQuery ($ builder , $ link , $ uriVariables [$ uriVariable ]);
44
+ }
38
45
39
- if ( $ to = $ link -> getToProperty ()) {
40
- $ builder = $ builder -> where ( $ builder -> getModel ()->{ $ to }()-> getQualifiedForeignKeyName (), $ identifier );
46
+ return $ builder ;
47
+ }
41
48
42
- continue ;
43
- }
49
+ if (!($ linkClass = $ context ['linkClass ' ] ?? false )) {
50
+ return $ builder ;
51
+ }
44
52
45
- if ( $ from = $ link -> getFromProperty ()) {
46
- $ relation = $ this -> application -> make ( $ link -> getFromClass ()) ;
47
- $ builder = $ builder -> getModel ()-> where ( $ relation ->{ $ from }()-> getQualifiedForeignKeyName (), $ identifier ) ;
53
+ $ newLink = null ;
54
+ $ linkedOperation = null ;
55
+ $ linkProperty = $ context [ ' linkProperty ' ] ?? null ;
48
56
49
- continue ;
57
+ try {
58
+ $ resourceMetadataCollection = $ this ->resourceMetadataCollectionFactory ->create ($ linkClass );
59
+ $ linkedOperation = $ resourceMetadataCollection ->getOperation ($ operation ->getName ());
60
+ } catch (OperationNotFoundException ) {
61
+ // Instead, we'll look for the first Query available.
62
+ foreach ($ resourceMetadataCollection as $ resourceMetadata ) {
63
+ foreach ($ resourceMetadata ->getGraphQlOperations () as $ op ) {
64
+ if ($ op instanceof Query) {
65
+ $ linkedOperation = $ op ;
66
+ }
50
67
}
68
+ }
69
+ }
70
+
71
+ if (!$ linkedOperation instanceof Operation) {
72
+ return $ builder ;
73
+ }
51
74
52
- $ builder ->where ($ builder ->getModel ()->qualifyColumn ($ link ->getIdentifiers ()[0 ]), $ identifier );
75
+ $ resourceClass = $ builder ->getModel ()::class;
76
+ foreach ($ linkedOperation ->getLinks () ?? [] as $ link ) {
77
+ if ($ resourceClass === $ link ->getToClass () && $ linkProperty === $ link ->getFromProperty ()) {
78
+ $ newLink = $ link ;
79
+ break ;
53
80
}
81
+ }
54
82
83
+ if (!$ newLink ) {
55
84
return $ builder ;
56
85
}
57
86
58
- return $ builder ;
87
+ return $ this ->buildQuery ($ builder , $ newLink , $ uriVariables [$ newLink ->getIdentifiers ()[0 ]]);
88
+ }
89
+
90
+ /**
91
+ * @param Builder<Model> $builder
92
+ *
93
+ * @throws \Illuminate\Contracts\Container\BindingResolutionException
94
+ *
95
+ * @return Builder<Model> $builder
96
+ */
97
+ private function buildQuery (Builder $ builder , Link $ link , mixed $ identifier ): Builder
98
+ {
99
+ if ($ to = $ link ->getToProperty ()) {
100
+ return $ builder ->where ($ builder ->getModel ()->{$ to }()->getQualifiedForeignKeyName (), $ identifier );
101
+ }
102
+
103
+ if ($ from = $ link ->getFromProperty ()) {
104
+ $ relation = $ this ->application ->make ($ link ->getFromClass ());
105
+
106
+ return $ builder ->getModel ()->where ($ relation ->{$ from }()->getQualifiedForeignKeyName (), $ identifier );
107
+ }
108
+
109
+ return $ builder ->where ($ builder ->getModel ()->qualifyColumn ($ link ->getIdentifiers ()[0 ]), $ identifier );
59
110
}
60
111
}
0 commit comments