Skip to content

Commit 8530d86

Browse files
committed
The API documentation was not properly generated for methods annotated with the subclassed RpcMethod.
This commit should be reverted as soon as this pull-request is accepted: sajya/server#87
1 parent da204e1 commit 8530d86

3 files changed

Lines changed: 174 additions & 2 deletions

File tree

app/Console/Commands/Docs.php

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Console\Commands;
6+
7+
use Illuminate\Routing\Route;
8+
use Illuminate\Support\Collection;
9+
use Illuminate\Support\Str;
10+
use Illuminate\Support\Stringable;
11+
use ReflectionClass;
12+
use ReflectionMethod;
13+
use Sajya\Server\Annotations\Param;
14+
use Sajya\Server\Attributes\RpcMethod;
15+
16+
/** @deprecated Remove as soon as this pull-request is accepted : https://github.com/sajya/server/pull/87 */
17+
class Docs extends \Sajya\Server\Docs
18+
{
19+
/**
20+
* Docs constructor.
21+
*
22+
* @param Route $route
23+
*/
24+
public function __construct(Route $route)
25+
{
26+
parent::__construct($route);
27+
}
28+
29+
/**
30+
* @return \Illuminate\Support\Collection
31+
*/
32+
public function getAnnotations(): Collection
33+
{
34+
return collect($this->procedures)
35+
->map(function (string $class) {
36+
37+
$reflectionClass = new ReflectionClass($class);
38+
$name = $reflectionClass->getProperty('name')->getValue();
39+
40+
return collect($reflectionClass->getMethods(ReflectionMethod::IS_PUBLIC))
41+
->map(function (ReflectionMethod $method) use ($name) {
42+
43+
$attributes = $this->getMethodAnnotations($method);
44+
45+
$request = [
46+
'jsonrpc' => '2.0',
47+
'id' => 1,
48+
'method' => $name . $this->delimiter . $method->getName(),
49+
'params' => $attributes?->params,
50+
];
51+
52+
$response = [
53+
'jsonrpc' => '2.0',
54+
'id' => 1,
55+
'result' => $attributes?->result,
56+
];
57+
58+
return [
59+
'name' => $name,
60+
'delimiter' => $this->delimiter,
61+
'method' => $method->getName(),
62+
'description' => $attributes?->description,
63+
'params' => $attributes?->params,
64+
'result' => $attributes?->result,
65+
'request' => $this->highlight($request),
66+
'response' => $this->highlight($response),
67+
];
68+
});
69+
})
70+
->flatten(1);
71+
}
72+
73+
private function getMethodAnnotations(ReflectionMethod $method): ?RpcMethod
74+
{
75+
$attributes = $method->getAttributes(RpcMethod::class, \ReflectionAttribute::IS_INSTANCEOF);
76+
77+
foreach ($attributes as $attribute) {
78+
/** @var RpcMethod $instance */
79+
$instance = $attribute->newInstance();
80+
81+
return $instance;
82+
}
83+
84+
return null;
85+
}
86+
87+
/**
88+
* Highlights a JSON structure using HTML span tags with colors.
89+
*
90+
* @param array $value The JSON data to be highlighted.
91+
*
92+
* @return \Illuminate\Support\Stringable The highlighted JSON as a string.
93+
* @throws \JsonException If encoding fails.
94+
*
95+
*/
96+
private function highlight(array $value): Stringable
97+
{
98+
$json = json_encode($value, JSON_THROW_ON_ERROR | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
99+
100+
return Str::of($json)
101+
// Highlight keys (both string and numeric)
102+
->replaceMatches('/"(\w+)":/i', '"<span style="color:#A0AEC0;">$1</span>":')
103+
->replaceMatches('/"(\d+)":/i', '"<span style="color:#A0AEC0;">$1</span>":')
104+
105+
// Highlight null values
106+
->replaceMatches('/":\s*(null)/i', '": <span style="color:#F7768E;">$1</span>')
107+
108+
// Highlight string values
109+
->replaceMatches('/":\s*"([^"]*)"/', '": "<span style="color:#9ECE6A;">$1</span>"')
110+
111+
// Highlight numeric values
112+
->replaceMatches('/":\s*(\d+(\.\d+)?)/', '": <span style="color:#E0AF68;">$1</span>')
113+
114+
// Highlight boolean values (true/false)
115+
->replaceMatches('/":\s*(true|false)/i', '": <span style="color:#7AA2F7;">$1</span>')
116+
->wrap('<pre style="color:rgba(212,212,212,0.75);">', '</pre>');
117+
}
118+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace App\Console\Commands;
6+
7+
use Illuminate\Console\Command;
8+
use Illuminate\Support\Facades\Route;
9+
use Illuminate\Support\Facades\Storage;
10+
11+
/** @deprecated Remove as soon as this pull-request is accepted : https://github.com/sajya/server/pull/87 */
12+
class DocsCommand extends \Sajya\Server\Commands\DocsCommand
13+
{
14+
/**
15+
* The name and signature of the console command.
16+
*
17+
* @var string
18+
*/
19+
protected $signature = 'cywise:docs {route}
20+
{--name=docs.html : Name of the generated documentation}
21+
{--path=/api/ : Path where included documentation files are located}';
22+
23+
/**
24+
* Execute the console command.
25+
*
26+
* @return int
27+
* @throws \Throwable
28+
*/
29+
public function handle(): int
30+
{
31+
$routeName = $this->argument('route');
32+
33+
$route = Route::getRoutes()->getByName($routeName);
34+
35+
if ($route === null) {
36+
$this->warn("Route '$routeName' not found");
37+
38+
return 1;
39+
}
40+
41+
$docs = new Docs($route);
42+
43+
$html = view('sajya::docs', [
44+
'title' => config('app.name'),
45+
'uri' => route($routeName),
46+
'procedures' => $docs->getAnnotations(),
47+
]);
48+
49+
Storage::disk()->put($this->option('path') . $this->option('name'), $html->render());
50+
$this->info('Documentation was generated successfully.');
51+
52+
return Command::SUCCESS;
53+
}
54+
}

towerify/Dockerfile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -155,8 +155,8 @@ COPY --chown=www-data:www-data --from=frontend /app/public/build/ /var/www/html/
155155
RUN chmod -R ug+rwx /var/www/html/storage /var/www/html/bootstrap/cache
156156

157157
# Generate API docs
158-
RUN php artisan sajya:docs 'v2.public.rpc.endpoint' --path='/public/docs/' --name 'docs.public.html'
159-
RUN php artisan sajya:docs 'v2.private.rpc.endpoint' --path='/public/docs/' --name 'docs.private.html'
158+
RUN php artisan cywise:docs 'v2.public.rpc.endpoint' --path='/public/docs/' --name 'docs.public.html'
159+
RUN php artisan cywise:docs 'v2.private.rpc.endpoint' --path='/public/docs/' --name 'docs.private.html'
160160

161161
COPY <<-EOT /etc/apache2/sites-available/laravel.conf
162162
<VirtualHost *:80>

0 commit comments

Comments
 (0)