Skip to content

Commit ec3b0d5

Browse files
committed
Read schemas from yaml files
1 parent 998a687 commit ec3b0d5

File tree

12 files changed

+247
-54
lines changed

12 files changed

+247
-54
lines changed

src/bundle/ApiPlatform/OpenApiFactory.php

Lines changed: 7 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,10 @@
1313

1414
final class OpenApiFactory implements OpenApiFactoryInterface
1515
{
16-
public function __construct(private readonly OpenApiFactoryInterface $decorated)
17-
{
16+
public function __construct(
17+
private readonly OpenApiFactoryInterface $decorated,
18+
private readonly SchemasCollectionFactory $schemaCollectionFactory,
19+
) {
1820
}
1921

2022
/**
@@ -24,59 +26,11 @@ public function __invoke(array $context = []): OpenApi
2426
{
2527
$openApi = $this->decorated->__invoke($context);
2628

27-
/** @var \ArrayObject<string, mixed> $schemas */
28-
$schemas = new \ArrayObject();
29-
$schemas['BaseObject'] = [
30-
'type' => 'object',
31-
'required' => ['_media-type', '_href'],
32-
'properties' => [
33-
'_media-type' => [
34-
'type' => 'string',
35-
],
36-
'_href' => [
37-
'type' => 'string',
38-
],
39-
],
40-
];
41-
$schemas['Language'] = [
42-
'allOf' => [
43-
[
44-
'$ref' => '#/components/schemas/BaseObject',
45-
],
46-
[
47-
'type' => 'object',
48-
'required' => ['id', 'languageCode', 'name', 'enabled'],
49-
'properties' => [
50-
'id' => [
51-
'description' => 'The language ID (auto generated).',
52-
'type' => 'integer',
53-
],
54-
'languageCode' => [
55-
'description' => 'The languageCode code.',
56-
'type' => 'string',
57-
],
58-
'name' => [
59-
'description' => 'Human readable name of the language.',
60-
'type' => 'string',
61-
],
62-
'enabled' => [
63-
'description' => 'Indicates if the language is enabled or not.',
64-
'type' => 'boolean',
65-
],
66-
],
67-
],
68-
],
69-
];
70-
$schemas['LanguageList'] = [
71-
'description' => ' List of languages.',
72-
'type' => 'array',
73-
'items' => [
74-
'$ref' => '#/components/schemas/Language',
75-
],
76-
];
29+
$schemasCollection = $this->schemaCollectionFactory->create();
30+
$schemas = iterator_to_array($schemasCollection);
7731

7832
$components = $openApi->getComponents();
79-
$components = $components->withSchemas($schemas);
33+
$components = $components->withSchemas(new \ArrayObject($schemas));
8034

8135
$openApi = $openApi->withComponents($components);
8236

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Ibexa\Bundle\Rest\ApiPlatform;
10+
11+
use Ibexa\Rest\ApiPlatform\SchemasCollection;
12+
use Ibexa\Rest\ApiPlatform\SchemasCollectionFactoryInterface;
13+
use Ibexa\Rest\ApiPlatform\SchemasProviderInterface;
14+
15+
/**
16+
* @internal
17+
*/
18+
final class SchemasCollectionFactory implements SchemasCollectionFactoryInterface
19+
{
20+
/**
21+
* @var array<SchemasProviderInterface>
22+
*/
23+
private array $providers = [];
24+
25+
public function create(): SchemasCollection
26+
{
27+
$schemas = [];
28+
29+
foreach ($this->providers as $provider) {
30+
$schemas = array_merge($schemas, $provider->getSchemas());
31+
}
32+
33+
return new SchemasCollection($schemas);
34+
}
35+
36+
public function addProvider(SchemasProviderInterface $provider): void
37+
{
38+
$this->providers[] = $provider;
39+
}
40+
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
8+
namespace Ibexa\Bundle\Rest\DependencyInjection\Compiler;
9+
10+
use Ibexa\Bundle\Rest\ApiPlatform\SchemasCollectionFactory;
11+
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
12+
use Symfony\Component\DependencyInjection\ContainerBuilder;
13+
use Symfony\Component\DependencyInjection\Reference;
14+
15+
class SchemaProviderPass implements CompilerPassInterface
16+
{
17+
public const API_PLATFORM_SCHEMA_PROVIDER_SERVICE_TAG = 'ibexa.api_platform.schemas_provider';
18+
19+
public function process(ContainerBuilder $container): void
20+
{
21+
if (!$container->hasDefinition(SchemasCollectionFactory::class)) {
22+
return;
23+
}
24+
25+
$definition = $container->getDefinition(SchemasCollectionFactory::class);
26+
27+
$taggedServiceIds = $container->findTaggedServiceIds(self::API_PLATFORM_SCHEMA_PROVIDER_SERVICE_TAG);
28+
foreach ($taggedServiceIds as $serviceId => $attributes) {
29+
$definition->addMethodCall(
30+
'addProvider',
31+
[new Reference($serviceId)]
32+
);
33+
}
34+
}
35+
}

src/bundle/DependencyInjection/IbexaRestExtension.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99

1010
use Ibexa\Bundle\Core\DependencyInjection\Configuration\SiteAccessAware\ConfigurationProcessor;
1111
use Ibexa\Bundle\Rest\DependencyInjection\Compiler\ClassNameResourceNamePass;
12+
use Ibexa\Bundle\Rest\DependencyInjection\Compiler\SchemaProviderPass;
13+
use Ibexa\Rest\ApiPlatform\SchemasProviderInterface;
1214
use Ibexa\Rest\Server\Controller as RestController;
1315
use Symfony\Component\Config\FileLocator;
1416
use Symfony\Component\Config\Resource\FileResource;
@@ -93,5 +95,8 @@ private function configureApiPlatformAutotagging(ContainerBuilder $container): v
9395
{
9496
$container->registerForAutoconfiguration(RestController::class)
9597
->addTag(ClassNameResourceNamePass::API_PLATFORM_RESOURCE_SERVICE_TAG);
98+
99+
$container->registerForAutoconfiguration(SchemasProviderInterface::class)
100+
->addTag(SchemaProviderPass::API_PLATFORM_SCHEMA_PROVIDER_SERVICE_TAG);
96101
}
97102
}

src/bundle/IbexaRestBundle.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ public function build(ContainerBuilder $container): void
2424
$container->addCompilerPass(new Compiler\OutputVisitorPass());
2525
$container->addCompilerPass(new Compiler\ValueObjectVisitorPass());
2626
$container->addCompilerPass(new Compiler\ClassNameResourceNamePass());
27+
$container->addCompilerPass(new Compiler\SchemaProviderPass());
2728

2829
if ($container->hasExtension('lexik_jwt_authentication')) {
2930
$container->addCompilerPass(new Compiler\LexikAuthorizationHeaderBridgePass());
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
schemas:
2+
BaseObject:
3+
type: object
4+
required:
5+
- _media-type
6+
- _href
7+
properties:
8+
_media-type:
9+
type: string
10+
_href:
11+
type: string
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
schemas:
2+
Language:
3+
allOf:
4+
- ref: "#/components/schemas/BaseObject"
5+
- type: object
6+
description: This class represents a language in the Repository.
7+
required:
8+
- id
9+
- languageCode
10+
- name
11+
- enabled
12+
properties:
13+
id:
14+
description: The language ID (auto generated).
15+
type: integer
16+
languageCode:
17+
description: The languageCode code.
18+
type: string
19+
name:
20+
description: Human readable name of the language.
21+
type: string
22+
enabled:
23+
description: Indicates if the language is enabled or not.
24+
type: boolean
25+
LanguageList:
26+
description: List of languages.
27+
type: array
28+
items:
29+
$ref: "#/components/schemas/Language"

src/bundle/Resources/config/api_platform.yml

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,28 @@ services:
1818
ibexa.api_platform.ibexa_openapi.factory:
1919
class: 'Ibexa\Bundle\Rest\ApiPlatform\OpenApiFactory'
2020
decorates: ibexa.api_platform.openapi.factory
21-
arguments: ['@.inner']
21+
arguments:
22+
- '@.inner'
23+
- '@Ibexa\Bundle\Rest\ApiPlatform\SchemasCollectionFactory'
2224

2325
ibexa.api_platform.openapi.factory:
2426
parent: api_platform.openapi.factory
2527
arguments:
2628
index_0: '@Ibexa\Bundle\Rest\ApiPlatform\ClassNameResourceNameCollectionFactory'
2729

2830
Ibexa\Bundle\Rest\ApiPlatform\ClassNameResourceNameCollectionFactory: ~
31+
32+
33+
# Collecting schemas
34+
35+
Ibexa\Bundle\Rest\ApiPlatform\SchemasCollectionFactory: ~
36+
37+
ibexa.api_platform.schemas_provider.rest:
38+
class: Ibexa\Rest\ApiPlatform\SchemasProvider
39+
autowire: true
40+
autoconfigure: true
41+
arguments:
42+
$files:
43+
- '@@IbexaRestBundle/Resources/api_platform/base.yml'
44+
- '@@IbexaRestBundle/Resources/api_platform/language_schemas.yml'
45+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Ibexa\Rest\ApiPlatform;
10+
11+
final class SchemasCollection implements \IteratorAggregate, \Countable
12+
{
13+
/**
14+
* @param array<string, mixed> $schemas
15+
*/
16+
public function __construct(private readonly array $schemas = [])
17+
{
18+
}
19+
20+
/**
21+
* @return \Traversable<string>
22+
*/
23+
public function getIterator(): \Traversable
24+
{
25+
return new \ArrayIterator($this->schemas);
26+
}
27+
28+
public function count(): int
29+
{
30+
return \count($this->schemas);
31+
}
32+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
3+
/**
4+
* @copyright Copyright (C) Ibexa AS. All rights reserved.
5+
* @license For full copyright and license information view LICENSE file distributed with this source code.
6+
*/
7+
declare(strict_types=1);
8+
9+
namespace Ibexa\Rest\ApiPlatform;
10+
11+
interface SchemasCollectionFactoryInterface
12+
{
13+
public function create(): mixed;
14+
}

0 commit comments

Comments
 (0)