mirror of
https://github.com/ambieco/scribe.git
synced 2026-03-26 14:14:05 +08:00
Refactor
This commit is contained in:
@@ -18,10 +18,11 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
- Support for specifying example model sources ([39ff208](https://github.com/knuckleswtf/scribe/commit/39ff208085d68eed4c459768ac5a1120934f021a))
|
||||
- Support for subgroups ([7cf07738](https://github.com/knuckleswtf/scribe/commit/7cf0773864fbdd1772fea9a5ff9e7ffd3360d7d2),[2ebf40b](https://github.com/knuckleswtf/scribe/commit/2ebf40b5e5be309bf5e685a0cd58bb70856b033d))
|
||||
- Nested response fields are now collapsed ([00b09bb](https://github.com/knuckleswtf/scribe/commit/00b09bbea8ec64006db864bf807004d48926c6d3))
|
||||
- Inlined routes (no more Scribe/Controller class)
|
||||
- Changed signature of Strategy#invoke ($routeRules is now optional)
|
||||
- `add_routes` now uses inline routes (no more `Scribe\Controller` class)
|
||||
- Changed signature of Strategy ($routeRules is now optional,and there's now an instance var $endpointData, although it's not set by default)
|
||||
- Parameter data from successive stages is now merged
|
||||
- Basic support for overriding docs for inherited methods ([9735fdf](9735fdf150469f186bab395fcfabd042f570c50c))
|
||||
- note views may have changed
|
||||
|
||||
## 3.36.0 (12 August 2022)
|
||||
### Modified
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2021 Shalvah Adebayo
|
||||
Copyright (c) 2022 Shalvah
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</p>
|
||||
|
||||
|
||||
> [v3 is out now](https://scribe.knuckles.wtf/blog/2021/06/08/laravel-v3)!
|
||||
> [v4 is out now](https://scribe.knuckles.wtf/blog/laravel-v4)!
|
||||
|
||||
Scribe helps you generate API documentation for humans from your Laravel/Lumen/[Dingo](https://github.com/dingo/api) codebase. See a live example at [demo.scribe.knuckles.wtf](https://demo.scribe.knuckles.wtf).
|
||||
|
||||
@@ -26,7 +26,7 @@ Scribe helps you generate API documentation for humans from your Laravel/Lumen/[
|
||||
## Documentation
|
||||
Check out the documentation at [scribe.knuckles.wtf/laravel](http://scribe.knuckles.wtf/laravel).
|
||||
|
||||
If you're coming from `mpociot/laravel-apidoc-generator`, there's a [migration guide](https://scribe.knuckles.wtf/laravel/migrating-apidoc).
|
||||
If you're coming from `mpociot/laravel-apidoc-generator`, first [migrate to v3](http://scribe.knuckles.wtf/blog/laravel/3.x/migrating-apidoc)`, then [to v4](http://scribe.knuckles.wtf/blog/laravel/migrating-v4).
|
||||
|
||||
## Contributing
|
||||
Contributing is easy! See our [contribution guide](https://scribe.knuckles.wtf/laravel/contributing).
|
||||
|
||||
@@ -358,7 +358,7 @@ INTRO
|
||||
* By default, Scribe will try the model's factory, and if that fails, try fetching the first from the database.
|
||||
* You can reorder or remove strategies here.
|
||||
*/
|
||||
'models_source' => ['factoryCreate', 'factoryMake', 'database'],
|
||||
'models_source' => ['factoryCreate', 'factoryMake', 'databaseFirst'],
|
||||
],
|
||||
|
||||
/**
|
||||
|
||||
@@ -11,16 +11,16 @@ class ResponseFromApiResource
|
||||
public string $name,
|
||||
public string $model,
|
||||
public int $status = 200,
|
||||
public ?string $description = '',
|
||||
|
||||
/* Mark if this should be used as a collection. Only needed if not using a ResourceCollection. */
|
||||
public bool $collection = false,
|
||||
|
||||
public ?string $description = '',
|
||||
public array $factoryStates = [],
|
||||
public array $with = [],
|
||||
|
||||
public ?int $paginate = null,
|
||||
public ?int $simplePaginate = null,
|
||||
public array $additionalData = [],
|
||||
public array $additional = [],
|
||||
)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -9,9 +9,9 @@ use Knuckles\Scribe\Extracting\Shared\ResponseFileTools;
|
||||
class ResponseFromFile
|
||||
{
|
||||
public function __construct(
|
||||
public ?string $file = null,
|
||||
public string $file,
|
||||
public int $status = 200,
|
||||
public array $merge = [],
|
||||
public array|string $merge = [],
|
||||
public ?string $description = '',
|
||||
) {
|
||||
}
|
||||
|
||||
@@ -11,15 +11,15 @@ class ResponseFromTransformer
|
||||
public string $name,
|
||||
public string $model,
|
||||
public int $status = 200,
|
||||
/* Mark if this should be used as a collection. */
|
||||
public bool $collection = false,
|
||||
|
||||
public ?string $description = '',
|
||||
|
||||
/* Mark if this should be used as a collection. Only needed if not using a CollectionTransformer. */
|
||||
public bool $collection = false,
|
||||
public array $factoryStates = [],
|
||||
public array $with = [],
|
||||
public ?string $resourceKey = null,
|
||||
|
||||
/* Format: [numberPerPage, adapter]. Example: [10, SomePaginator::class] */
|
||||
/* Format: [adapter, numberPerPage]. Example: [SomePaginator::class, 10] */
|
||||
public array $paginate = [],
|
||||
) {
|
||||
}
|
||||
|
||||
14
src/Attributes/Unauthenticated.php
Normal file
14
src/Attributes/Unauthenticated.php
Normal file
@@ -0,0 +1,14 @@
|
||||
<?php
|
||||
|
||||
namespace Knuckles\Scribe\Attributes;
|
||||
|
||||
use Attribute;
|
||||
|
||||
#[Attribute(Attribute::TARGET_FUNCTION | Attribute::TARGET_METHOD | Attribute::TARGET_CLASS)]
|
||||
class Unauthenticated
|
||||
{
|
||||
public function toArray()
|
||||
{
|
||||
return ["authenticated" => false];
|
||||
}
|
||||
}
|
||||
@@ -29,11 +29,11 @@ class GenerateDocumentation extends Command
|
||||
|
||||
protected $description = 'Generate API documentation from your Laravel/Dingo routes.';
|
||||
|
||||
private DocumentationConfig $docConfig;
|
||||
protected DocumentationConfig $docConfig;
|
||||
|
||||
private bool $shouldExtract;
|
||||
protected bool $shouldExtract;
|
||||
|
||||
private bool $forcing;
|
||||
protected bool $forcing;
|
||||
|
||||
protected string $configName;
|
||||
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace Knuckles\Scribe\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Knuckles\Scribe\Tools\Globals;
|
||||
use Shalvah\Upgrader\Upgrader;
|
||||
|
||||
class Upgrade extends Command
|
||||
@@ -27,7 +28,9 @@ class Upgrade extends Command
|
||||
return;
|
||||
}
|
||||
|
||||
$this->info("Welcome to the Scribe v3 to v4 upgrader.");
|
||||
$isMajorUpgrade = array_key_exists("default_group", $oldConfig) || array_key_exists("faker_seed", $oldConfig);
|
||||
|
||||
$isMajorUpgrade && $this->info("Welcome to the Scribe v3 to v4 upgrader.");
|
||||
$this->line("Checking for config file changes...");
|
||||
|
||||
$upgrader = Upgrader::ofConfigFile("config/$configName.php", __DIR__ . '/../../config/scribe.php')
|
||||
@@ -53,6 +56,17 @@ class Upgrade extends Command
|
||||
}
|
||||
$this->newLine();
|
||||
|
||||
if (!$isMajorUpgrade) {
|
||||
$this->info("✔ Done.");
|
||||
$this->info(sprintf("See the full changelog at https://github.com/knuckleswtf/scribe/blob/%s/CHANGELOG.md", Globals::SCRIBE_VERSION));
|
||||
return;
|
||||
}
|
||||
|
||||
$this->upgradeToV4();
|
||||
}
|
||||
|
||||
protected function upgradeToV4(): void
|
||||
{
|
||||
if ($this->confirm("Do you have any custom strategies?")) {
|
||||
$this->line('1. Add a new property <info>public ?ExtractedEndpointData $endpointData;</info>.');
|
||||
$this->line('2. Replace the <info>array $routeRules</info> parameter in __invoke() with <info>array $routeRules = []</info> .');
|
||||
@@ -62,18 +76,10 @@ class Upgrade extends Command
|
||||
if ($this->confirm("Did you customize the Blade templates used by Scribe?")) {
|
||||
$this->warn('A few minor changes were made to the templates. See the release announcement for details.');
|
||||
}
|
||||
$this->newLine();
|
||||
|
||||
$this->line("Scribe now supports PHP 8 attributes for annotations. "
|
||||
. "You can use both, but we recommend switching to attributes (see the docs).");
|
||||
if ($this->confirm("Would you like help in replacing your docblock tags with attributes?")) {
|
||||
$this->warn('Install our Rector package knuckleswtf/scribe-rector-t2a and run it.');
|
||||
}
|
||||
$this->warn("For attributes to work, you need to add the attribute strategies to your config file. See the release announcement for details.");
|
||||
|
||||
$this->newLine();
|
||||
$this->info("✔ Done.");
|
||||
$this->line("See the release announcement at <href=https://scribe.knuckles.wtf/v4>http://scribe.knuckles.wtf/v4</> for the full upgrade guide!");
|
||||
$this->line("See the release announcement at <href=https://scribe.knuckles.wtf/blog/laravel-v4>http://scribe.knuckles.wtf/blog/laravel-v4</> for the full upgrade guide!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,12 +18,12 @@ trait InstantiatesExampleModels
|
||||
*/
|
||||
protected function instantiateExampleModel(string $type, array $factoryStates = [], array $relations = [])
|
||||
{
|
||||
$configuredStrategies = $this->config->get('examples.models_source', ['factoryCreate', 'factoryMake', 'database']);
|
||||
$configuredStrategies = $this->config->get('examples.models_source', ['factoryCreate', 'factoryMake', 'databaseFirst']);
|
||||
|
||||
$strategies = [
|
||||
'factoryCreate' => fn() => $this->getExampleModelFromFactoryCreate($type, $factoryStates, $relations),
|
||||
'factoryMake' => fn() => $this->getExampleModelFromFactoryMake($type, $factoryStates, $relations),
|
||||
'database' => fn() => $this->getExampleModelFromDatabase($type, $relations),
|
||||
'databaseFirst' => fn() => $this->getExampleModelFromDatabaseFirst($type, $relations),
|
||||
];
|
||||
|
||||
foreach ($configuredStrategies as $strategyName) {
|
||||
@@ -51,7 +51,7 @@ trait InstantiatesExampleModels
|
||||
return $factory->make();
|
||||
}
|
||||
|
||||
protected function getExampleModelFromDatabase(string $type, array $relations = [])
|
||||
protected function getExampleModelFromDatabaseFirst(string $type, array $relations = [])
|
||||
{
|
||||
return $type::with($relations)->first();
|
||||
}
|
||||
|
||||
@@ -60,42 +60,43 @@ class GetFromDocBlocks extends Strategy
|
||||
{
|
||||
foreach ($methodDocBlock->getTags() as $tag) {
|
||||
if ($tag->getName() === 'group') {
|
||||
$routeGroupParts = explode("\n", trim($tag->getContent()));
|
||||
$routeGroupName = array_shift($routeGroupParts);
|
||||
$routeGroupDescription = trim(implode("\n", $routeGroupParts));
|
||||
$endpointGroupParts = explode("\n", trim($tag->getContent()));
|
||||
$endpointGroupName = array_shift($endpointGroupParts);
|
||||
$endpointGroupDescription = trim(implode("\n", $endpointGroupParts));
|
||||
|
||||
// If the route has no title (the methodDocBlock's "short description"),
|
||||
// we'll assume the routeGroupDescription is actually the title
|
||||
// If the endpoint has no title (the methodDocBlock's "short description"),
|
||||
// we'll assume the endpointGroupDescription is actually the title
|
||||
// Something like this:
|
||||
// /**
|
||||
// * Fetch cars. <-- This is route title.
|
||||
// * Fetch cars. <-- This is endpoint title.
|
||||
// * @group Cars <-- This is group name.
|
||||
// * APIs for cars. <-- This is group description (not required).
|
||||
// **/
|
||||
// VS
|
||||
// /**
|
||||
// * @group Cars <-- This is group name.
|
||||
// * Fetch cars. <-- This is route title, NOT group description.
|
||||
// * Fetch cars. <-- This is endpoint title, NOT group description.
|
||||
// **/
|
||||
|
||||
// BTW, this is a spaghetti way of doing this.
|
||||
// It shall be refactored soon. Deus vult!💪
|
||||
// ...Or maybe not
|
||||
if (empty($methodDocBlock->getShortDescription())) {
|
||||
return [$routeGroupName, '', $routeGroupDescription];
|
||||
return [$endpointGroupName, '', $endpointGroupDescription];
|
||||
}
|
||||
|
||||
return [$routeGroupName, $routeGroupDescription, $methodDocBlock->getShortDescription()];
|
||||
return [$endpointGroupName, $endpointGroupDescription, $methodDocBlock->getShortDescription()];
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to the controller
|
||||
foreach ($controllerDocBlock->getTags() as $tag) {
|
||||
if ($tag->getName() === 'group') {
|
||||
$routeGroupParts = explode("\n", trim($tag->getContent()));
|
||||
$routeGroupName = array_shift($routeGroupParts);
|
||||
$routeGroupDescription = implode("\n", $routeGroupParts);
|
||||
$endpointGroupParts = explode("\n", trim($tag->getContent()));
|
||||
$endpointGroupName = array_shift($endpointGroupParts);
|
||||
$endpointGroupDescription = implode("\n", $endpointGroupParts);
|
||||
|
||||
return [$routeGroupName, $routeGroupDescription, $methodDocBlock->getShortDescription()];
|
||||
return [$endpointGroupName, $endpointGroupDescription, $methodDocBlock->getShortDescription()];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ use Knuckles\Scribe\Attributes\ResponseFromApiResource;
|
||||
use Knuckles\Scribe\Attributes\ResponseFromFile;
|
||||
use Knuckles\Scribe\Attributes\ResponseFromTransformer;
|
||||
use Knuckles\Scribe\Attributes\Subgroup;
|
||||
use Knuckles\Scribe\Attributes\Unauthenticated;
|
||||
use Knuckles\Scribe\Extracting\DatabaseTransactionHelpers;
|
||||
use Knuckles\Scribe\Extracting\InstantiatesExampleModels;
|
||||
use Knuckles\Scribe\Extracting\ParamHelpers;
|
||||
@@ -30,6 +31,7 @@ class GetFromMetadataAttributes extends PhpAttributeStrategy
|
||||
Subgroup::class,
|
||||
Endpoint::class,
|
||||
Authenticated::class,
|
||||
Unauthenticated::class,
|
||||
];
|
||||
|
||||
protected function extractFromAttributes(
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace Knuckles\Scribe\Extracting\Strategies\ResponseFields;
|
||||
use Knuckles\Scribe\Extracting\Shared\ResponseFieldTools;
|
||||
use Knuckles\Scribe\Extracting\Strategies\GetFieldsFromTagStrategy;
|
||||
use Mpociot\Reflection\DocBlock;
|
||||
use Knuckles\Scribe\Tools\Utils as u;
|
||||
|
||||
class GetFromResponseFieldTag extends GetFieldsFromTagStrategy
|
||||
{
|
||||
|
||||
@@ -61,7 +61,7 @@ class UseResponseAttributes extends PhpAttributeStrategy
|
||||
$this->startDbTransaction();
|
||||
$content = ApiResourceResponseTools::fetch(
|
||||
$attributeInstance->name, $attributeInstance->collection, $modelInstantiator,
|
||||
$this->endpointData, $pagination, $attributeInstance->additionalData,
|
||||
$this->endpointData, $pagination, $attributeInstance->additional,
|
||||
);
|
||||
$this->endDbTransaction();
|
||||
|
||||
@@ -76,7 +76,9 @@ class UseResponseAttributes extends PhpAttributeStrategy
|
||||
{
|
||||
$modelInstantiator = fn() => $this->instantiateExampleModel($attributeInstance->model, $attributeInstance->factoryStates, $attributeInstance->with);
|
||||
|
||||
$pagination = ['perPage' => $attributeInstance->paginate[0], 'adapter' => $attributeInstance->paginate[1]];
|
||||
$pagination = [
|
||||
'perPage' => $attributeInstance->paginate[1] ?? null, 'adapter' => $attributeInstance->paginate[0]
|
||||
];
|
||||
$this->startDbTransaction();
|
||||
$content = TransformerResponseTools::fetch(
|
||||
$attributeInstance->name, $attributeInstance->collection, $modelInstantiator,
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace Knuckles\Scribe\Extracting\Strategies\Responses;
|
||||
|
||||
use Knuckles\Camel\Extraction\ExtractedEndpointData;
|
||||
use Exception;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use Illuminate\Support\Arr;
|
||||
use Knuckles\Scribe\Extracting\DatabaseTransactionHelpers;
|
||||
use Knuckles\Scribe\Extracting\InstantiatesExampleModels;
|
||||
@@ -12,12 +11,7 @@ use Knuckles\Scribe\Extracting\RouteDocBlocker;
|
||||
use Knuckles\Scribe\Extracting\Shared\TransformerResponseTools;
|
||||
use Knuckles\Scribe\Extracting\Strategies\Strategy;
|
||||
use Knuckles\Scribe\Tools\AnnotationParser as a;
|
||||
use Knuckles\Scribe\Tools\ConsoleOutputUtils as c;
|
||||
use Knuckles\Scribe\Tools\ErrorHandlingUtils as e;
|
||||
use Knuckles\Scribe\Tools\Utils;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Resource\Collection;
|
||||
use League\Fractal\Resource\Item;
|
||||
use Mpociot\Reflection\DocBlock\Tag;
|
||||
use ReflectionClass;
|
||||
use ReflectionFunctionAbstract;
|
||||
@@ -132,11 +126,14 @@ class UseTransformerTags extends Strategy
|
||||
return ['adapter' => null, 'perPage' => null];
|
||||
}
|
||||
|
||||
preg_match('/^\s*(.+?)\s+(\d+)?$/', $tag->getContent(), $result);
|
||||
preg_match('/^\s*(.+?)(\s+\d+)?$/', $tag->getContent(), $result);
|
||||
$paginatorAdapter = $result[1];
|
||||
$perPage = $result[2] ?? null;
|
||||
if ($perPage) {
|
||||
$perPage = trim($perPage);
|
||||
}
|
||||
|
||||
return ['adapter' => $paginatorAdapter, 'perPage' => $perPage];
|
||||
return ['adapter' => $paginatorAdapter, 'perPage' => $perPage ?: null];
|
||||
}
|
||||
|
||||
public function getTransformerResponseFromTags(array $tags): ?array
|
||||
|
||||
@@ -22,7 +22,7 @@ abstract class TagStrategyWithFormRequestFallback extends Strategy
|
||||
public function getParametersFromDocBlockInFormRequestOrMethod(Route $route, ReflectionFunctionAbstract $method): array
|
||||
{
|
||||
$classTags = RouteDocBlocker::getDocBlocksFromRoute($route)['class']?->getTags() ?: [];
|
||||
// If there's a FormRequest, we check there for tags.
|
||||
// If there's a FormRequest, w.e check there for tags.
|
||||
if ($formRequestClass = $this->getFormRequestReflectionClass($method)) {
|
||||
$formRequestDocBlock = new DocBlock($formRequestClass->getDocComment());
|
||||
$parametersFromFormRequest = $this->getFromTags($formRequestDocBlock->getTags(), $classTags);
|
||||
|
||||
@@ -95,7 +95,7 @@ class GroupedEndpointsFromApp implements GroupedEndpointsContract
|
||||
*/
|
||||
private function extractEndpointsInfoFromLaravelApp(array $matches, array $cachedEndpoints, array $latestEndpointsData, array $groups): array
|
||||
{
|
||||
$generator = $this->makeExtractor();
|
||||
$extractor = $this->makeExtractor();
|
||||
|
||||
$parsedEndpoints = [];
|
||||
|
||||
@@ -120,7 +120,7 @@ class GroupedEndpointsFromApp implements GroupedEndpointsContract
|
||||
|
||||
try {
|
||||
c::info('Processing route: ' . c::getRouteRepresentation($route));
|
||||
$currentEndpointData = $generator->processRoute($route, $routeItem->getRules());
|
||||
$currentEndpointData = $extractor->processRoute($route, $routeItem->getRules());
|
||||
// If latest data is different from cached data, merge latest into current
|
||||
[$currentEndpointData, $index] = $this->mergeAnyEndpointDataUpdates($currentEndpointData, $cachedEndpoints, $latestEndpointsData, $groups);
|
||||
|
||||
|
||||
@@ -13,48 +13,15 @@ use Knuckles\Scribe\Tools\Utils;
|
||||
|
||||
class ScribeServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Bootstrap the application events.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
// Register custom Markdown Blade compiler so we can automatically have MD views converted to HTML
|
||||
$this->app->view->getEngineResolver()
|
||||
->register('blademd', fn() => new BladeMarkdownEngine($this->app['blade.compiler']));
|
||||
$this->app->view->addExtension('md.blade.php', 'blademd');
|
||||
$this->registerViews();
|
||||
|
||||
$this->loadViewsFrom(__DIR__ . '/../resources/views/', 'scribe');
|
||||
|
||||
// Publish views in separate, smaller groups for ease of end-user modifications
|
||||
$viewGroups = [
|
||||
'views' => '',
|
||||
'examples' => 'partials/example-requests',
|
||||
'themes' => 'themes',
|
||||
'markdown' => 'markdown',
|
||||
];
|
||||
foreach ($viewGroups as $group => $path) {
|
||||
$this->publishes([
|
||||
__DIR__ . "/../resources/views/$path" => $this->app->basePath("resources/views/vendor/scribe/$path"),
|
||||
], "scribe-$group");
|
||||
}
|
||||
|
||||
$this->publishes([
|
||||
__DIR__ . '/../config/scribe.php' => $this->app->configPath('scribe.php'),
|
||||
], 'scribe-config');
|
||||
|
||||
$this->mergeConfigFrom(__DIR__ . '/../config/scribe.php', 'scribe');
|
||||
$this->registerConfig();
|
||||
|
||||
$this->bootRoutes();
|
||||
|
||||
if ($this->app->runningInConsole()) {
|
||||
$this->commands([
|
||||
GenerateDocumentation::class,
|
||||
MakeStrategy::class,
|
||||
Upgrade::class,
|
||||
]);
|
||||
}
|
||||
$this->registerCommands();
|
||||
|
||||
// Bind the route matcher implementation
|
||||
$this->app->bind(RouteMatcherInterface::class, config('scribe.routeMatcher', RouteMatcher::class));
|
||||
@@ -78,4 +45,47 @@ class ScribeServiceProvider extends ServiceProvider
|
||||
$this->loadRoutesFrom($routesPath);
|
||||
}
|
||||
}
|
||||
|
||||
protected function registerViews(): void
|
||||
{
|
||||
// Register custom Markdown Blade compiler so we can automatically have MD views converted to HTML
|
||||
$this->app->view->getEngineResolver()
|
||||
->register('blademd', fn() => new BladeMarkdownEngine($this->app['blade.compiler']));
|
||||
$this->app->view->addExtension('md.blade.php', 'blademd');
|
||||
|
||||
$this->loadViewsFrom(__DIR__ . '/../resources/views/', 'scribe');
|
||||
|
||||
// Publish views in separate, smaller groups for ease of end-user modifications
|
||||
$viewGroups = [
|
||||
'views' => '',
|
||||
'examples' => 'partials/example-requests',
|
||||
'themes' => 'themes',
|
||||
'markdown' => 'markdown',
|
||||
];
|
||||
foreach ($viewGroups as $group => $path) {
|
||||
$this->publishes([
|
||||
__DIR__ . "/../resources/views/$path" => $this->app->basePath("resources/views/vendor/scribe/$path"),
|
||||
], "scribe-$group");
|
||||
}
|
||||
}
|
||||
|
||||
protected function registerConfig(): void
|
||||
{
|
||||
$this->publishes([
|
||||
__DIR__ . '/../config/scribe.php' => $this->app->configPath('scribe.php'),
|
||||
], 'scribe-config');
|
||||
|
||||
$this->mergeConfigFrom(__DIR__ . '/../config/scribe.php', 'scribe');
|
||||
}
|
||||
|
||||
protected function registerCommands(): void
|
||||
{
|
||||
if ($this->app->runningInConsole()) {
|
||||
$this->commands([
|
||||
GenerateDocumentation::class,
|
||||
MakeStrategy::class,
|
||||
Upgrade::class,
|
||||
]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,6 +8,7 @@ use Knuckles\Scribe\Attributes\Authenticated;
|
||||
use Knuckles\Scribe\Attributes\Endpoint;
|
||||
use Knuckles\Scribe\Attributes\Group;
|
||||
use Knuckles\Scribe\Attributes\Subgroup;
|
||||
use Knuckles\Scribe\Attributes\Unauthenticated;
|
||||
use Knuckles\Scribe\Extracting\Strategies\Metadata\GetFromMetadataAttributes;
|
||||
use Knuckles\Scribe\Tools\DocumentationConfig;
|
||||
use PHPUnit\Framework\TestCase;
|
||||
@@ -81,6 +82,23 @@ class UseMetadataAttributesTest extends TestCase
|
||||
"description" => "",
|
||||
"authenticated" => false,
|
||||
], $results);
|
||||
|
||||
$endpoint = $this->endpoint(function (ExtractedEndpointData $e) {
|
||||
$e->controller = new ReflectionClass(MetadataAttributesTestController2::class);
|
||||
$e->method = $e->controller->getMethod('c1');
|
||||
});
|
||||
$results = $this->fetch($endpoint);
|
||||
$this->assertArraySubset([
|
||||
"authenticated" => true,
|
||||
], $results);
|
||||
$endpoint = $this->endpoint(function (ExtractedEndpointData $e) {
|
||||
$e->controller = new ReflectionClass(MetadataAttributesTestController2::class);
|
||||
$e->method = $e->controller->getMethod('c2');
|
||||
});
|
||||
$results = $this->fetch($endpoint);
|
||||
$this->assertArraySubset([
|
||||
"authenticated" => false,
|
||||
], $results);
|
||||
}
|
||||
|
||||
protected function fetch($endpoint): array
|
||||
@@ -132,3 +150,16 @@ class MetadataAttributesTestController
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
#[Authenticated]
|
||||
class MetadataAttributesTestController2
|
||||
{
|
||||
public function c1()
|
||||
{
|
||||
}
|
||||
|
||||
#[Unauthenticated]
|
||||
public function c2()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ class UseApiResourceTagsTest extends BaseLaravelTest
|
||||
/** @test */
|
||||
public function respects_models_source_settings()
|
||||
{
|
||||
$config = new DocumentationConfig(['examples' => ['models_source' => ['database', 'factoryMake']]]);
|
||||
$config = new DocumentationConfig(['examples' => ['models_source' => ['databaseFirst', 'factoryMake']]]);
|
||||
$route = new Route(['POST'], "/somethingRandom", ['uses' => [TestController::class, 'dummy']]);
|
||||
|
||||
$strategy = new UseApiResourceTags($config);
|
||||
|
||||
@@ -211,14 +211,14 @@ class ResponseAttributesTestController
|
||||
}
|
||||
|
||||
#[ResponseFromApiResource(TestUserApiResource::class, TestUser::class, collection: true,
|
||||
factoryStates: ["state1", "random-state"], simplePaginate: 1, additionalData: ["a" => "b"])]
|
||||
factoryStates: ["state1", "random-state"], simplePaginate: 1, additional: ["a" => "b"])]
|
||||
public function apiResourceAttributes()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
#[ResponseFromTransformer(TestTransformer::class, TestModel::class, collection: true,
|
||||
paginate: [1, IlluminatePaginatorAdapter::class])]
|
||||
paginate: [IlluminatePaginatorAdapter::class, 1])]
|
||||
public function transformerAttributes()
|
||||
{
|
||||
|
||||
|
||||
Reference in New Issue
Block a user