1414namespace ApiPlatform \Metadata \Tests \Resource \Factory ;
1515
1616use ApiPlatform \Metadata \ApiProperty ;
17+ use ApiPlatform \Metadata \ApiResource ;
1718use ApiPlatform \Metadata \FilterInterface ;
19+ use ApiPlatform \Metadata \GetCollection ;
1820use ApiPlatform \Metadata \Parameters ;
1921use ApiPlatform \Metadata \Property \Factory \PropertyMetadataFactoryInterface ;
2022use ApiPlatform \Metadata \Property \Factory \PropertyNameCollectionFactoryInterface ;
@@ -36,8 +38,12 @@ public function testParameterFactory(): void
3638 $ nameCollection ->method ('create ' )->willReturn (new PropertyNameCollection (['id ' , 'hydra ' , 'everywhere ' ]));
3739 $ propertyMetadata = $ this ->createStub (PropertyMetadataFactoryInterface::class);
3840 $ propertyMetadata ->method ('create ' )->willReturnOnConsecutiveCalls (
39- new ApiProperty (identifier: true ), new ApiProperty (readable: true ), new ApiProperty (readable: true ),
40- new ApiProperty (identifier: true ), new ApiProperty (readable: true ), new ApiProperty (readable: true )
41+ new ApiProperty (identifier: true ),
42+ new ApiProperty (readable: true ),
43+ new ApiProperty (readable: true ),
44+ new ApiProperty (identifier: true ),
45+ new ApiProperty (readable: true ),
46+ new ApiProperty (readable: true )
4147 );
4248 $ filterLocator = $ this ->createStub (ContainerInterface::class);
4349 $ filterLocator ->method ('has ' )->willReturn (true );
@@ -77,14 +83,71 @@ public function getDescription(string $resourceClass): array
7783 $ this ->assertNull ($ everywhere ->getOpenApi ());
7884 }
7985
86+ public function testQueryParameterWithPropertyPlaceholder (): void
87+ {
88+ $ nameCollection = $ this ->createStub (PropertyNameCollectionFactoryInterface::class);
89+ $ nameCollection ->method ('create ' )->willReturn (new PropertyNameCollection (['id ' , 'name ' , 'description ' ]));
90+
91+ $ propertyMetadata = $ this ->createStub (PropertyMetadataFactoryInterface::class);
92+ $ propertyMetadata ->method ('create ' )->willReturn (
93+ new ApiProperty (readable: true ),
94+ );
95+
96+ $ filterLocator = $ this ->createStub (ContainerInterface::class);
97+ $ filterLocator ->method ('has ' )->willReturn (false ); // No specific filter logic needed for this test
98+
99+ $ parameterFactory = new ParameterResourceMetadataCollectionFactory (
100+ $ nameCollection ,
101+ $ propertyMetadata ,
102+ new AttributesResourceMetadataCollectionFactory (),
103+ $ filterLocator
104+ );
105+
106+ $ resourceMetadataCollection = $ parameterFactory ->create (HasParameterAttribute::class);
107+ $ operation = $ resourceMetadataCollection ->getOperation (forceCollection: true );
108+ $ parameters = $ operation ->getParameters ();
109+
110+ $ this ->assertInstanceOf (Parameters::class, $ parameters );
111+
112+ // Assert that the original parameter with ':property' is removed
113+ $ this ->assertFalse ($ parameters ->has ('search[:property] ' ));
114+
115+ // Assert that the new parameters are created and have the correct properties
116+ $ this ->assertTrue ($ parameters ->has ('search[name] ' ));
117+ $ this ->assertTrue ($ parameters ->has ('search[description] ' ));
118+ $ this ->assertTrue ($ parameters ->has ('static_param ' ));
119+
120+ $ searchNameParam = $ parameters ->get ('search[name] ' );
121+ $ this ->assertInstanceOf (QueryParameter::class, $ searchNameParam );
122+ $ this ->assertSame ('Search by property ' , $ searchNameParam ->getDescription ());
123+ $ this ->assertSame ('name ' , $ searchNameParam ->getProperty ());
124+ $ this ->assertSame ('search[name] ' , $ searchNameParam ->getKey ());
125+
126+ $ searchDescriptionParam = $ parameters ->get ('search[description] ' );
127+ $ this ->assertInstanceOf (QueryParameter::class, $ searchDescriptionParam );
128+ $ this ->assertSame ('Search by property ' , $ searchDescriptionParam ->getDescription ());
129+ $ this ->assertSame ('description ' , $ searchDescriptionParam ->getProperty ());
130+ $ this ->assertSame ('search[description] ' , $ searchDescriptionParam ->getKey ());
131+
132+ $ staticParam = $ parameters ->get ('static_param ' );
133+ $ this ->assertInstanceOf (QueryParameter::class, $ staticParam );
134+ $ this ->assertSame ('A static parameter ' , $ staticParam ->getDescription ());
135+ $ this ->assertNull ($ staticParam ->getProperty ());
136+ $ this ->assertSame ('static_param ' , $ staticParam ->getKey ());
137+ }
138+
80139 public function testParameterFactoryNoFilter (): void
81140 {
82141 $ nameCollection = $ this ->createStub (PropertyNameCollectionFactoryInterface::class);
83142 $ nameCollection ->method ('create ' )->willReturn (new PropertyNameCollection (['id ' , 'hydra ' , 'everywhere ' ]));
84143 $ propertyMetadata = $ this ->createStub (PropertyMetadataFactoryInterface::class);
85144 $ propertyMetadata ->method ('create ' )->willReturnOnConsecutiveCalls (
86- new ApiProperty (identifier: true ), new ApiProperty (readable: true ), new ApiProperty (readable: true ),
87- new ApiProperty (identifier: true ), new ApiProperty (readable: true ), new ApiProperty (readable: true )
145+ new ApiProperty (identifier: true ),
146+ new ApiProperty (readable: true ),
147+ new ApiProperty (readable: true ),
148+ new ApiProperty (identifier: true ),
149+ new ApiProperty (readable: true ),
150+ new ApiProperty (readable: true )
88151 );
89152 $ filterLocator = $ this ->createStub (ContainerInterface::class);
90153 $ filterLocator ->method ('has ' )->willReturn (false );
@@ -135,3 +198,25 @@ public function testParameterFactoryWithLimitedProperties(): void
135198 $ this ->assertSame (['name ' ], $ param ->getProperties ());
136199 }
137200}
201+
202+ #[ApiResource(
203+ operations: [
204+ new GetCollection (
205+ parameters: [
206+ 'search[:property] ' => new QueryParameter (
207+ description: 'Search by property ' ,
208+ properties: ['name ' , 'description ' ]
209+ ),
210+ 'static_param ' => new QueryParameter (
211+ description: 'A static parameter '
212+ ),
213+ ]
214+ ),
215+ ]
216+ )]
217+ class HasParameterAttribute
218+ {
219+ public $ id ;
220+ public $ name ;
221+ public $ description ;
222+ }
0 commit comments