Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion examples/petstore/Data/Pet/DeletePetHeaderData.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ public function __construct(
* lowercased) and each value is an array, so the first value of each
* declared header is taken before validation.
*/
public static function fromHeaders(Request $request): static
public static function fromHeaders(Request $request): self
{
$all = $request->headers->all();
$headers = [];
Expand Down
2 changes: 1 addition & 1 deletion examples/petstore/Data/Pet/DeletePetPathData.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function __construct(
* only, so path-segment constraints are enforced at runtime (a bad value
* is a 422, not a silent 200).
*/
public static function fromRoute(Request $request): static
public static function fromRoute(Request $request): self
{
return self::validateAndCreate($request->route()->parameters());
}
Expand Down
2 changes: 1 addition & 1 deletion examples/petstore/Data/Pet/FindPetsByStatusQueryData.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function __construct(
* Validate against rules() and hydrate from the query string only, so
* request-body fields never bleed into query validation (or vice versa).
*/
public static function fromQuery(Request $request): static
public static function fromQuery(Request $request): self
{
return self::validateAndCreate($request->query->all());
}
Expand Down
2 changes: 1 addition & 1 deletion examples/petstore/Data/Pet/FindPetsByTagsQueryData.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function __construct(
* Validate against rules() and hydrate from the query string only, so
* request-body fields never bleed into query validation (or vice versa).
*/
public static function fromQuery(Request $request): static
public static function fromQuery(Request $request): self
{
return self::validateAndCreate($request->query->all());
}
Expand Down
2 changes: 1 addition & 1 deletion examples/petstore/Data/Pet/GetPetByIdPathData.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function __construct(
* only, so path-segment constraints are enforced at runtime (a bad value
* is a 422, not a silent 200).
*/
public static function fromRoute(Request $request): static
public static function fromRoute(Request $request): self
{
return self::validateAndCreate($request->route()->parameters());
}
Expand Down
2 changes: 1 addition & 1 deletion examples/petstore/Data/Pet/UpdatePetWithFormPathData.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function __construct(
* only, so path-segment constraints are enforced at runtime (a bad value
* is a 422, not a silent 200).
*/
public static function fromRoute(Request $request): static
public static function fromRoute(Request $request): self
{
return self::validateAndCreate($request->route()->parameters());
}
Expand Down
2 changes: 1 addition & 1 deletion examples/petstore/Data/Pet/UpdatePetWithFormQueryData.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function __construct(
* Validate against rules() and hydrate from the query string only, so
* request-body fields never bleed into query validation (or vice versa).
*/
public static function fromQuery(Request $request): static
public static function fromQuery(Request $request): self
{
return self::validateAndCreate($request->query->all());
}
Expand Down
2 changes: 1 addition & 1 deletion examples/petstore/Data/Pet/UploadFilePathData.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function __construct(
* only, so path-segment constraints are enforced at runtime (a bad value
* is a 422, not a silent 200).
*/
public static function fromRoute(Request $request): static
public static function fromRoute(Request $request): self
{
return self::validateAndCreate($request->route()->parameters());
}
Expand Down
2 changes: 1 addition & 1 deletion examples/petstore/Data/Pet/UploadFileQueryData.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public function __construct(
* Validate against rules() and hydrate from the query string only, so
* request-body fields never bleed into query validation (or vice versa).
*/
public static function fromQuery(Request $request): static
public static function fromQuery(Request $request): self
{
return self::validateAndCreate($request->query->all());
}
Expand Down
2 changes: 1 addition & 1 deletion examples/petstore/Data/Store/DeleteOrderPathData.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function __construct(
* only, so path-segment constraints are enforced at runtime (a bad value
* is a 422, not a silent 200).
*/
public static function fromRoute(Request $request): static
public static function fromRoute(Request $request): self
{
return self::validateAndCreate($request->route()->parameters());
}
Expand Down
2 changes: 1 addition & 1 deletion examples/petstore/Data/Store/GetOrderByIdPathData.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function __construct(
* only, so path-segment constraints are enforced at runtime (a bad value
* is a 422, not a silent 200).
*/
public static function fromRoute(Request $request): static
public static function fromRoute(Request $request): self
{
return self::validateAndCreate($request->route()->parameters());
}
Expand Down
2 changes: 1 addition & 1 deletion examples/petstore/Data/User/DeleteUserPathData.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function __construct(
* only, so path-segment constraints are enforced at runtime (a bad value
* is a 422, not a silent 200).
*/
public static function fromRoute(Request $request): static
public static function fromRoute(Request $request): self
{
return self::validateAndCreate($request->route()->parameters());
}
Expand Down
2 changes: 1 addition & 1 deletion examples/petstore/Data/User/GetUserByNamePathData.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function __construct(
* only, so path-segment constraints are enforced at runtime (a bad value
* is a 422, not a silent 200).
*/
public static function fromRoute(Request $request): static
public static function fromRoute(Request $request): self
{
return self::validateAndCreate($request->route()->parameters());
}
Expand Down
2 changes: 1 addition & 1 deletion examples/petstore/Data/User/LoginUserQueryData.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function __construct(
* Validate against rules() and hydrate from the query string only, so
* request-body fields never bleed into query validation (or vice versa).
*/
public static function fromQuery(Request $request): static
public static function fromQuery(Request $request): self
{
return self::validateAndCreate($request->query->all());
}
Expand Down
2 changes: 1 addition & 1 deletion examples/petstore/Data/User/UpdateUserPathData.php
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public function __construct(
* only, so path-segment constraints are enforced at runtime (a bad value
* is a 422, not a silent 200).
*/
public static function fromRoute(Request $request): static
public static function fromRoute(Request $request): self
{
return self::validateAndCreate($request->route()->parameters());
}
Expand Down
37 changes: 37 additions & 0 deletions qodana.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,40 @@ exclude:
# and couple two otherwise self-contained rules, which breaks the inlining
# story. The duplication is the price of keeping each rule self-contained.
- name: DuplicatedCode
# The remaining `(string) ...` casts the emitter keeps are load-bearing, not
# redundant: `(string) $name` restores the string-key invariant after PHP
# coerces a numeric-string array key (e.g. "200") to int at runtime (the same
# rationale as PhpCastIsUnnecessaryInspection above), and
# `(string) json_encode(...)` collapses json_encode's `string|false` return to
# a string so the `%s` sprintf argument is well-typed. Both guard real
# behaviour, so this inspection is a false positive here.
- name: PhpUnnecessaryStringCast
# PhpSameParameterValue fires on the framework-free CLI's general-purpose
# helpers `repeatedOption()` (StandaloneApplication) and `resolveRepeatable()`
# (CommandRequestFactory). Each is a deliberate, named, reusable seam (parse a
# repeatable --flag from argv; resolve a repeatable flag against its config
# key); they happen to have a single repeatable flag today. Inlining the flag
# name would couple a generic parser to one option and hurt readability, so
# the seam is intentional, not dead generality.
- name: PhpSameParameterValue
paths:
- src/Console/StandaloneApplication.php
- src/Console/CommandRequestFactory.php
# bin/openapi-laravel is the package's own framework-free entry point and the
# legitimate first-party consumer of StandaloneApplication. The class is
# @internal by design (#69: the whole PHP class API is internal; the supported
# interface is the CLI and the artisan command, not direct class use), so the
# bin script using it is correct, not a violation.
- name: PhpInternalEntityUsed
paths:
- bin/openapi-laravel
# The Clover report fed to Qodana (#89) comes from the FAST suite only
# (--exclude-group=slow), so the slow corpus gate (ReaderCorpusBaselineTest
# runs the parser/emitter over all 135 specs) never contributes coverage to
# the report. The lines that gate alone exercises then show up as
# "uncovered" in Qodana even though the full `composer test` run hits them
# and the dedicated 100% line-coverage gate (`composer test:type`) enforces
# them. Running the full slow suite under coverage in this informational
# workflow would roughly triple its runtime for no signal we do not already
# have, so this inspection is pure noise here.
- name: PhpCoverageInspection
8 changes: 4 additions & 4 deletions src/Console/CommandRequestFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public function fromCommand(Command $command, bool $stubs = false): GenerationRe

// Security-to-middleware mapping (issue #77). Config-only like the
// route group settings: a map is config-shaped, there is no CLI flag.
$securityMiddlewareMap = $this->configMiddlewareMap('openapi-laravel.security.middleware_map');
$securityMiddlewareMap = $this->configMiddlewareMap();

return new GenerationRequest(
$spec,
Expand Down Expand Up @@ -132,9 +132,9 @@ public function fromCommand(Command $command, bool $stubs = false): GenerationRe
*
* @return array<string, list<string>>
*/
private function configMiddlewareMap(string $key): array
private function configMiddlewareMap(): array
{
$configured = config($key);
$configured = config('openapi-laravel.security.middleware_map');
if (! is_array($configured)) {
return [];
}
Expand Down Expand Up @@ -332,7 +332,7 @@ private function resolveToggle(Command $command, string $flag, string $configKey

$configured = config($configKey);

return $configured === null ? true : (bool) $configured;
return $configured === null || (bool) $configured;
}

private function stringOption(Command $command, string $name): ?string
Expand Down
12 changes: 6 additions & 6 deletions src/Emitter/ClassRenderer.php
Original file line number Diff line number Diff line change
Expand Up @@ -453,7 +453,7 @@ private function renderFromQuery(array $booleanNames, array $delimitedArrays = [
if ($booleanNames === [] && $delimitedArrays === []) {
return $doc
.' */'."\n"
.' public static function fromQuery(Request $request): static'."\n"
.' public static function fromQuery(Request $request): self'."\n"
." {\n"
.' return self::validateAndCreate($request->query->all());'."\n"
.' }';
Expand Down Expand Up @@ -504,7 +504,7 @@ private function renderFromQuery(array $booleanNames, array $delimitedArrays = [
return $doc
.$docExtra
.' */'."\n"
.' public static function fromQuery(Request $request): static'."\n"
.' public static function fromQuery(Request $request): self'."\n"
." {\n"
.$body
."\n"
Expand Down Expand Up @@ -540,7 +540,7 @@ private function renderFromRoute(array $booleanNames): string
if ($booleanNames === []) {
return $doc
.' */'."\n"
.' public static function fromRoute(Request $request): static'."\n"
.' public static function fromRoute(Request $request): self'."\n"
." {\n"
.' return self::validateAndCreate($request->route()->parameters());'."\n"
.' }';
Expand All @@ -555,7 +555,7 @@ private function renderFromRoute(array $booleanNames): string
.' * Boolean parameters arrive as the form-style literals true / false,'."\n"
.' * which are mapped to 1 / 0 before validation.'."\n"
.' */'."\n"
.' public static function fromRoute(Request $request): static'."\n"
.' public static function fromRoute(Request $request): self'."\n"
." {\n"
.' $parameters = $request->route()->parameters();'."\n"
."\n"
Expand Down Expand Up @@ -622,7 +622,7 @@ private function renderFromHeaders(array $headerNames, array $booleanNames): str
if ($booleanNames === []) {
return $doc
.' */'."\n"
.' public static function fromHeaders(Request $request): static'."\n"
.' public static function fromHeaders(Request $request): self'."\n"
." {\n"
.$prologue
."\n"
Expand All @@ -639,7 +639,7 @@ private function renderFromHeaders(array $headerNames, array $booleanNames): str
.' * Boolean parameters arrive as the form-style literals true / false,'."\n"
.' * which are mapped to 1 / 0 before validation.'."\n"
.' */'."\n"
.' public static function fromHeaders(Request $request): static'."\n"
.' public static function fromHeaders(Request $request): self'."\n"
." {\n"
.$prologue
."\n"
Expand Down
4 changes: 2 additions & 2 deletions src/Emitter/EnumEmitter.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,10 +17,10 @@
*
* @internal
*/
final class EnumEmitter
final readonly class EnumEmitter
{
public function __construct(
private readonly GenerationState $state,
private GenerationState $state,
) {}

public function emitEnum(string $className, SchemaNode $schema): void
Expand Down
8 changes: 6 additions & 2 deletions src/Emitter/RequestDataSynthesizer.php
Original file line number Diff line number Diff line change
Expand Up @@ -208,8 +208,12 @@ public function generateHeaderData(string $baseName, string $operationLabel, arr
* presence-only `mixed`, and header additionally skips the reserved
* framework-owned standard headers.
*
* @param 'query'|'path'|'header' $in
* @param list<ParameterNode> $parameters
* @param 'query'|'path'|'header' $in the parameter location this call synthesizes a class for
* @param string $baseName StudlyCaps operation context (operationId or the method+path fallback), without suffix
* @param string $operationLabel "GET /pets", for warning messages
* @param list<ParameterNode> $parameters the operation's parameters; only those matching `$in` are kept
* @param ?string $tag the operation's first tag (or the 'Untagged' fallback) for the grouped layout (issue #93); ignored in the flat layout
* @return string|null the synthesized class name, or null when every parameter was skipped
*/
private function generateParamData(string $in, string $baseName, string $operationLabel, array $parameters, ?string $tag): ?string
{
Expand Down
39 changes: 15 additions & 24 deletions src/Emitter/Server/OperationCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -967,14 +967,11 @@ private function componentParameters(OpenApiDocument $document): array
return [];
}

$result = [];
foreach ($components->parameters as $name => $parameter) {
if (is_string($name) && $name !== '' && $parameter instanceof ParameterNode) {
$result[$name] = $parameter;
}
}

return $result;
return array_filter(
$components->parameters,
static fn (mixed $parameter, mixed $name): bool => is_string($name) && $name !== '' && $parameter instanceof ParameterNode,
ARRAY_FILTER_USE_BOTH,
);
}

/**
Expand All @@ -993,14 +990,11 @@ private function collectComponentRequestBodies(OpenApiDocument $document): array
return [];
}

$result = [];
foreach ($components->requestBodies as $name => $body) {
if (is_string($name) && $name !== '' && $body instanceof RequestBodyNode) {
$result[$name] = $body;
}
}

return $result;
return array_filter(
$components->requestBodies,
static fn (mixed $body, mixed $name): bool => is_string($name) && $name !== '' && $body instanceof RequestBodyNode,
ARRAY_FILTER_USE_BOTH,
);
}

/**
Expand Down Expand Up @@ -1086,14 +1080,11 @@ private function collectComponentResponses(OpenApiDocument $document): array
return [];
}

$result = [];
foreach ($components->responses as $name => $response) {
if (is_string($name) && $name !== '' && $response instanceof ResponseNode) {
$result[$name] = $response;
}
}

return $result;
return array_filter(
$components->responses,
static fn (mixed $response, mixed $name): bool => is_string($name) && $name !== '' && $response instanceof ResponseNode,
ARRAY_FILTER_USE_BOTH,
);
}

/**
Expand Down
Loading
Loading