Skip to content

Commit

Permalink
Merge branch 'vNext' into add-withCount-support
Browse files Browse the repository at this point in the history
  • Loading branch information
shalvah authored Jan 18, 2025
2 parents 6222667 + d5e61eb commit 781b9fd
Show file tree
Hide file tree
Showing 31 changed files with 95 additions and 84 deletions.
4 changes: 2 additions & 2 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Lint

on:
push:
branches: [master]
branches: [master, vNext]
pull_request:

jobs:
Expand All @@ -11,7 +11,7 @@ jobs:
strategy:
matrix:
php:
- 8.1
- 8.3

name: Lint code (PHP ${{ matrix.php }})

Expand Down
7 changes: 4 additions & 3 deletions .github/workflows/run-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name: Tests

on:
push:
branches: [master, v4]
branches: [master, vNext]
pull_request:

jobs:
Expand All @@ -11,13 +11,14 @@ jobs:
strategy:
matrix:
php:
- '8.4'
- '8.3'
- '8.2'
- '8.1'
- '8.0'
deps:
- highest
include:
- {php: '8.0', deps: lowest}
- {php: '8.1', deps: lowest}
- {php: '8.1', deps: dingo}

name: Tests (PHP ${{ matrix.php }} - ${{ matrix.deps }})
Expand Down
14 changes: 14 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,20 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),

### Removed

