1313
1414namespace ApiPlatform \Laravel \Eloquent \State ;
1515
16+ use ApiPlatform \Metadata \Exception \OperationNotFoundException ;
17+ use ApiPlatform \Metadata \GraphQl \Query ;
1618use ApiPlatform \Metadata \HttpOperation ;
19+ use ApiPlatform \Metadata \Link ;
20+ use ApiPlatform \Metadata \Resource \Factory \ResourceMetadataCollectionFactoryInterface ;
1721use Illuminate \Contracts \Foundation \Application ;
1822use Illuminate \Database \Eloquent \Builder ;
1923use Illuminate \Database \Eloquent \Model ;
@@ -25,6 +29,7 @@ final class LinksHandler implements LinksHandlerInterface
2529{
2630 public function __construct (
2731 private readonly Application $ application ,
32+ private readonly ResourceMetadataCollectionFactoryInterface $ resourceMetadataCollectionFactory ,
2833 ) {
2934 }
3035
@@ -34,27 +39,64 @@ public function handleLinks(Builder $builder, array $uriVariables, array $contex
3439
3540 if ($ operation instanceof HttpOperation) {
3641 foreach (array_reverse ($ operation ->getUriVariables () ?? []) as $ uriVariable => $ link ) {
37- $ identifier = $ uriVariables [$ uriVariable ];
42+ $ builder = $ this ->buildQuery ($ builder , $ link , $ uriVariables [$ uriVariable ]);
43+ }
3844
39- if ( $ to = $ link -> getToProperty ()) {
40- $ builder = $ builder -> where ( $ builder -> getModel ()-> getTable (). ' . ' . $ builder -> getModel ()->{ $ to }()-> getForeignKeyName (), $ identifier );
45+ return $ builder ;
46+ }
4147
42- continue ;
43- }
48+ if (!($ linkClass = $ context ['linkClass ' ] ?? false )) {
49+ return $ builder ;
50+ }
4451
45- if ( $ from = $ link -> getFromProperty ()) {
46- $ relation = $ this -> application -> make ( $ link -> getFromClass ()) ;
47- $ builder = $ builder -> getModel ()-> where ( $ builder -> getModel ()-> getTable (). ' . ' . $ relation ->{ $ from }()-> getForeignKeyName (), $ identifier ) ;
52+ $ newLink = null ;
53+ $ linkedOperation = null ;
54+ $ linkProperty = $ context [ ' linkProperty ' ] ?? null ;
4855
49- continue ;
56+ try {
57+ $ resourceMetadataCollection = $ this ->resourceMetadataCollectionFactory ->create ($ linkClass );
58+ $ linkedOperation = $ resourceMetadataCollection ->getOperation ($ operation ->getName ());
59+ } catch (OperationNotFoundException ) {
60+ // Instead, we'll look for the first Query available.
61+ foreach ($ resourceMetadataCollection as $ resourceMetadata ) {
62+ foreach ($ resourceMetadata ->getGraphQlOperations () as $ op ) {
63+ if ($ op instanceof Query) {
64+ $ linkedOperation = $ op ;
65+ }
5066 }
67+ }
68+ }
5169
52- $ builder ->where ($ builder ->getModel ()->getTable ().'. ' .$ link ->getIdentifiers ()[0 ], $ identifier );
70+ if (!$ linkedOperation ) {
71+ return $ builder ;
72+ }
73+
74+ $ resourceClass = $ builder ->getModel ()::class;
75+ foreach ($ linkedOperation ->getLinks () ?? [] as $ link ) {
76+ if ($ resourceClass === $ link ->getToClass () && $ linkProperty === $ link ->getFromProperty ()) {
77+ $ newLink = $ link ;
78+ break ;
5379 }
80+ }
5481
82+ if (!$ newLink ) {
5583 return $ builder ;
5684 }
5785
58- return $ builder ;
86+ return $ this ->buildQuery ($ builder , $ newLink , $ uriVariables [$ newLink ->getIdentifiers ()[0 ]]);
87+ }
88+
89+ private function buildQuery (Builder $ builder , Link $ link , mixed $ identifier ): Builder
90+ {
91+ if ($ to = $ link ->getToProperty ()) {
92+ return $ builder ->where ($ builder ->getModel ()->{$ to }()->getQualifiedForeignKeyName (), $ identifier );
93+ }
94+
95+ if ($ from = $ link ->getFromProperty ()) {
96+ $ relation = $ this ->application ->make ($ link ->getFromClass ());
97+ return $ builder ->getModel ()->where ($ relation ->{$ from }()->getQualifiedForeignKeyName (), $ identifier );
98+ }
99+
100+ return $ builder ->where ($ builder ->getModel ()->qualifyColumn ($ link ->getIdentifiers ()[0 ]), $ identifier );
59101 }
60102}
0 commit comments