Skip to content

Commit 90bbf32

Browse files
committed
Merge pull request #49 from abacaphiliac/collection-input-filter
bug-fix: rendering of nested collections
2 parents 31be867 + 1545243 commit 90bbf32

File tree

5 files changed

+174
-5
lines changed

5 files changed

+174
-5
lines changed

src/ApiFactory.php

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -359,13 +359,12 @@ private function mapFields(array $fields, $prefix = '')
359359
$flatFields = [];
360360

361361
foreach ($fields as $idx => $field) {
362-
if (isset($field['type'])
362+
if (isset($field['type'], $field['input_filter'])
363363
&& ($field['type'] === CollectionInputFilter::class
364364
|| is_subclass_of($field['type'], CollectionInputFilter::class))
365-
&& isset($field['input_filter'])
366365
) {
367366
$filteredFields = array_diff_key($field['input_filter'], ['type' => 0]);
368-
$fullindex = $prefix ? sprintf('%s[]/%s', $prefix, $idx) : $idx . '[]';
367+
$fullindex = $prefix ? sprintf('%s/%s[]', $prefix, $idx) : $idx . '[]';
369368
$flatFields = array_merge($flatFields, $this->mapFields($filteredFields, $fullindex));
370369
continue;
371370
}

src/Service.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -235,7 +235,7 @@ public function setFields($fields)
235235
}
236236

237237
/**
238-
* @return array
238+
* @return Field[]
239239
*/
240240
public function getFields($type)
241241
{

test/ApiFactoryTest.php

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
use PHPUnit_Framework_TestCase as TestCase;
1010
use Zend\ModuleManager\ModuleManager;
1111
use ZF\Apigility\Documentation\ApiFactory;
12+
use ZF\Apigility\Documentation\Service;
1213
use ZF\Apigility\Provider\ApigilityProviderInterface;
1314
use ZF\Configuration\ModuleUtils;
1415

@@ -142,7 +143,7 @@ public function testCreateApi()
142143

143144
$this->assertEquals('Test', $api->getName());
144145
$this->assertEquals(1, $api->getVersion());
145-
$this->assertCount(6, $api->getServices());
146+
$this->assertCount(7, $api->getServices());
146147
}
147148

148149
public function testCreateRestService()
@@ -237,6 +238,37 @@ public function testCreateRestServiceWithCollection()
237238
$this->assertSame('AnotherCollection[]/FooBar', $fields[1]->getName());
238239
}
239240

241+
public function testCreateRestArtistsService()
242+
{
243+
$docConfig = include __DIR__ . '/TestAsset/module-config/documentation.config.php';
244+
245+
$api = $this->apiFactory->createApi('Test', 1);
246+
247+
$service = $this->apiFactory->createService($api, 'Bands');
248+
self::assertInstanceOf(Service::class, $service);
249+
250+
self::assertEquals('Bands', $service->getName());
251+
self::assertEquals(
252+
$docConfig['Test\V1\Rest\Bands\Controller']['description'],
253+
$service->getDescription()
254+
);
255+
256+
$fields = $service->getFields('input_filter');
257+
self::assertCount(11, $fields);
258+
259+
self::assertSame('name', $fields[0]->getName());
260+
self::assertSame('artists[]/first_name', $fields[1]->getName());
261+
self::assertSame('artists[]/last_name', $fields[2]->getName());
262+
self::assertSame('debut_album/title', $fields[3]->getName());
263+
self::assertSame('debut_album/release_date', $fields[4]->getName());
264+
self::assertSame('debut_album/tracks[]/number', $fields[5]->getName());
265+
self::assertSame('debut_album/tracks[]/title', $fields[6]->getName());
266+
self::assertSame('albums[]/title', $fields[7]->getName());
267+
self::assertSame('albums[]/release_date', $fields[8]->getName());
268+
self::assertSame('albums[]/tracks[]/number', $fields[9]->getName());
269+
self::assertSame('albums[]/tracks[]/title', $fields[10]->getName());
270+
}
271+
240272
public function testCreateRpcService()
241273
{
242274
$docConfig = include __DIR__ . '/TestAsset/module-config/documentation.config.php';

test/TestAsset/module-config/documentation.config.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,4 +86,7 @@
8686
],
8787
'description' => 'Ping the API',
8888
],
89+
'Test\\V1\\Rest\\Bands\\Controller' => [
90+
'description' => 'A REST service about our favorite musical Bands.',
91+
],
8992
];

