X-Git-Url: http://source.bookstackapp.com/bookstack/blobdiff_plain/a6633642232efd164d4708967ab59e498fbff896..refs/pull/3391/head:/app/Api/ApiDocsGenerator.php diff --git a/app/Api/ApiDocsGenerator.php b/app/Api/ApiDocsGenerator.php index 2953647bb..671923ab1 100644 --- a/app/Api/ApiDocsGenerator.php +++ b/app/Api/ApiDocsGenerator.php @@ -1,18 +1,21 @@ -generate(); + $docs = (new ApiDocsGenerator())->generate(); Cache::put($cacheKey, $docs, 60 * 24); } + return $docs; } @@ -42,6 +46,7 @@ class ApiDocsGenerator $apiRoutes = $this->loadDetailsFromControllers($apiRoutes); $apiRoutes = $this->loadDetailsFromFiles($apiRoutes); $apiRoutes = $apiRoutes->groupBy('base_model'); + return $apiRoutes; } @@ -52,11 +57,18 @@ class ApiDocsGenerator { return $routes->map(function (array $route) { $exampleTypes = ['request', 'response']; + $fileTypes = ['json', 'http']; foreach ($exampleTypes as $exampleType) { - $exampleFile = base_path("dev/api/{$exampleType}s/{$route['name']}.json"); - $exampleContent = file_exists($exampleFile) ? file_get_contents($exampleFile) : null; - $route["example_{$exampleType}"] = $exampleContent; + foreach ($fileTypes as $fileType) { + $exampleFile = base_path("dev/api/{$exampleType}s/{$route['name']}." . $fileType); + if (file_exists($exampleFile)) { + $route["example_{$exampleType}"] = file_get_contents($exampleFile); + continue 2; + } + } + $route["example_{$exampleType}"] = null; } + return $route; }); } @@ -71,12 +83,14 @@ class ApiDocsGenerator $comment = $method->getDocComment(); $route['description'] = $comment ? $this->parseDescriptionFromMethodComment($comment) : null; $route['body_params'] = $this->getBodyParamsFromClass($route['controller'], $route['controller_method']); + return $route; }); } /** * Load body params and their rules by inspecting the given class and method name. + * * @throws BindingResolutionException */ protected function getBodyParamsFromClass(string $className, string $methodName): ?array @@ -88,25 +102,51 @@ class ApiDocsGenerator $this->controllerClasses[$className] = $class; } - $rules = $class->getValdationRules()[$methodName] ?? []; - foreach ($rules as $param => $ruleString) { - $rules[$param] = explode('|', $ruleString); + $rules = collect($class->getValidationRules()[$methodName] ?? [])->map(function ($validations) { + return array_map(function ($validation) { + return $this->getValidationAsString($validation); + }, $validations); + })->toArray(); + + return empty($rules) ? null : $rules; + } + + /** + * Convert the given validation message to a readable string. + */ + protected function getValidationAsString($validation): string + { + if (is_string($validation)) { + return $validation; + } + + if (is_object($validation) && method_exists($validation, '__toString')) { + return strval($validation); + } + + if ($validation instanceof Password) { + return 'min:8'; } - return count($rules) > 0 ? $rules : null; + + $class = get_class($validation); + + throw new Exception("Cannot provide string representation of rule for class: {$class}"); } /** * Parse out the description text from a class method comment. */ - protected function parseDescriptionFromMethodComment(string $comment) + protected function parseDescriptionFromMethodComment(string $comment): string { $matches = []; preg_match_all('/^\s*?\*\s((?![@\s]).*?)$/m', $comment, $matches); + return implode(' ', $matches[1] ?? []); } /** * Get a reflection method from the given class name and method name. + * * @throws ReflectionException */ protected function getReflectionMethod(string $className, string $methodName): ReflectionMethod @@ -131,16 +171,16 @@ class ApiDocsGenerator [$controller, $controllerMethod] = explode('@', $route->action['uses']); $baseModelName = explode('.', explode('/', $route->uri)[1])[0]; $shortName = $baseModelName . '-' . $controllerMethod; + return [ - 'name' => $shortName, - 'uri' => $route->uri, - 'method' => $route->methods[0], - 'controller' => $controller, - 'controller_method' => $controllerMethod, + 'name' => $shortName, + 'uri' => $route->uri, + 'method' => $route->methods[0], + 'controller' => $controller, + 'controller_method' => $controllerMethod, 'controller_method_kebab' => Str::kebab($controllerMethod), - 'base_model' => $baseModelName, + 'base_model' => $baseModelName, ]; }); } - -} \ No newline at end of file +}