Skip to content

Commit

Permalink
Merge branch 'vNext' into php-84-upgrade
Browse files Browse the repository at this point in the history
  • Loading branch information
shalvah authored Jan 18, 2025
2 parents 024fe5c + 7fa4283 commit 7cb4239
Show file tree
Hide file tree
Showing 21 changed files with 32 additions and 613 deletions.
9 changes: 0 additions & 9 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ jobs:
- highest
include:
- {php: '8.1', deps: lowest}
- {php: '8.1', deps: dingo}

name: Tests (PHP ${{ matrix.php }} - ${{ matrix.deps }})

Expand All @@ -36,10 +35,6 @@ jobs:
if: ${{ matrix.deps == 'highest' }}
run: composer update

- name: Install dependencies (Dingo)
if: ${{ matrix.deps == 'dingo' }}
run: COMPOSER=composer.dingo.json composer update --prefer-stable

- name: Install dependencies (lowest)
if: ${{ matrix.deps == 'lowest' }}
run: COMPOSER=composer.lowest.json composer update --prefer-stable
Expand All @@ -52,7 +47,3 @@ jobs:
- name: Execute tests (Lowest)
run: COMPOSER=composer.lowest.json composer test-ci
if: ${{ matrix.deps == 'lowest' }}

- name: Execute tests (Dingo)
run: COMPOSER=composer.dingo.json composer test-ci
if: ${{ matrix.deps == 'dingo' }}
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
.DS_Store
composer.lock
composer.dingo.lock
.php_cs.cache
/vendor/
public/
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