test/TestAsset/module-config/module.config.php

Lines changed: 135 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,15 @@
6464
],
6565
],
6666
],
67+
'test.rest.bands' => [
68+
'type' => 'Segment',
69+
'options' => [
70+
'route' => '/bands[/:band_id]',
71+
'defaults' => [
72+
'controller' => 'Test\\V1\\Rest\\Bands\\Controller',
73+
],
74+
],
75+
],
6776
],
6877
],
6978
'zf-versioning' => [
@@ -80,6 +89,7 @@
8089
'Test\\V1\\Rest\\FooBar\\FooBarResource' => 'Test\\V1\\Rest\\FooBar\\FooBarResource',
8190
'Test\\V1\\Rest\\FooBarCollection\\FooBarResource' => 'Test\\V1\\Rest\\FooBarCollection\\FooBarResource',
8291
'Test\\V1\\Rest\\BooBaz\\BooBazResource' => 'Test\\V1\\Rest\\BooBaz\\BooBazResource',
92+
'Test\\V1\\Rest\\Bands\\BandsResource' => 'Test\\V1\\Rest\\Bands\\BandsResource',
8393
],
8494
],
8595
'zf-rest' => [
@@ -166,6 +176,28 @@
166176
'collection_class' => 'Test\\V1\\Rest\\EntityFields\\EntityFieldsCollection',
167177
'service_name' => 'EntityFields',
168178
],
179+
'Test\\V1\\Rest\\Bands\\Controller' => [
180+
'listener' => 'Test\\V1\\Rest\\Bands\\BandsResource',
181+
'route_name' => 'test.rest.bands',
182+
'route_identifier_name' => 'artist_id',
183+
'collection_name' => 'foo_bar',
184+
'entity_http_methods' => [
185+
0 => 'GET',
186+
1 => 'PATCH',
187+
2 => 'PUT',
188+
3 => 'DELETE',
189+
],
190+
'collection_http_methods' => [
191+
0 => 'GET',
192+
1 => 'POST',
193+
],
194+
'collection_query_whitelist' => [],
195+
'page_size' => 25,
196+
'page_size_param' => null,
197+
'entity_class' => 'Test\\V1\\Rest\\Bands\\ArtistEntity',
198+
'collection_class' => 'Test\\V1\\Rest\\Bands\\ArtistCollection',
199+
'service_name' => 'Bands',
200+
],
169201
],
170202
'zf-content-negotiation' => [
171203
'controllers' => [
@@ -174,6 +206,7 @@
174206
'Test\\V1\\Rest\\BooBaz\\Controller' => 'HalJson',
175207
'Test\\V1\\Rpc\\MyRpc\\Controller' => 'Json',
176208
'Test\\V1\\Rpc\\Ping\\Controller' => 'Json',
209+
'Test\\V1\\Rest\\Bands\\Controller' => 'HalJson',
177210
],
178211
'accept_whitelist' => [
179212
'Test\\V1\\Rest\\FooBar\\Controller' => [
@@ -206,6 +239,11 @@
206239
1 => 'application/json',
207240
2 => 'application/*+json',
208241
],
242+
'Test\\V1\\Rest\\Bands\\Controller' => [
243+
0 => 'application/vnd.test.v1+json',
244+
1 => 'application/hal+json',
245+
2 => 'application/json',
246+
],
209247
],
210248
'content_type_whitelist' => [
211249
'Test\\V1\\Rest\\FooBar\\Controller' => [
@@ -232,6 +270,10 @@
232270
0 => 'application/vnd.test.v1+json',
233271
1 => 'application/json',
234272
],
273+
'Test\\V1\\Rest\\Bands\\Controller' => [
274+
0 => 'application/vnd.test.v1+json',
275+
1 => 'application/json',
276+
],
235277
],
236278
],
237279
'zf-hal' => [
@@ -266,6 +308,12 @@
266308
'route_identifier_name' => 'id',
267309
'is_collection' => true,
268310
],
311+
'Test\\V1\\Rest\\Bands\\ArtistEntity' => [
312+
'entity_identifier_name' => 'id',
313+
'route_name' => 'test.rest.bands',
314+
'route_identifier_name' => 'artist_id',
315+
'hydrator' => 'Zend\\Hydrator\\ArraySerializable',
316+
],
269317
],
270318
],
271319
'controllers' => [
@@ -301,6 +349,9 @@
301349
'input_filter' => 'Test\\V1\\Rest\\EntityFields\\Validator',
302350
'PUT' => 'Test\\V1\\Rest\\EntityFields\\Validator\\Put',
303351
],
352+
'Test\\V1\\Rest\\Bands\\Controller' => [
353+
'input_filter' => 'Test\\V1\\Rest\\Bands\\Validator',
354+
],
304355
],
305356
'input_filter_specs' => [
306357
'Test\\V1\\Rest\\FooBar\\Validator' => [
@@ -407,6 +458,90 @@
407458
'description' => 'test_put',
408459
],
409460
],
461+
'Test\\V1\\Rest\\Bands\\Validator' => [
462+
[
463+
'name' => 'name',
464+
'required' => true,
465+
'description' => 'The name of the Band.',
466+
],
467+
'artists' => [
468+
'type' => Zend\InputFilter\CollectionInputFilter::class,
469+
'input_filter' => [
470+
'type' => \Zend\InputFilter\InputFilter::class,
471+
'first_name' => [
472+
'name' => 'first_name',
473+
'required' => true,
474+
'description' => 'The Artist\'s first name.',
475+
],
476+
'last_name' => [
477+
'name' => 'last_name',
478+
'required' => true,
479+
'description' => 'The Artist\'s last name.',
480+
],
481+
],
482+
],
483+
'debut_album' => [
484+
'type' => \Zend\InputFilter\InputFilter::class,
485+
'title' => [
486+
'name' => 'title',
487+
'required' => true,
488+
'description' => 'Album title.',
489+
],
490+
'release_date' => [
491+
'name' => 'release_date',
492+
'required' => true,
493+
'description' => 'Album release date.',
494+
],
495+
'tracks' => [
496+
'type' => Zend\InputFilter\CollectionInputFilter::class,
497+
'input_filter' => [
498+
'type' => \Zend\InputFilter\InputFilter::class,
499+
'number' => [
500+
'name' => 'number',
501+
'required' => true,
502+
'description' => 'Track number.',
503+
],
504+
'title' => [
505+
'name' => 'title',
506+
'required' => true,
507+
'description' => 'Track title.',
508+
],
509+
],
510+
],
511+
],
512+
'albums' => [
513+
'type' => Zend\InputFilter\CollectionInputFilter::class,
514+
'input_filter' => [
515+
'type' => \Zend\InputFilter\InputFilter::class,
516+
'title' => [
517+
'name' => 'title',
518+
'required' => true,
519+
'description' => 'Album title.',
520+
],
521+
'release_date' => [
522+
'name' => 'release_date',
523+
'required' => true,
524+
'description' => 'Album release date.',
525+
],
526+
'tracks' => [
527+
'type' => Zend\InputFilter\CollectionInputFilter::class,
528+
'input_filter' => [
529+
'type' => \Zend\InputFilter\InputFilter::class,
530+
'number' => [
531+
'name' => 'number',
532+
'required' => true,
533+
'description' => 'Track number.',
534+
],
535+
'title' => [
536+
'name' => 'title',
537+
'required' => true,
538+
'description' => 'Track title.',
539+
],
540+
],
541+
],
542+
],
543+
],
544+
],
410545
],
411546
'zf-mvc-auth' => [
412547
'authentication' => [

0 commit comments

Comments
 (0)