From c16095cbef6df3963129fcef31403c5bdf7b00dc Mon Sep 17 00:00:00 2001 From: Jakov Knezovic Date: Fri, 5 Jun 2026 15:03:23 +0200 Subject: [PATCH 1/5] NGSTACK-1017 cover array type object schema reference jsonld enhancement --- .../JsonSchema/SchemaFactoryDecorator.php | 77 +++++++++++++------ 1 file changed, 55 insertions(+), 22 deletions(-) diff --git a/src/ApiPlatform/JsonSchema/SchemaFactoryDecorator.php b/src/ApiPlatform/JsonSchema/SchemaFactoryDecorator.php index 96e39c1..e163f3f 100644 --- a/src/ApiPlatform/JsonSchema/SchemaFactoryDecorator.php +++ b/src/ApiPlatform/JsonSchema/SchemaFactoryDecorator.php @@ -58,38 +58,69 @@ public function buildSchema(string $className, string $format = 'json', string $ /** @param ArrayObject $definitions */ private function ensureJsonldInputPropertyForInputSchemas(string $reference, string $schemaPrefix, ArrayObject $definitions): void { - $definitionName = str_replace($schemaPrefix, '', $reference); - - foreach ($definitions[$definitionName]['properties'] ?? [] as $property) { - if (isset($property['type'])) { + foreach ($definitions[$this->stripSchemaPrefix($schemaPrefix, $reference)]['properties'] ?? [] as $property) { + if ( + isset($property['type']) + && $property['type'] !== 'array' + ) { continue; } if (isset($property['$ref'])) { $this->addJsonldInputProperty( + $this->stripSchemaPrefix( + $schemaPrefix, + $property['$ref'], + ), + $definitions, + ); + + continue; + } + + if (isset($property['items']['$ref'])) { + $this->addJsonldInputProperty( + $this->stripSchemaPrefix( + $schemaPrefix, + $property['items']['$ref'], + ), $definitions, - $schemaPrefix, - $property['$ref'], ); - break; + continue; } foreach (self::SCHEMA_LOGICAL_OPERATORS as $operator) { - if (!isset($property[$operator])) { - continue; + if (isset($property[$operator])) { + foreach ($property[$operator] as $subschema) { + if (!isset($subschema['$ref'])) { + continue; + } + + $this->addJsonldInputProperty( + $this->stripSchemaPrefix( + $schemaPrefix, + $subschema['$ref'], + ), + $definitions, + ); + } } - foreach ($property[$operator] as $subschema) { - if (!isset($subschema['$ref'])) { - continue; + if (isset($property['items'][$operator])) { + foreach ($property['items'][$operator] as $subschema) { + if (!isset($subschema['$ref'])) { + continue; + } + + $this->addJsonldInputProperty( + $this->stripSchemaPrefix( + $schemaPrefix, + $subschema['$ref'], + ), + $definitions, + ); } - - $this->addJsonldInputProperty( - $definitions, - $schemaPrefix, - $subschema['$ref'], - ); } } } @@ -97,13 +128,15 @@ private function ensureJsonldInputPropertyForInputSchemas(string $reference, str /** @param ArrayObject $definitions */ private function addJsonldInputProperty( + string $definitionKey, ArrayObject $definitions, - string $schemaPrefix, - string $ref, ): void { - $definitionKey = str_replace($schemaPrefix, '', $ref); - $definitions[$definitionKey]['properties'][self::JSONLD_INPUT_OBJECT_PROPERTY_NAME] ??= self::JSONLD_INPUT_OBJECT_PROPERTY; } + + private function stripSchemaPrefix(string $schemaPrefix, string $reference): string + { + return str_replace($schemaPrefix, '', $reference); + } } From 4adac78f600ad93ec756b9bb95e87b9605b5bbf8 Mon Sep 17 00:00:00 2001 From: Jakov Knezovic Date: Fri, 5 Jun 2026 15:06:09 +0200 Subject: [PATCH 2/5] NGSTACK-1017 fix phpstan on null key arrray access --- src/Service/IriTemplatesService.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/Service/IriTemplatesService.php b/src/Service/IriTemplatesService.php index 750f9da..da757a4 100644 --- a/src/Service/IriTemplatesService.php +++ b/src/Service/IriTemplatesService.php @@ -13,6 +13,7 @@ use Symfony\Component\Routing\Route; use Symfony\Component\Routing\RouterInterface; +use function is_string; use function preg_replace; final class IriTemplatesService @@ -52,12 +53,16 @@ public function getIriTemplatesData(): array /** @var string $operationName */ $operationName = $operation->getName(); $route = $routeCollection->get($operationName); + $shortName = $resourceMetadata->getShortName(); - if (!$route instanceof Route) { + if ( + !$route instanceof Route + || !is_string($shortName) + ) { continue; } - $iriTemplates[$resourceMetadata->getShortName()] = $this->sanitizePath($route->getPath()); + $iriTemplates[$shortName] = $this->sanitizePath($route->getPath()); break; } From 66e35dfd86c07d20c0cebde6c5bcac65be09e0af Mon Sep 17 00:00:00 2001 From: Jakov Knezovic Date: Fri, 5 Jun 2026 15:28:41 +0200 Subject: [PATCH 3/5] NGSTACK-1017 move reference collection to separate method --- .../JsonSchema/SchemaFactoryDecorator.php | 54 +++++++++---------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/src/ApiPlatform/JsonSchema/SchemaFactoryDecorator.php b/src/ApiPlatform/JsonSchema/SchemaFactoryDecorator.php index e163f3f..db01349 100644 --- a/src/ApiPlatform/JsonSchema/SchemaFactoryDecorator.php +++ b/src/ApiPlatform/JsonSchema/SchemaFactoryDecorator.php @@ -58,34 +58,40 @@ public function buildSchema(string $className, string $format = 'json', string $ /** @param ArrayObject $definitions */ private function ensureJsonldInputPropertyForInputSchemas(string $reference, string $schemaPrefix, ArrayObject $definitions): void { - foreach ($definitions[$this->stripSchemaPrefix($schemaPrefix, $reference)]['properties'] ?? [] as $property) { + foreach ( + $this->collectReferences( + $definitions[ + $this->stripSchemaPrefix($schemaPrefix, $reference) + ]['properties'] ?? [], + $schemaPrefix, + ) as $definitionKey) { + $this->addJsonldInputProperty($definitionKey, $definitions); + } + } + + /** + * @param array> $properties + * + * @return iterable + */ + private function collectReferences(array $properties, string $schemaPrefix): iterable + { + foreach ($properties as $property) { if ( isset($property['type']) - && $property['type'] !== 'array' + && !isset($property['items']) ) { continue; } if (isset($property['$ref'])) { - $this->addJsonldInputProperty( - $this->stripSchemaPrefix( - $schemaPrefix, - $property['$ref'], - ), - $definitions, - ); + yield $this->stripSchemaPrefix($schemaPrefix, $property['$ref']); continue; } if (isset($property['items']['$ref'])) { - $this->addJsonldInputProperty( - $this->stripSchemaPrefix( - $schemaPrefix, - $property['items']['$ref'], - ), - $definitions, - ); + yield $this->stripSchemaPrefix($schemaPrefix, $property['items']['$ref']); continue; } @@ -97,13 +103,7 @@ private function ensureJsonldInputPropertyForInputSchemas(string $reference, str continue; } - $this->addJsonldInputProperty( - $this->stripSchemaPrefix( - $schemaPrefix, - $subschema['$ref'], - ), - $definitions, - ); + yield $this->stripSchemaPrefix($schemaPrefix, $subschema['$ref']); } } @@ -113,13 +113,7 @@ private function ensureJsonldInputPropertyForInputSchemas(string $reference, str continue; } - $this->addJsonldInputProperty( - $this->stripSchemaPrefix( - $schemaPrefix, - $subschema['$ref'], - ), - $definitions, - ); + yield $this->stripSchemaPrefix($schemaPrefix, $subschema['$ref']); } } } From deb9abfc3855b87468966e40f968d0e95e1a057d Mon Sep 17 00:00:00 2001 From: Jakov Knezovic Date: Fri, 5 Jun 2026 15:55:07 +0200 Subject: [PATCH 4/5] NGSTACK-1017 bump security advisory affected versions in composer.json --- .github/workflows/static_analysis.yml | 2 +- composer.json | 24 ++++++++++++------------ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml index 6431e04..8f8e4a1 100644 --- a/.github/workflows/static_analysis.yml +++ b/.github/workflows/static_analysis.yml @@ -29,7 +29,7 @@ jobs: - run: composer global config --no-plugins allow-plugins.symfony/flex true - run: composer global require --no-scripts symfony/flex - - run: composer config extra.symfony.require ~7.3.0 + - run: composer config extra.symfony.require ~7.4.13 - run: composer update --prefer-dist diff --git a/composer.json b/composer.json index 180612f..c2eae0f 100644 --- a/composer.json +++ b/composer.json @@ -22,18 +22,18 @@ "minimum-stability": "beta", "require": { "php": ">=8.4", - "symfony/routing": "^7.3 || ^8.0", - "symfony/config": "^7.3 || ^8.0", - "symfony/dependency-injection": "^7.3 || ^8.0", - "symfony/event-dispatcher": "^7.3 || ^8.0", - "symfony/http-foundation": "^7.3 || ^8.0", - "symfony/http-kernel": "^7.3 || ^8.0", - "symfony/property-access": "^7.3 || ^8.0", - "symfony/framework-bundle": "^7.3 || ^8.0", - "symfony/console": "^7.3 || ^8.0", - "symfony/security-core": "^7.3 || ^8.0", - "symfony/security-http": "^7.3 || ^8.0", - "symfony/yaml": "^7.3 || ^8.0", + "symfony/routing": "^7.4.13 || ^8.0.13", + "symfony/http-foundation": "^7.4.13 || ^8.0.13", + "symfony/security-http": "^7.4.13 || ^8.0.13", + "symfony/yaml": "^7.4.13 || ^8.0.13", + "symfony/config": "^7.4.13 || ^8.0.13", + "symfony/dependency-injection": "^7.4.13 || ^8.0.13", + "symfony/event-dispatcher": "^7.4.13 || ^8.0.13", + "symfony/http-kernel": "^7.4.13 || ^8.0.13", + "symfony/property-access": "^7.4.13 || ^8.0.13", + "symfony/framework-bundle": "^7.4.13 || ^8.0.13", + "symfony/console": "^7.4.13 || ^8.0.13", + "symfony/security-core": "^7.4.13 || ^8.0.13", "api-platform/symfony": "^4.2", "api-platform/doctrine-orm": "^4.2", "lexik/jwt-authentication-bundle": "^3.1", From b7032f429e1931b2805989aa4e2d0aeb45129266 Mon Sep 17 00:00:00 2001 From: Jakov Knezovic Date: Fri, 5 Jun 2026 16:01:46 +0200 Subject: [PATCH 5/5] NGSTACK-1017 test lowest safe symfony deps --- .github/workflows/static_analysis.yml | 6 +++--- composer.json | 18 +++++++++--------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/.github/workflows/static_analysis.yml b/.github/workflows/static_analysis.yml index 8f8e4a1..b69bd63 100644 --- a/.github/workflows/static_analysis.yml +++ b/.github/workflows/static_analysis.yml @@ -29,8 +29,8 @@ jobs: - run: composer global config --no-plugins allow-plugins.symfony/flex true - run: composer global require --no-scripts symfony/flex - - run: composer config extra.symfony.require ~7.4.13 + - run: composer config extra.symfony.require ~7.4.0 - - run: composer update --prefer-dist + - run: composer update --prefer-dist --with-all-dependencies - - run: composer ${{ matrix.script }} \ No newline at end of file + - run: composer ${{ matrix.script }} diff --git a/composer.json b/composer.json index c2eae0f..d1e167c 100644 --- a/composer.json +++ b/composer.json @@ -25,15 +25,15 @@ "symfony/routing": "^7.4.13 || ^8.0.13", "symfony/http-foundation": "^7.4.13 || ^8.0.13", "symfony/security-http": "^7.4.13 || ^8.0.13", - "symfony/yaml": "^7.4.13 || ^8.0.13", - "symfony/config": "^7.4.13 || ^8.0.13", - "symfony/dependency-injection": "^7.4.13 || ^8.0.13", - "symfony/event-dispatcher": "^7.4.13 || ^8.0.13", - "symfony/http-kernel": "^7.4.13 || ^8.0.13", - "symfony/property-access": "^7.4.13 || ^8.0.13", - "symfony/framework-bundle": "^7.4.13 || ^8.0.13", - "symfony/console": "^7.4.13 || ^8.0.13", - "symfony/security-core": "^7.4.13 || ^8.0.13", + "symfony/yaml": "^7.4.12 || ^8.0.12", + "symfony/config": "^7.4 || ^8.0", + "symfony/dependency-injection": "^7.4 || ^8.0", + "symfony/event-dispatcher": "^7.4 || ^8.0", + "symfony/http-kernel": "^7.4 || ^8.0", + "symfony/property-access": "^7.4 || ^8.0", + "symfony/framework-bundle": "^7.4 || ^8.0", + "symfony/console": "^7.4 || ^8.0", + "symfony/security-core": "^7.4 || ^8.0", "api-platform/symfony": "^4.2", "api-platform/doctrine-orm": "^4.2", "lexik/jwt-authentication-bundle": "^3.1",