8000 PoC PHP file resource metadata factory · Sylius/SyliusResourceBundle@09d90cc · GitHub
[go: up one dir, main page]

Skip to content

Commit 09d90cc

Browse files
committed
PoC PHP file resource metadata factory
1 parent 69d39f1 commit 09d90cc

File tree

16 files changed

+362
-3
lines changed

16 files changed

+362
-3
lines changed

psalm.xml

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,12 @@
116116
<file name="src/Bundle/Grid/Parser/OptionsParser.php" />
117117
</errorLevel>
118118
</InvalidReturnStatement>
119+
120+
<InvalidNullableReturnType>
121+
<errorLevel type="suppress">
122+
<file name="src/Component/src/Metadata/Extractor/PhpFileMetadataExtractor.php" />
123+
</errorLevel>
124+
</InvalidNullableReturnType>
119125

120126
<InvalidReturnType>
121127
<errorLevel type="suppress">
@@ -179,6 +185,12 @@
179185
</errorLevel>
180186
</NullArgument>
181187

188+
<NullableReturnStatement>
189+
<errorLevel type="suppress">
190+
<file name="src/Component/src/Metadata/Extractor/PhpFileMetadataExtractor.php" />
191+
</errorLevel>
192+
</NullableReturnStatement>
193+
182194
<PossiblyFalseOperand>
183195
<errorLevel type="suppress">
184196
<file name="src/Component/src/Reflection/ClassInfoTrait.php" />
@@ -320,6 +332,12 @@
320332
<directory name="src/Component/legacy/src/Translation" />
321333
</errorLevel>
322334
</UnrecognizedStatement>
335+
336+
<UnresolvableInclude>
337+
<errorLevel type="suppress">
338+
<file name="src/Component/src/Metadata/Extractor/PhpFileMetadataExtractor.php" />
339+
</errorLevel>
340+
</UnresolvableInclude>
323341

324342
<UnsupportedReferenceUsage>
325343
<errorLevel type="suppress">

src/Bundle/DependencyInjection/Configuration.php

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,9 @@ public function getConfigTreeBuilder(): TreeBuilder
3939
->arrayNode('mapping')
4040
->addDefaultsIfNotSet()
4141
->children()
42+
->arrayNode('imports')
43+
->prototype('scalar')->end()
44+
->end()
4245
->arrayNode('paths')
4346
->prototype('scalar')->end()
4447
->end()

src/Bundle/Resources/config/services/metadata.xml

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,14 +21,28 @@
2121
<tag name="cache.pool" />
2222
</service>
2323

24+
<service id="sylius_resource.metadata.extractor.php_file" class="Sylius\Resource\Metadata\Extractor\PhpFileMetadataExtractor">
25+
<argument>%sylius.resource.mapping%</argument>
26+
</service>
27+
28+
<service id="sylius.resource_metadata_collection.factory" alias="sylius.resource_metadata_collection.factory.php_file" />
29+
<service id="Sylius\Resource\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface" alias="sylius.resource_metadata_collection.factory.php_file" />
30+
31+
<service id="sylius.resource_metadata_collection.factory.php_file" class="Sylius\Resource\Metadata\Resource\Factory\PhpFileResourceMetadataCollectionFactory">
32+
<argument type="service" id="sylius.resource_registry" />
33+
<argument type="service" id="sylius.routing.factory.operation_route_name_factory" />
34+
<argument type="service" id="sylius_resource.metadata.extractor.php_file" />
35+
</service>
36+
2437
<service id="sylius.resource_metadata_collection.factory.attributes"
2538
class="Sylius\Resource\Metadata\Resource\Factory\AttributesResourceMetadataCollectionFactory"
39+
decorates="sylius.resource_metadata_collection.factory"
40+
decoration-priority="400"
2641
>
2742
<argument type="service" id="sylius.resource_registry" />
2843
<argument type="service" id="sylius.routing.factory.operation_route_name_factory" />
44+
<argument type="service" id=".inner" />
2945
</service>
30-
<service id="sylius.resource_metadata_collection.factory" alias="sylius.resource_metadata_collection.factory.attributes" />
31-
<service id="Sylius\Resource\Metadata\Resource\Factory\ResourceMetadataCollectionFactoryInterface" alias="sylius.resource_metadata_collection.factory.attributes" />
3246

3347
<service id="sylius.resource_metadata_collection.factory.state_machine"
3448
class="Sylius\Resource\Metadata\Resource\Factory\StateMachineResourceMetadataCollectionFactory"