> [v4 is out now](https://scribe.knuckles.wtf/blog/laravel-v4)! Featuring subgroups, easier sorting, and an automated upgrade command.
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).
Scribe helps you generate API documentation for humans from your Laravel/Lumen codebase. See a live example at [demo.scribe.knuckles.wtf](https://demo.scribe.knuckles.wtf).

## Features
- Useful output:
Expand Down
11 changes: 5 additions & 6 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
"keywords": [
"API",
"documentation",
"laravel",
"dingo"
"laravel"
],
"homepage": "http://github.com/knuckleswtf/scribe",
"authors": [
Expand Down Expand Up @@ -61,10 +60,10 @@
},
"scripts": {
"lint": "phpstan analyse -c ./phpstan.neon src camel --memory-limit 1G",
"test": "pest --exclude-group dingo --colors",
"test-ci": "pest --exclude-group dingo --coverage --min=80",
"test-parallel": "paratest -p16 --stop-on-failure --exclude-group dingo",
"test-parallel-ci": "paratest -p16 --exclude-group dingo"
"test": "pest --stop-on-failure --colors",
"test-ci": "pest --coverage --min=80",
"test-parallel": "paratest -p16 --stop-on-failure",
"test-parallel-ci": "paratest -p16"
},
"extra": {
"laravel": {
Expand Down
11 changes: 5 additions & 6 deletions composer.lowest.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,7 @@
"keywords": [
"API",
"documentation",
"laravel",
"dingo"
"laravel"
],
"homepage": "http://github.com/knuckleswtf/scribe",
"authors": [
Expand Down Expand Up @@ -63,10 +62,10 @@
},
"scripts": {
"lint": "phpstan analyse -c ./phpstan.neon src camel --memory-limit 1G",
"test": "phpunit --stop-on-failure --exclude-group dingo",
"test-ci": "pest --exclude-group dingo --coverage --min=80",
"test-parallel": "paratest -p16 --stop-on-failure --exclude-group dingo",
"test-parallel-ci": "paratest -p16 --exclude-group dingo"
"test": "phpunit --stop-on-failure",
"test-ci": "pest --coverage --min=80",
"test-parallel": "paratest -p16 --stop-on-failure",
"test-parallel-ci": "paratest -p16"
},
"extra": {
"laravel": {
Expand Down
3 changes: 0 additions & 3 deletions config/scribe.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,6 @@

// Match only routes whose domains match this pattern (use * as a wildcard to match any characters). Example: 'api.*'.
'domains' => ['*'],

// [Dingo router only] Match only routes registered under this version. Wildcards are NOT supported.
'versions' => ['v1'],
],

// Include these routes even if they did not match the rules above.
Expand Down
3 changes: 0 additions & 3 deletions phpstan.neon
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,7 @@ parameters:
reportUnmatchedIgnoredErrors: true
inferPrivatePropertyTypeFromConstructor: true
ignoreErrors:
- '#Call to an undefined method Illuminate\\Routing\\Route::versions\(\).#'
- '#Call to an undefined method ReflectionType::getName\(\).#'
- '#.+Dingo.+#'
- '#.+Laravel\\Lumen\\Application.+#'
- '#Call to an undefined method Illuminate\\Contracts\\Filesystem\\Filesystem::path\(\)#'
- '#Call to an undefined method Illuminate\\Contracts\\Foundation\\Application::forgetInstance\(\)#'
- '#Access to an undefined property Illuminate\\Support\\HigherOrderCollectionProxy#'
Expand Down
2 changes: 1 addition & 1 deletion src/Commands/GenerateDocumentation.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class GenerateDocumentation extends Command
{--scribe-dir= : Specify the directory where Scribe stores its intermediate output and cache. Defaults to `.<config_file>`}
";

protected $description = 'Generate API documentation from your Laravel/Dingo routes.';
protected $description = 'Generate API documentation from your Laravel routes.';

protected DocumentationConfig $docConfig;

Expand Down
2 changes: 0 additions & 2 deletions src/Config/Routes.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ class Routes
public static function match(
array $prefixes = ['api/*'],
array $domains = ['*'],
array $dingoVersions = ['v1'],
array $alwaysInclude = [],
array $alwaysExclude = [],
): static
Expand All @@ -18,7 +17,6 @@ public static function match(
public function __construct(
public array $prefixes = [],
public array $domains = [],
public array $dingoVersions = [],
public array $alwaysInclude = [],
public array $alwaysExclude = []
)
Expand Down
1 change: 0 additions & 1 deletion src/Config/Serializer.php
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@ protected static function generateRoutesConfig(Routes $routesConfig): array
'match' => [
'prefixes' => $routesConfig->prefixes,
'domains' => $routesConfig->domains,
'versions' => $routesConfig->dingoVersions,
],
'include' => $routesConfig->alwaysInclude,
'exclude' => $routesConfig->alwaysExclude,
Expand Down
7 changes: 2 additions & 5 deletions src/Extracting/FindsFormRequestForMethod.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,7 @@

namespace Knuckles\Scribe\Extracting;

use Illuminate\Foundation\Http\FormRequest as LaravelFormRequest;
use Dingo\Api\Http\FormRequest as DingoFormRequest;
use Illuminate\Foundation\Http\FormRequest;
use ReflectionClass;
use ReflectionException;
use ReflectionFunctionAbstract;
Expand All @@ -27,9 +26,7 @@ protected function getFormRequestReflectionClass(ReflectionFunctionAbstract $met
continue;
}

if (
(class_exists(LaravelFormRequest::class) && $argumentClass->isSubclassOf(LaravelFormRequest::class))
|| (class_exists(DingoFormRequest::class) && $argumentClass->isSubclassOf(DingoFormRequest::class))) {
if ($argumentClass->isSubclassOf(FormRequest::class)) {
return $argumentClass;
}
}
Expand Down
14 changes: 4 additions & 10 deletions src/Extracting/Strategies/GetFromFormRequestBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@

use Illuminate\Routing\Route;
use Knuckles\Camel\Extraction\ExtractedEndpointData;
use Dingo\Api\Http\FormRequest as DingoFormRequest;
use Illuminate\Foundation\Http\FormRequest as LaravelFormRequest;
use Illuminate\Foundation\Http\FormRequest;
use Knuckles\Scribe\Extracting\FindsFormRequestForMethod;
use Knuckles\Scribe\Extracting\ParsesValidationRules;
use Knuckles\Scribe\Tools\ConsoleOutputUtils as c;
Expand Down Expand Up @@ -43,7 +42,7 @@ public function getParametersFromFormRequest(ReflectionFunctionAbstract $method,
$formRequest = new $className;
}
// Set the route properly so it works for users who have code that checks for the route.
/** @var LaravelFormRequest|DingoFormRequest $formRequest */
/** @var FormRequest $formRequest */
$formRequest->setRouteResolver(function () use ($formRequest, $route) {
// Also need to bind the request to the route in case their code tries to inspect current request
return $route->bind($formRequest);
Expand All @@ -59,11 +58,9 @@ public function getParametersFromFormRequest(ReflectionFunctionAbstract $method,
}

/**
* @param LaravelFormRequest|DingoFormRequest $formRequest
*
* @return mixed
*/
protected function getRouteValidationRules($formRequest)
protected function getRouteValidationRules(FormRequest $formRequest)
{
if (method_exists($formRequest, 'validator')) {
$validationFactory = app(ValidationFactory::class);
Expand All @@ -77,10 +74,7 @@ protected function getRouteValidationRules($formRequest)
return [];
}

/**
* @param LaravelFormRequest|DingoFormRequest $formRequest
*/
protected function getCustomParameterData($formRequest)
protected function getCustomParameterData(FormRequest $formRequest)
{
if (method_exists($formRequest, $this->customParameterDataMethodName)) {
return call_user_func_array([$formRequest, $this->customParameterDataMethodName], []);
Expand Down
53 changes: 2 additions & 51 deletions src/Extracting/Strategies/Responses/ResponseCalls.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

namespace Knuckles\Scribe\Extracting\Strategies\Responses;

use Dingo\Api\Dispatcher;
use Dingo\Api\Routing\Route as DingoRoute;
use Exception;
use Illuminate\Contracts\Http\Kernel;
use Illuminate\Http\Request;
Expand Down Expand Up @@ -205,47 +203,6 @@ private function finish()
$this->rollbackLaravelConfigChanges();
}

/**
* @param Request $request
*
* @return \Illuminate\Http\JsonResponse|mixed
*/
public function callDingoRoute(Request $request, Route $route)
{
/** @var \Dingo\Api\Dispatcher $dispatcher */
$dispatcher = app(\Dingo\Api\Dispatcher::class);

/** @var DingoRoute $route */
$dispatcher->version($route->versions()[0]);
foreach ($request->headers as $header => $value) {
$dispatcher->header($header, $value);
}

// set domain and body parameters
$dispatcher->on($request->header('SERVER_NAME'))
->with($request->request->all());

// set URL and query parameters
$uri = $request->getRequestUri();
$query = $request->getQueryString();
if (!empty($query)) {
$uri .= "?$query";
}

$response = call_user_func_array(
[$dispatcher, strtolower($request->method())],
[$uri]
);

// the response from the Dingo dispatcher is the 'raw' response from the controller,
// so we have to ensure it's JSON first
if (!$response instanceof Response) {
$response = response()->json($response);
}

return $response;
}

public function getMethods(Route $route): array
{
return array_diff($route->methods(), ['HEAD']);
Expand Down Expand Up @@ -287,18 +244,12 @@ private function addBodyParameters(Request $request, array $body): void
*
* @param Route $route
*
* @return \Illuminate\Http\JsonResponse|mixed|\Symfony\Component\HttpFoundation\Response
* @return \Symfony\Component\HttpFoundation\Response
* @throws Exception
*/
protected function makeApiCall(Request $request, Route $route)
{
if ($this->config->get('router') == 'dingo') {
$response = $this->callDingoRoute($request, $route);
} else {
$response = $this->callLaravelOrLumenRoute($request);
}

return $response;
return $this->callLaravelOrLumenRoute($request);
}

protected function callLaravelOrLumenRoute(Request $request): \Symfony\Component\HttpFoundation\Response
Expand Down
2 changes: 1 addition & 1 deletion src/GroupedEndpoints/GroupedEndpointsFromApp.php
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ protected function extractEndpointsInfoAndWriteToDisk(RouteMatcherInterface $rou
$cachedEndpoints = Camel::loadEndpointsToFlatPrimitivesArray(static::$cacheDir);
}

$routes = $routeMatcher->getRoutes($this->docConfig->get('routes', []), $this->docConfig->get('router'));
$routes = $routeMatcher->getRoutes($this->docConfig->get('routes', []));
$endpoints = $this->extractEndpointsInfoFromLaravelApp($routes, $cachedEndpoints, $latestEndpointsData);

$groupedEndpoints = collect($endpoints)->groupBy('metadata.groupName')->map(function (Collection $endpointsInGroup) {
Expand Down
38 changes: 9 additions & 29 deletions src/Matching/RouteMatcher.php
Original file line number Diff line number Diff line change
Expand Up @@ -2,24 +2,21 @@

namespace Knuckles\Scribe\Matching;

use Dingo\Api\Routing\RouteCollection;
use Illuminate\Routing\Route;
use Illuminate\Support\Facades\Route as RouteFacade;
use Illuminate\Support\Str;
use Knuckles\Scribe\Tools\RoutePatternMatcher;

class RouteMatcher implements RouteMatcherInterface
{
public function getRoutes(array $routeRules = [], string $router = 'laravel'): array
public function getRoutes(array $routeRules = []): array
{
$usingDingoRouter = strtolower($router) == 'dingo';

return $this->getRoutesToBeDocumented($routeRules, $usingDingoRouter);
return $this->getRoutesToBeDocumented($routeRules);
}

private function getRoutesToBeDocumented(array $routeRules, bool $usingDingoRouter = false): array
private function getRoutesToBeDocumented(array $routeRules): array
{
$allRoutes = $this->getAllRoutes($usingDingoRouter);
$allRoutes = $this->getAllRoutes();

$matchedRoutes = [];

Expand All @@ -35,7 +32,7 @@ private function getRoutesToBeDocumented(array $routeRules, bool $usingDingoRout
continue;
}

if ($this->shouldIncludeRoute($route, $routeRule, $includes, $usingDingoRouter)) {
if ($this->shouldIncludeRoute($route, $routeRule, $includes)) {
$matchedRoutes[] = new MatchedRoute($route, $routeRule['apply'] ?? []);
}
}
Expand All @@ -44,38 +41,21 @@ private function getRoutesToBeDocumented(array $routeRules, bool $usingDingoRout
return $matchedRoutes;
}

private function getAllRoutes(bool $usingDingoRouter)
private function getAllRoutes()
{
if (! $usingDingoRouter) {
return RouteFacade::getRoutes();
}

/** @var \Dingo\Api\Routing\Router $router */
$router = app(\Dingo\Api\Routing\Router::class);
$allRouteCollections = $router->getRoutes();

return collect($allRouteCollections)
->flatMap(function (RouteCollection $collection) {
return $collection->getRoutes();
})->toArray();
return RouteFacade::getRoutes();
}

private function shouldIncludeRoute(Route $route, array $routeRule, array $mustIncludes, bool $usingDingoRouter): bool
private function shouldIncludeRoute(Route $route, array $routeRule, array $mustIncludes): bool
{
if (RoutePatternMatcher::matches($route, $mustIncludes)) {
return true;
}

$matchesVersion = true;
if ($usingDingoRouter) {
$matchesVersion = !empty(array_intersect($route->versions(), $routeRule['match']['versions'] ?? []));
}

$domainsToMatch = $routeRule['match']['domains'] ?? [];
$pathsToMatch = $routeRule['match']['prefixes'] ?? [];

return Str::is($domainsToMatch, $route->getDomain()) && Str::is($pathsToMatch, $route->uri())
&& $matchesVersion;
return Str::is($domainsToMatch, $route->getDomain()) && Str::is($pathsToMatch, $route->uri());
}

private function shouldExcludeRoute(Route $route, array $routeRule): bool
Expand Down
3 changes: 1 addition & 2 deletions src/Matching/RouteMatcherInterface.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,8 @@ interface RouteMatcherInterface
* Resolve matched routes that should be documented.
*
* @param array $routeRules Route rules defined under the "routes" section in config
* @param string $router
*
* @return MatchedRoute[]
*/
public function getRoutes(array $routeRules = [], string $router = 'laravel'): array;
public function getRoutes(array $routeRules = []): array;
}
Loading

0 comments on commit 7cb4239

Please sign in to comment.