Skip to content

Commit c7b0c79

Browse files
committed
Merge remote-tracking branch 'origin/master'
2 parents 9b070e7 + fc16f27 commit c7b0c79

File tree

8 files changed

+102
-8
lines changed

8 files changed

+102
-8
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
1313

1414
### Removed
1515

16+
## [3.8.0] - Wednesday, 29 May 2019
17+
### Added
18+
- Support for PHP array callable syntax in route action (https://github.com/mpociot/laravel-apidoc-generator/pull/516)
19+
1620
## [3.7.3] - Thursday, 23 May 2019
1721
### Fixed
1822
- Added faker_seed (https://github.com/mpociot/laravel-apidoc-generator/commit/d2901e51a68c17066d4dd96054ff5bfdf124945b)

src/Commands/GenerateDocumentation.php

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use ReflectionException;
88
use Illuminate\Routing\Route;
99
use Illuminate\Console\Command;
10+
use Mpociot\ApiDoc\Tools\Utils;
1011
use Mpociot\Reflection\DocBlock;
1112
use Illuminate\Support\Collection;
1213
use Illuminate\Support\Facades\URL;
@@ -217,7 +218,7 @@ private function processRoutes(Generator $generator, array $routes)
217218
foreach ($routes as $routeItem) {
218219
$route = $routeItem['route'];
219220
/** @var Route $route */
220-
if ($this->isValidRoute($route) && $this->isRouteVisibleForDocumentation($route->getAction()['uses'])) {
221+
if ($this->isValidRoute($route) && $this->isRouteVisibleForDocumentation($route->getAction())) {
221222
$parsedRoutes[] = $generator->processRoute($route, $routeItem['apply']);
222223
$this->info('Processed route: ['.implode(',', $generator->getMethods($route)).'] '.$generator->getUri($route));
223224
} else {
@@ -235,19 +236,24 @@ private function processRoutes(Generator $generator, array $routes)
235236
*/
236237
private function isValidRoute(Route $route)
237238
{
238-
return ! is_callable($route->getAction()['uses']) && ! is_null($route->getAction()['uses']);
239+
$action = Utils::getRouteActionUses($route->getAction());
240+
if (is_array($action)) {
241+
$action = implode('@', $action);
242+
}
243+
244+
return ! is_callable($action) && ! is_null($action);
239245
}
240246

241247
/**
242-
* @param $route
248+
* @param $action
243249
*
244250
* @throws ReflectionException
245251
*
246252
* @return bool
247253
*/
248-
private function isRouteVisibleForDocumentation($route)
254+
private function isRouteVisibleForDocumentation($action)
249255
{
250-
list($class, $method) = explode('@', $route);
256+
list($class, $method) = Utils::getRouteActionUses($action);
251257
$reflection = new ReflectionClass($class);
252258

253259
if (! $reflection->hasMethod($method)) {
@@ -260,7 +266,7 @@ private function isRouteVisibleForDocumentation($route)
260266
$phpdoc = new DocBlock($comment);
261267

262268
return collect($phpdoc->getTags())
263-
->filter(function ($tag) use ($route) {
269+
->filter(function ($tag) use ($action) {
264270
return $tag->getName() === 'hideFromAPIDocumentation';
265271
})
266272
->isEmpty();

src/Tools/Generator.php

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,8 +53,7 @@ public function getMethods(Route $route)
5353
*/
5454
public function processRoute(Route $route, array $rulesToApply = [])
5555
{
56-
$routeAction = $route->getAction();
57-
list($class, $method) = explode('@', $routeAction['uses']);
56+
list($class, $method) = Utils::getRouteActionUses($route->getAction());
5857
$controller = new ReflectionClass($class);
5958
$method = $controller->getMethod($method);
6059

src/Tools/Utils.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,28 @@ public static function getFullUrl(Route $route, array $bindings = []): string
1414
return self::replaceUrlParameterBindings($uri, $bindings);
1515
}
1616

17+
/**
18+
* @param array $action
19+
*
20+
* @return array|null
21+
*/
22+
public static function getRouteActionUses(array $action)
23+
{
24+
if ($action['uses'] !== null) {
25+
if (is_array($action['uses'])) {
26+
return $action['uses'];
27+
} elseif (is_string($action['uses'])) {
28+
return explode('@', $action['uses']);
29+
}
30+
}
31+
if (array_key_exists(0, $action) && array_key_exists(1, $action)) {
32+
return [
33+
0 => $action[0],
34+
1 => $action[1],
35+
];
36+
}
37+
}
38+
1739
/**
1840
* Transform parameters in URLs into real values (/users/{user} -> /users/2).
1941
* Uses bindings specified by caller, otherwise just uses '1'.

tests/GenerateDocumentationTest.php

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,35 @@ public function console_command_does_not_work_with_closure_using_dingo()
9393
$this->assertContains('Processed route: [GET] test', $output);
9494
}
9595

96+
/** @test */
97+
public function console_command_work_with_routes_uses_array()
98+
{
99+
RouteFacade::get('/api/array/test', [TestController::class, 'withEndpointDescription']);
100+
101+
config(['apidoc.routes.0.match.prefixes' => ['api/*']]);
102+
$output = $this->artisan('apidoc:generate');
103+
104+
$this->assertNotContains('Skipping route: [GET] api/array/test', $output);
105+
$this->assertContains('Processed route: [GET] api/array/test', $output);
106+
}
107+
108+
/** @test */
109+
public function console_command_work_with_dingo_routes_uses_array()
110+
{
111+
$api = app(\Dingo\Api\Routing\Router::class);
112+
$api->version('v1', function ($api) {
113+
$api->get('/array/dingo/test', [TestController::class, 'withEndpointDescription']);
114+
});
115+
116+
config(['apidoc.router' => 'dingo']);
117+
config(['apidoc.routes.0.match.prefixes' => ['*']]);
118+
config(['apidoc.routes.0.match.versions' => ['v1']]);
119+
$output = $this->artisan('apidoc:generate');
120+
121+
$this->assertNotContains('Skipping route: [GET] array/dingo/test', $output);
122+
$this->assertContains('Processed route: [GET] array/dingo/test', $output);
123+
}
124+
96125
/** @test */
97126
public function can_skip_single_routes()
98127
{

tests/Unit/DingoGeneratorTest.php

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,16 @@ public function createRoute(string $httpMethod, string $path, string $controller
3434

3535
return $route;
3636
}
37+
38+
public function createRouteUsesArray(string $httpMethod, string $path, string $controllerMethod, $register = false)
39+
{
40+
$route = null;
41+
/** @var Router $api */
42+
$api = app(Router::class);
43+
$api->version('v1', function (Router $api) use ($controllerMethod, $path, $httpMethod, &$route) {
44+
$route = $api->$httpMethod($path, [TestController::class, $controllerMethod]);
45+
});
46+
47+
return $route;
48+
}
3749
}

tests/Unit/GeneratorTestCase.php

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,5 +601,18 @@ public function uses_configured_settings_when_calling_route()
601601
$this->assertEquals('value', $responseContent['header']);
602602
}
603603

604+
/** @test */
605+
public function can_use_arrays_in_routes_uses()
606+
{
607+
$route = $this->createRouteUsesArray('GET', '/api/array/test', 'withEndpointDescription');
608+
609+
$parsed = $this->generator->processRoute($route);
610+
611+
$this->assertSame('Example title.', $parsed['title']);
612+
$this->assertSame("This will be the long description.\nIt can also be multiple lines long.", $parsed['description']);
613+
}
614+
604615
abstract public function createRoute(string $httpMethod, string $path, string $controllerMethod, $register = false);
616+
617+
abstract public function createRouteUsesArray(string $httpMethod, string $path, string $controllerMethod, $register = false);
605618
}

tests/Unit/LaravelGeneratorTest.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,4 +24,13 @@ public function createRoute(string $httpMethod, string $path, string $controller
2424
return new Route([$httpMethod], $path, ['uses' => TestController::class."@$controllerMethod"]);
2525
}
2626
}
27+
28+
public function createRouteUsesArray(string $httpMethod, string $path, string $controllerMethod, $register = false)
29+
{
30+
if ($register) {
31+
return RouteFacade::{$httpMethod}($path, TestController::class."@$controllerMethod");
32+
} else {
33+
return new Route([$httpMethod], $path, ['uses' => [TestController::class, $controllerMethod]]);
34+
}
35+
}
2736
}

0 commit comments

Comments
 (0)