Skip to content

Commit a23d736

Browse files
author
Tobias Kündig
committed
Implemented Data Structures
Moved data structures to the end so resource groups don't get split up Consolidate all data structures into one section Restructured Applied style ci patch
1 parent fbabe54 commit a23d736

File tree

10 files changed

+307
-5
lines changed

10 files changed

+307
-5
lines changed

src/Annotation/Attribute.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ class Attribute
1313
public $identifier;
1414

1515
/**
16-
* @var string
16+
* @var mixed
1717
*/
1818
public $type = 'string';
1919

src/Annotation/DataStructures.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
namespace Dingo\Blueprint\Annotation;
4+
5+
/**
6+
* @Annotation
7+
*/
8+
class DataStructures
9+
{
10+
/**
11+
* @array<Type>
12+
*/
13+
public $value;
14+
}

src/Annotation/Property.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace Dingo\Blueprint\Annotation;
4+
5+
/**
6+
* @Annotation
7+
*/
8+
class Property
9+
{
10+
/**
11+
* @var string
12+
*/
13+
public $identifier;
14+
15+
/**
16+
* @var string
17+
*/
18+
public $type = 'string';
19+
20+
/**
21+
* @var string
22+
*/
23+
public $description;
24+
25+
/**
26+
* @var mixed
27+
*/
28+
public $sample;
29+
}

src/Annotation/Request.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,9 @@ class Request
3131
* @var array<Dingo\Blueprint\Annotation\Attribute>
3232
*/
3333
public $attributes;
34+
35+
/**
36+
* @var Dingo\Blueprint\Annotation\Type
37+
*/
38+
public $type;
3439
}

src/Annotation/Response.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,4 +31,9 @@ class Response
3131
* @var array<Dingo\Blueprint\Annotation\Attribute>
3232
*/
3333
public $attributes;
34+
35+
/**
36+
* @var Dingo\Blueprint\Annotation\Type
37+
*/
38+
public $type;
3439
}

src/Annotation/Type.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
namespace Dingo\Blueprint\Annotation;
4+
5+
/**
6+
* @Annotation
7+
*/
8+
class Type
9+
{
10+
/**
11+
* @var string
12+
*/
13+
public $identifier;
14+
15+
/**
16+
* @var mixed
17+
*/
18+
public $type;
19+
20+
/**
21+
* @array<Property>
22+
*/
23+
public $properties;
24+
}

src/Blueprint.php

Lines changed: 104 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Dingo\Blueprint;
44

5+
use Dingo\Blueprint\Annotation\Type;
56
use ReflectionClass;
67
use RuntimeException;
78
use Illuminate\Support\Str;
@@ -135,7 +136,9 @@ protected function generateContentsFromResources(Collection $resources, $name)
135136
$contents .= sprintf('# %s', $name);
136137
$contents .= $this->line(2);
137138

138-
$resources->each(function ($resource) use (&$contents) {
139+
$globalDataStructures = new Collection();
140+
141+
$resources->each(function ($resource) use (&$contents, $globalDataStructures) {
139142
if ($resource->getActions()->isEmpty()) {
140143
return;
141144
}
@@ -160,6 +163,10 @@ protected function generateContentsFromResources(Collection $resources, $name)
160163
$contents .= $description;
161164
}
162165

166+
if (($dataStructures = $resource->getDataStructures()) && ! $dataStructures->isEmpty()) {
167+
$globalDataStructures->push($dataStructures);
168+
}
169+
163170
if (($attributes = $action->getAttributes()) && ! $attributes->isEmpty()) {
164171
$this->appendAttributes($contents, $attributes);
165172
}
@@ -192,6 +199,15 @@ protected function generateContentsFromResources(Collection $resources, $name)
192199
$contents .= $this->line(2);
193200
});
194201

202+
if (! $globalDataStructures->isEmpty()) {
203+
$contents .= $this->line(1);
204+
$contents .= '# Data Structures';
205+
206+
$globalDataStructures->each(function ($dataStructure) use (&$contents) {
207+
$this->appendDataStructures($contents, $dataStructure);
208+
});
209+
}
210+
195211
return stripslashes(trim($contents));
196212
}
197213

@@ -217,15 +233,35 @@ protected function appendAttributes(&$contents, Collection $attributes, $indent
217233
$contents .= sprintf(': %s', $attribute->sample);
218234
}
219235

236+
$arrayType = false;
237+
if (is_array($attribute->type)) {
238+
$arrayType = true;
239+
$attribute->type = array_shift($attribute->type);
240+
}
241+
242+
$type = $this->resolveType($attribute->type);
243+
220244
$contents .= sprintf(
221245
' (%s, %s) - %s',
222-
$attribute->type,
246+
$arrayType ? "array[${type}]" : $type,
223247
$attribute->required ? 'required' : 'optional',
224248
$attribute->description
225249
);
226250
});
227251
}
228252