src/Bundle/Resources/config/services/metadata/resource_name.xml

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,5 +22,15 @@
2222
<argument>%sylius.resource.mapping%</argument>
2323
</service>
2424
<service id="Sylius\Resource\Metadata\Resource\Factory\AttributesResourceNameCollectionFactory" alias="sylius_resource.metadata.resource.name_collection.factory.attributes" />
25+
26+
<service id="sylius_resource.metadata.resource.name_collection.factory.php_file"
27+
class="Sylius\Resource\Metadata\Resource\Factory\PhpFileResourceNameCollectionFactory"
28+
decorates="sylius_resource.metadata.resource.name_collection.factory"
29+
decoration-priority="100"
30+
>
31+
<argument type="service" id="sylius_resource.metadata.extractor.php_file" />
32+
<argument type="service" id=".inner" />
33+
</service>
34+
<service id="Sylius\Resource\Metadata\Resource\Factory\PhpFileResourceMetadataCollectionFactory" alias="sylius_resource.metadata.resource.name_collection.factory.php_file" />
2535
</services>
2636
</container>

src/Component/spec/Symfony/Routing/Factory/AttributesOperationRouteFactorySpec.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ function let(
4242
new AttributesResourceMetadataCollectionFactory(
4343
$resourceRegistry->getWrappedObject(),
4444
new OperationRouteNameFactory(),
45-
'symfony',
4645
),
4746
);
4847
}
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Sylius package.
5+
*
6+
* (c) Sylius Sp. z o.o.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Sylius\Resource\Metadata\Extractor;
15+
16+
use Sylius\Resource\Metadata\ResourceMetadata;
17+
18+
interface MetadataExtractorInterface
19+
{
20+
/**
21+
* @return ResourceMetadata[]
22+
*/
23+
public function extract(): array;
24+
}
Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Sylius package.
5+
*
6+
* (c) Sylius Sp. z o.o.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Sylius\Resource\Metadata\Extractor;
15+
16+
use Sylius\Resource\Metadata\ResourceMetadata;
17+
use Symfony\Component\Finder\Finder;
18+
19+
final class PhpFileMetadataExtractor implements MetadataExtractorInterface
20+
{
21+
public function __construct(
22+
private readonly array $resourceMapping,
23+
) {
24+
}
25+
26+
/**
27+
* @inheritDoc
28+
*/
29+
public function extract(): array
30+
{
31+
$metadata = [];
32+
33+
foreach ($this->getResourceFilePaths() as $filePath) {
34+
if (!is_readable($filePath)) {
35+
continue;
36+
}
37+
38+
$resource = $this->getPHPFileClosure($filePath)();
39+
40+
if (!$resource instanceof ResourceMetadata) {
41+
continue;
42+
}
43+
44+
$metadata[] = $resource;
45+
}
46+
47+
return $metadata;
48+
}
49+
50+
private function getResourceFilePaths(): iterable
51+
{
52+
foreach ($this->createFinder() as $file) {
53+
yield $file->getPathname();
54+
}
55+
}
56+
57+
private function createFinder(): Finder
58+
{
59+
$finder = (new Finder())->files();
60+
61+
foreach ($this->resourceMapping['imports'] ?? [] as $path) {
62+
$finder->in($path);
63+
}
64+
65+
return $finder->files();
66+
}
67+
68+
/**
69+
* Scope isolated include.
70+
*
71+
* Prevents access to $this/self from included files.
72+
*/
73+
private function getPHPFileClosure(string $filePath): \Closure
74+
{
75+
return \Closure::bind(function () use ($filePath): mixed {
76+
return require $filePath;
77+
}, null, null);
78+
}
79+
}

src/Component/src/Metadata/Resource/Factory/AttributesResourceMetadataCollectionFactory.php

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,16 @@ final class AttributesResourceMetadataCollectionFactory implements ResourceMetad
3030
public function __construct(
3131
private RegistryInterface $resourceRegistry,
3232
private OperationRouteNameFactory $operationRouteNameFactory,
33+
private ?ResourceMetadataCollectionFactoryInterface $decorated = null,
3334
) {
3435
}
3536