# 4.39.0 (31 December 2024)
## Added
- Correctly list required fields for nested objects in OpenAPI spec [#905](https://github.com/knuckleswtf/scribe/pull/905)
- Cursor pagination support in API responses (`cursorPaginate`/`paginate=cursor`) [#917](https://github.com/knuckleswtf/scribe/pull/917)

## Fixed
- Fixed type error when attempting to parse Request::validate [#925](https://github.com/knuckleswtf/scribe/pull/925)
- Don't render empty responses as string "null" in OpenAPI spec [#911](https://github.com/knuckleswtf/scribe/pull/911)
- Correctly replace `apiDescriptionUrl`for `external_laravel` (Eelements theme) [#906](https://github.com/knuckleswtf/scribe/pull/906)
- Cast form data values to strings in Postman collection [#926](https://github.com/knuckleswtf/scribe/pull/926)

## Modified
- Resolve PHP 8.4 deprecations [#929](https://github.com/knuckleswtf/scribe/pull/929)

# 4.38.0 (18 October 2024)
## Fixed
- Elements theme: Fix display of boolean examples [#887](https://github.com/knuckleswtf/scribe/pull/887)
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
}
],
"require": {
"php": ">=8.0",
"php": ">=8.1",
"ext-fileinfo": "*",
"ext-json": "*",
"ext-pdo": "*",
Expand Down
2 changes: 1 addition & 1 deletion composer.lowest.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
}
],
"require": {
"php": ">=8.0",
"php": ">=8.1",
"ext-fileinfo": "*",
"ext-json": "*",
"ext-pdo": "*",
Expand Down
4 changes: 2 additions & 2 deletions config/scribe.php
Original file line number Diff line number Diff line change
Expand Up @@ -106,7 +106,7 @@
// Options: query, body, basic, bearer, header (for custom header)
'in' => 'bearer',

// The name of the auth parameter (eg token, key, apiKey) or header (eg Authorization, Api-Key).
// The name of the auth parameter (e.g. token, key, apiKey) or header (e.g. Authorization, Api-Key).
'name' => 'key',

// The value of the parameter to be used by Scribe to authenticate response calls.
Expand Down Expand Up @@ -189,7 +189,7 @@
'last_updated' => 'Last updated: {date:F j, Y}',

'examples' => [
// Set this to any number (eg. 1234) to generate the same example values for parameters on each run,
// Set this to any number (e.g. 1234) to generate the same example values for parameters on each run,
'faker_seed' => null,

// With API resources and transformers, Scribe tries to generate example models to use in your API responses.
Expand Down
6 changes: 2 additions & 4 deletions src/Attributes/GenericParam.php
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,10 @@ protected function getEnumValues(): array
return $this->enum;
}

if (function_exists('enum_exists') && enum_exists($this->enum)
&& method_exists($this->enum, 'tryFrom')
) {
if (enum_exists($this->enum) && method_exists($this->enum, 'tryFrom')) {
return array_map(
// $case->value only exists on BackedEnums, not UnitEnums
// method_exists($enum, 'tryFrom') implies $enum instanceof BackedEnum
// method_exists($enum, 'tryFrom') implies the enum is a BackedEnum
// @phpstan-ignore-next-line
fn ($case) => $case->value,
$this->enum::cases()
Expand Down
8 changes: 4 additions & 4 deletions src/Config/Extracting.php
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ public static function auth(
bool $default = false,
string $in = 'bearer',
string $name = 'key',
string $useValue = null,
?string $useValue = null,
string $placeholder = '{YOUR_AUTH_KEY}',
string $extraInfo = ''
): array
Expand All @@ -48,10 +48,10 @@ public static function with(
Routes $routes,
string $defaultGroup = 'Endpoints',
array $databaseConnectionsToTransact = [],
int $fakerSeedForExamples = null,
?int $fakerSeedForExamples = null,
array $dataSourcesForExampleModels = ['factoryCreate', 'factoryMake', 'databaseFirst'],
string $routeMatcher = null,
string $fractalSerializer = null,
?string $routeMatcher = null,
?string $fractalSerializer = null,
array $auth = [],
array $strategies = [],
): Extracting
Expand Down
6 changes: 3 additions & 3 deletions src/Config/Output.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ class Output
{
public static function with(
string $theme = 'default',
string $title = null,
?string $title = null,
string $description = '',
array $baseUrls = [],
array $exampleLanguages = ['bash', 'javascript'],
Expand Down Expand Up @@ -45,7 +45,7 @@ public function __construct(
public static function laravelType(
bool $addRoutes = true,
string $docsUrl = '/docs',
string $assetsDirectory = null,
?string $assetsDirectory = null,
array $middleware = [],
): array
{
Expand Down Expand Up @@ -93,7 +93,7 @@ public static function openApi(

public static function tryItOut(
bool $enabled = true,
string $baseUrl = null,
?string $baseUrl = null,
bool $useCsrf = false,
string $csrfUrl = '/sanctum/csrf-cookie',
): array
Expand Down
2 changes: 1 addition & 1 deletion src/Extracting/ApiDetails.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ class ApiDetails

public function __construct(
PathConfig $paths,
DocumentationConfig $config = null,
?DocumentationConfig $config = null,
bool $preserveUserChanges = true
) {
$this->markdownOutputPath = $paths->intermediateOutputPath(); //.scribe by default
Expand Down
2 changes: 1 addition & 1 deletion src/Extracting/Extractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class Extractor

private static ?Route $routeBeingProcessed = null;

public function __construct(DocumentationConfig $config = null)
public function __construct(?DocumentationConfig $config = null)
{
// If no config is injected, pull from global
$this->config = $config ?: new DocumentationConfig(config('scribe'));
Expand Down
2 changes: 1 addition & 1 deletion src/Extracting/ParamHelpers.php
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ protected function getDummyValueGenerator(string $type, array $hints = []): \Clo
return $fakeFactoriesByType[$baseType] ?? $fakeFactoriesByType['string'];
}

private function getDummyDataGeneratorBetween(string $type, $min, $max = 90, string $fieldName = null): \Closure
private function getDummyDataGeneratorBetween(string $type, $min, $max = 90, ?string $fieldName = null): \Closure
{
$hints = [
'name' => $fieldName,
Expand Down
4 changes: 2 additions & 2 deletions src/Extracting/ParsesValidationRules.php
Original file line number Diff line number Diff line change
Expand Up @@ -205,15 +205,15 @@ protected function parseRule($rule, array &$parameterData, bool $independentOnly
return true;
}

if (function_exists('enum_exists') && $rule instanceof \Illuminate\Validation\Rules\Enum) {
if ($rule instanceof \Illuminate\Validation\Rules\Enum) {
$reflection = new \ReflectionClass($rule);
$property = $reflection->getProperty('type');
$property->setAccessible(true);
$type = $property->getValue($rule);

if (enum_exists($type) && method_exists($type, 'tryFrom')) {
// $case->value only exists on BackedEnums, not UnitEnums
// method_exists($enum, 'tryFrom') implies $enum instanceof BackedEnum
// method_exists($enum, 'tryFrom') implies the enum is a BackedEnum
// @phpstan-ignore-next-line
$cases = array_map(fn ($case) => $case->value, $type::cases());
$parameterData['type'] = gettype($cases[0]);
Expand Down
2 changes: 1 addition & 1 deletion src/Extracting/Shared/UrlParamsNormalizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ public static function getTypeHintedEnums(ReflectionFunctionAbstract $method): a
* @return string|null
*/
protected static function getRouteKeyForUrlParam(
Route $route, string $paramName, array $typeHintedEloquentModels = [], string $default = null
Route $route, string $paramName, array $typeHintedEloquentModels = [], ?string $default = null
): ?string
{
if ($binding = self::getInlineRouteKey($route, $paramName)) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,14 @@ public static function find(Node $node)

if (
$expr instanceof Node\Expr\StaticCall
&& in_array((string) $expr->class, ['Request', \Illuminate\Support\Facades\Request::class])
&& $expr->class instanceof Node\Name
&& in_array($expr->class->name, ['Request', \Illuminate\Support\Facades\Request::class])
) {
if ($expr->name->name == "validate") {
if ($expr->name->name === "validate") {
return $expr->args[0]->value;
}

if ($expr->name->name == "validateWithBag") {
if ($expr->name->name === "validateWithBag") {
return $expr->args[1]->value;
}
}
Expand Down
3 changes: 1 addition & 2 deletions src/Extracting/Strategies/GetFromInlineValidatorBase.php
Original file line number Diff line number Diff line change
Expand Up @@ -84,12 +84,11 @@ public function lookForInlineValidationRules(ClassMethod $methodAst): array
}
// Try to extract Enum rule
else if (
function_exists('enum_exists') &&
($enum = $this->extractEnumClassFromArrayItem($arrayItem)) &&
enum_exists($enum) && method_exists($enum, 'tryFrom')
) {
// $case->value only exists on BackedEnums, not UnitEnums
// method_exists($enum, 'tryFrom') implies $enum instanceof BackedEnum
// method_exists($enum, 'tryFrom') implies the enum is a BackedEnum
// @phpstan-ignore-next-line
$rulesList[] = 'in:' . implode(',', array_map(fn ($case) => $case->value, $enum::cases()));
}
Expand Down
2 changes: 1 addition & 1 deletion src/Extracting/Strategies/Metadata/GetFromDocBlocks.php
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ public function getMetadataFromDocBlock(DocBlock $methodDocBlock, DocBlock $clas
return $metadata;
}

protected function getAuthStatusFromDocBlock(DocBlock $methodDocBlock, DocBlock $classDocBlock = null): ?bool
protected function getAuthStatusFromDocBlock(DocBlock $methodDocBlock, ?DocBlock $classDocBlock = null): ?bool
{
foreach ($methodDocBlock->getTags() as $tag) {
if (strtolower($tag->getName()) === 'authenticated') {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -186,7 +186,7 @@ protected function setTypesAndExamplesForOthers(array $parameters, ExtractedEndp
*
* @return string|null
*/
protected function getNameOfUrlThing(string $url, string $paramName, string $alternateParamName = null): ?string
protected function getNameOfUrlThing(string $url, string $paramName, ?string $alternateParamName = null): ?string
{
$parts = explode("/", $url);
if (count($parts) === 1) return null; // URL was "/{thing}"
Expand Down
2 changes: 1 addition & 1 deletion src/Scribe.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

class Scribe
{
public const VERSION = '4.38.0';
public const VERSION = '4.39.0';

/**
* Specify a callback that will be executed just before a response call is made
Expand Down
2 changes: 1 addition & 1 deletion src/Tools/BladeMarkdownEngine.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class BladeMarkdownEngine extends CompilerEngine
{
private Parsedown $markdown;

public function __construct(CompilerInterface $compiler, Filesystem $files = null)
public function __construct(CompilerInterface $compiler, ?Filesystem $files = null)
{
parent::__construct($compiler, $files ?: new Filesystem);
$this->markdown = Parsedown::instance();
Expand Down
4 changes: 2 additions & 2 deletions src/Tools/PathConfig.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ public function __construct(
}
}

public function outputPath(string $resolvePath = null, string $separator = '/'): string
public function outputPath(?string $resolvePath = null, string $separator = '/'): string
{
if (is_null($resolvePath)) {
return $this->configName;
Expand All @@ -36,7 +36,7 @@ public function configFileName(): string
/**
* The directory where Scribe writes its intermediate output (default is .<config> ie .scribe)
*/
public function intermediateOutputPath(string $resolvePath = null, string $separator = '/'): string
public function intermediateOutputPath(?string $resolvePath = null, string $separator = '/'): string
{
if (is_null($resolvePath)) {
return $this->scribeDir;
Expand Down
2 changes: 1 addition & 1 deletion src/Writing/HtmlWriter.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class HtmlWriter
protected string $assetPathPrefix;
protected MarkdownParser $markdownParser;

public function __construct(DocumentationConfig $config = null)
public function __construct(?DocumentationConfig $config = null)
{
$this->config = $config ?: new DocumentationConfig(config('scribe', []));
$this->markdownParser = new MarkdownParser();
Expand Down
6 changes: 3 additions & 3 deletions src/Writing/OpenAPISpecWriter.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ class OpenAPISpecWriter

private DocumentationConfig $config;

public function __construct(DocumentationConfig $config = null)
public function __construct(?DocumentationConfig $config = null)
{
$this->config = $config ?: new DocumentationConfig(config('scribe', []));
}
Expand Down Expand Up @@ -400,7 +400,7 @@ protected function generateResponseContentSpec(?string $responseContent, OutputE
],
'example' => $decoded,
],
],
],
];

case 'object':
Expand Down Expand Up @@ -661,7 +661,7 @@ public function filterRequiredFields(OutputEndpointData $endpoint, array $proper

return $required;
}

/*
* Set the description for the schema. If the field has a description, it is set in the schema.
*/
Expand Down
4 changes: 2 additions & 2 deletions src/Writing/PostmanCollectionWriter.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ class PostmanCollectionWriter

protected string $baseUrl;

public function __construct(DocumentationConfig $config = null)
public function __construct(?DocumentationConfig $config = null)
{
$this->config = $config ?: new DocumentationConfig(config('scribe', []));
$this->baseUrl = $this->config->get('base_url') ?: config('app.url');
Expand Down Expand Up @@ -222,7 +222,7 @@ protected function getFormDataParams(array $paramsKeyValue, ?string $key = null,
if (!is_array($value)) {
$body[] = [
'key' => $index,
'value' => $value,
'value' => (string) $value,
'type' => 'text',
'description' => $paramsFullDetails[$index]->description ?? '',
];
Expand Down
5 changes: 0 additions & 5 deletions tests/Fixtures/TestController.php
Original file line number Diff line number Diff line change
Expand Up @@ -704,19 +704,14 @@ public function withEnumRule(Request $request)
]);
}

/**
* Can only run on PHP 8.1
public function withInjectedEnumAndModel(Category $category, TestUser $user)
{
return null;
}
*/
}

/**
enum Category: string
{
case Fruits = 'fruits';
case People = 'people';
}
*/
Loading

0 comments on commit 781b9fd

Please sign in to comment.