253+
/**
254+
* Append a type attribute to a resource or action.
255+
*
256+
* @param string $contents
257+
* @param Type $type
258+
* @param int $indent
259+
*/
260+
protected function appendType(&$contents, Type $type, $indent = 0)
261+
{
262+
$this->appendSection($contents, sprintf('Attributes (%s)', $type->identifier), $indent);
263+
}
264+
229265
/**
230266
* Append the parameters subsection to a resource or action.
231267
*
@@ -284,7 +320,9 @@ protected function appendResponse(&$contents, Annotation\Response $response, Res
284320
$this->appendHeaders($contents, array_merge($resource->getResponseHeaders(), $response->headers));
285321
}
286322

287-
if (isset($response->attributes)) {
323+
if (isset($response->type)) {
324+
$this->appendType($contents, $response->type, 1);
325+
} elseif (isset($response->attributes)) {
288326
$this->appendAttributes($contents, collect($response->attributes), 1);
289327
}
290328

@@ -316,7 +354,9 @@ protected function appendRequest(&$contents, $request, Resource $resource)
316354
$this->appendHeaders($contents, array_merge($resource->getRequestHeaders(), $request->headers));
317355
}
318356

319-
if (isset($request->attributes)) {
357+
if (isset($request->type)) {
358+
$this->appendType($contents, $request->type, 1);
359+
} elseif (isset($request->attributes)) {
320360
$this->appendAttributes($contents, collect($request->attributes), 1);
321361
}
322362

@@ -388,6 +428,66 @@ protected function appendSection(&$contents, $name, $indent = 0, $lines = 2)
388428
$contents .= '+ '.$name;
389429
}
390430

431+
/**
432+
* Append data structures.
433+
*
434+
* @param $contents
435+
* @param $allStructures
436+
*/
437+
protected function appendDataStructures(&$contents, $allStructures)
438+
{
439+
$allStructures->each(function ($dataStructures) use (&$contents) {
440+
collect($dataStructures->value)->each(function ($type) use (&$contents) {
441+
442+
$contents .= $this->line(2);
443+
$contents .= sprintf('## %s (%s)', $type->identifier, $this->resolveType($type->type));
444+
$contents .= $this->line(1);
445+
446+
if (isset($type->properties)) {
447+
$this->appendProperties($contents, collect($type->properties), -1, false);
448+
}
449+
});
450+
});
451+
}
452+
453+
/**
454+
* Resolves the name of a type from either a string or a Type class.
455+
*
456+
* @param string|Type $type
457+
*
458+
* @return string
459+
*/
460+
protected function resolveType($type)
461+
{
462+
return $type instanceof Type ? $type->identifier : $type;
463+
}
464+
465+
/**
466+
* Append the properties to a type.
467+
*
468+
* @param string $contents
469+
* @param \Illuminate\Support\Collection $properties
470+
*
471+
* @return void
472+
*/
473+
protected function appendProperties(&$contents, Collection $properties)
474+
{
475+
$properties->each(function ($property) use (&$contents) {
476+
$contents .= $this->line();
477+
$contents .= sprintf('+ %s', $property->identifier);
478+
479+
if ($property->sample) {
480+
$contents .= sprintf(': %s', $property->sample);
481+
}
482+
483+
$contents .= sprintf(
484+
' (%s) - %s',
485+
$property->type,
486+
$property->description
487+
);
488+
});
489+
}
490+
391491
/**
392492
* Prepare a body.
393493
*

src/Resource.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace Dingo\Blueprint;
44

5+
use Dingo\Blueprint\Annotation\DataStructures;
56
use Illuminate\Support\Collection;
67
use ReflectionClass;
78
use phpDocumentor\Reflection\DocBlock;
@@ -108,6 +109,18 @@ public function getActions()
108109
return $this->actions;
109110
}
110111

112+
/**
113+
* Get the data structures belonging to the resource.
114+
*
115+
* @return \Illuminate\Support\Collection
116+
*/
117+
public function getDataStructures()
118+
{
119+
return $this->annotations->filter(function ($annotation) {
120+
return $annotation instanceof DataStructures;
121+
});
122+
}
123+
111124
/**
112125
* get the resource URI.
113126
*

tests/BlueprintTest.php

Lines changed: 56 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -487,4 +487,60 @@ public function testGeneratingSimpleBlueprints()
487487

488488
$this->assertEquals(trim($expected), $blueprint->generate($resources, 'testing', 'v1', null));
489489
}
490+
491+
public function testGeneratingBlueprintsWithDataStructures()
492+
{
493+
$resources = new Collection([new Stubs\AccountController]);
494+
495+
$blueprint = new Blueprint(new SimpleAnnotationReader, new Filesystem);
496+
497+
$expected = <<<'EOT'
498+
FORMAT: 1A
499+
500+
# testing
501+
502+
# Account [/accounts]
503+
504+
## Show all accounts. [GET /accounts]
505+
506+
507+
+ Response 200 (application/json)
508+
509+
+ Attributes
510+
+ success: true (boolean, required) - Status of the request
511+
+ data (array[Account], required) - The account's data
512+
513+
## Show a specific account. [GET /accounts/1]
514+
515+
516+
+ Response 200 (application/json)
517+
518+
+ Attributes
519+
+ success: true (boolean, required) - Status of the request
520+
+ data (Deposit, required) - The account's data
521+
522+
## Create a new account. [POST /accounts]
523+
524+
525+
+ Request (application/json)
526+
527+
+ Attributes (Account)
528+
529+
+ Response 200 (application/json)
530+
531+
+ Attributes (Account)
532+
533+
534+
# Data Structures
535+
536+
## Account (object)
537+
538+
+ name: Savings (string) - The account name
539+
+ balance: 1200 (number) - The account balance
540+
541+
## Deposit (Account)
542+
543+
EOT;
544+
$this->assertEquals(trim($expected), $blueprint->generate($resources, 'testing', 'v1', null));
545+
}
490546
}

0 commit comments

Comments
 (0)