3637
public function create(string $resourceClass): ResourceMetadataCollection
3738
{
3839
$resourceMetadataCollection = new ResourceMetadataCollection();
40+
if ($this->decorated) {
41+
$resourceMetadataCollection = $this->decorated->create($resourceClass);
42+
}
3943

4044
$attributes = ClassReflection::getClassAttributes($resourceClass);
4145

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Sylius package.
5+
*
6+
* (c) Sylius Sp. z o.o.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Sylius\Resource\Metadata\Resource\Factory;
15+
16+
use Sylius\Resource\Metadata\Extractor\MetadataExtractorInterface;
17+
use Sylius\Resource\Metadata\Operation;
18+
use Sylius\Resource\Metadata\Operations;
19+
use Sylius\Resource\Metadata\RegistryInterface;
20+
use Sylius\Resource\Metadata\Resource\ResourceMetadataCollection;
21+
use Sylius\Resource\Symfony\Routing\Factory\RouteName\OperationRouteNameFactory;
22+
23+
final class PhpFileResourceMetadataCollectionFactory implements ResourceMetadataCollectionFactoryInterface
24+
{
25+
use OperationDefaultsTrait;
26+
27+
public function __construct(
28+
private readonly RegistryInterface $resourceRegistry,
29+
private readonly OperationRouteNameFactory $operationRouteNameFactory,
30+
private readonly MetadataExtractorInterface $metadataExtractor,
31+
private readonly ?ResourceMetadataCollectionFactoryInterface $decorated = null,
32+
) {
33+
}
34+
35+
public function create(string $resourceClass): ResourceMetadataCollection
36+
{
37+
$resourceMetadataCollection = new ResourceMetadataCollection();
38+
if ($this->decorated) {
39+
$resourceMetadataCollection = $this->decorated->create($resourceClass);
40+
}
41+
42+
foreach ($this->metadataExtractor->extract() as $resource) {
43+
if ($resourceClass !== $resource->getClass()) {
44+
continue;
45+
}
46+
47+
$resourceAlias = $resource->getAlias();
48+
49+
if (null !== $resourceAlias) {
50+
$resourceConfiguration = $this->resourceRegistry->get($resource->getAlias() ?? '');
51+
} else {
52+
$resourceConfiguration = $this->resourceRegistry->getByClass($resourceClass);
53+
}
54+
55+
$resource = $this->getResourceWithDefaults($resourceClass, $resource, $resourceConfiguration);
56+
57+
$operations = [];
58+
/** @var Operation $operation */
59+
foreach ($resource->getOperations() ?? new Operations() as $operation) {
60+
[$key, $operation] = $this->getOperationWithDefaults($this->operationRouteNameFactory, $this->resourceRegistry, $resource, $operation);
61+
$operations[$key] = $operation;
62+
}
63+
64+
if ($operations) {
65+
$resource = $resource->withOperations(new Operations($operations));
66+
}
67+
68+
$resourceMetadataCollection[] = $resource;
69+
}
70+
71+
return $resourceMetadataCollection;
72+
}
73+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
3+
/*
4+
* This file is part of the Sylius package.
5+
*
6+
* (c) Sylius Sp. z o.o.
7+
*
8+
* For the full copyright and license information, please view the LICENSE
9+
* file that was distributed with this source code.
10+
*/
11+
12+
declare(strict_types=1);
13+
14+
namespace Sylius\Resource\Metadata\Resource\Factory;
15+
16+
use Sylius\Resource\Metadata\Extractor\MetadataExtractorInterface;
17+
use Sylius\Resource\Metadata\Resource\ResourceNameCollection;
18+
19+
final class PhpFileResourceNameCollectionFactory implements ResourceNameCollectionFactoryInterface
20+
{
21+
use OperationDefaultsTrait;
22+
23+
public function __construct(
24+
private readonly MetadataExtractorInterface $metadataExtractor,
25+
private readonly ?ResourceNameCollectionFactoryInterface $decorated = null,
26+
) {
27+
}
28+
29+
public function create(): ResourceNameCollection
30+
{
31+
$classes = [];
32+
33+
if ($this->decorated) {
< 97F8 /td>34+
foreach ($this->decorated->create() as $resourceClass) {
35+
$classes[$resourceClass] = true;
36+
}
37+
}
38+
39+
foreach ($this->metadataExtractor->extract() as $resource) {
40+
$resourceClass = $resource->getClass();
41+
42+
if (null === $resourceClass) {
43+
continue;
44+
}
45+
46+
$classes[$resourceClass] = true;
47+
}
48+
49+
return new ResourceNameCollection(array_keys($classes));
50+
}
51+
}

0 commit comments

Comments
 (0)
0