Skip to content

Commit 761f841

Browse files
committed
feat: add CleanupRelations fields to OpenApi JSON
1 parent 6cb78d1 commit 761f841

File tree

4 files changed

+140
-1
lines changed

4 files changed

+140
-1
lines changed

src/ApiDefinition/EntitySchemaGeneratorDecorator.php

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ public function getSchema(array $definitions): array
5151

5252
$entityProperties = $schema[$entity]['properties'];
5353

54-
/** @var array<int, ManyToManyAssociationField|OneToManyAssociationField> $relevantFields */
5554
$relevantFields = $definition->getFields()
5655
->filter(fn(Field $field) => $this->isRelevantField($field));
5756

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,94 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Swh\SmartRelationSync\ApiDefinition;
6+
7+
use OpenApi\Annotations\Property;
8+
use OpenApi\Annotations\Schema;
9+
use Shopware\Core\Framework\Api\ApiDefinition\DefinitionService;
10+
use Shopware\Core\Framework\Api\ApiDefinition\Generator\OpenApi\OpenApiDefinitionSchemaBuilder;
11+
use Shopware\Core\Framework\Api\Context\AdminApiSource;
12+
use Shopware\Core\Framework\Api\Context\SalesChannelApiSource;
13+
use Shopware\Core\Framework\DataAbstractionLayer\EntityDefinition;
14+
use Shopware\Core\Framework\DataAbstractionLayer\Field\Field;
15+
use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\ApiAware;
16+
use Shopware\Core\Framework\DataAbstractionLayer\Field\Flag\IgnoreInOpenapiSchema;
17+
use Shopware\Core\Framework\DataAbstractionLayer\Field\ManyToManyAssociationField;
18+
use Shopware\Core\Framework\DataAbstractionLayer\Field\OneToManyAssociationField;
19+
use Swh\SmartRelationSync\DataAbstractionLayer\WriteCommandExtractorDecorator;
20+
21+
class OpenApiDefinitionSchemaBuilderDecorator extends OpenApiDefinitionSchemaBuilder
22+
{
23+
/**
24+
* @return Schema[]
25+
*/
26+
public function getSchemaByDefinition(
27+
EntityDefinition $definition,
28+
string $path,
29+
bool $forSalesChannel,
30+
bool $onlyFlat = false,
31+
string $apiType = DefinitionService::TYPE_JSON_API,
32+
): array {
33+
$schemas = parent::getSchemaByDefinition($definition, $path, $forSalesChannel, $onlyFlat, $apiType);
34+
35+
if (count($schemas) !== 1) {
36+
return $schemas;
37+
}
38+
39+
$relevantFields = $definition->getFields()
40+
->filter(fn(Field $field) => $this->isRelevantField($field));
41+
42+
$schema = current($schemas);
43+
44+
foreach ($relevantFields as $field) {
45+
if (!$this->shouldFieldBeIncluded($field, $forSalesChannel)) {
46+
continue;
47+
}
48+
49+
$enableFieldName = WriteCommandExtractorDecorator::getCleanupEnableFieldName($field);
50+
51+
$property = new Property([
52+
'property' => $enableFieldName,
53+
'type' => 'boolean',
54+
]);
55+
56+
$schema->properties[] = $property;
57+
}
58+
59+
return $schemas;
60+
}
61+
62+
/**
63+
* @phpstan-assert-if-true ManyToManyAssociationField|OneToManyAssociationField $field
64+
*/
65+
private function isRelevantField(Field $field): bool
66+
{
67+
return WriteCommandExtractorDecorator::isRelevantField($field);
68+
}
69+
70+
private function shouldFieldBeIncluded(Field $field, bool $forSalesChannel): bool
71+
{
72+
if ($field->getPropertyName() === 'translations'
73+
|| preg_match('#translations$#i', $field->getPropertyName())
74+
) {
75+
return false;
76+
}
77+
78+
$ignoreOpenApiSchemaFlag = $field->getFlag(IgnoreInOpenapiSchema::class);
79+
if ($ignoreOpenApiSchemaFlag !== null) {
80+
return false;
81+
}
82+
83+
$flag = $field->getFlag(ApiAware::class);
84+
if ($flag === null) {
85+
return false;
86+
}
87+
88+
if (!$flag->isSourceAllowed($forSalesChannel ? SalesChannelApiSource::class : AdminApiSource::class)) {
89+
return false;
90+
}
91+
92+
return true;
93+
}
94+
}

src/Resources/config/services.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,10 @@
33
declare(strict_types=1);
44

55
use Shopware\Core\Framework\Api\ApiDefinition\Generator\EntitySchemaGenerator;
6+
use Shopware\Core\Framework\Api\ApiDefinition\Generator\OpenApi\OpenApiDefinitionSchemaBuilder;
67
use Shopware\Core\Framework\DataAbstractionLayer\Write\WriteCommandExtractor;
78
use Swh\SmartRelationSync\ApiDefinition\EntitySchemaGeneratorDecorator;
9+
use Swh\SmartRelationSync\ApiDefinition\OpenApiDefinitionSchemaBuilderDecorator;
810
use Swh\SmartRelationSync\DataAbstractionLayer\CleanupRelationsRegistry;
911
use Swh\SmartRelationSync\DataAbstractionLayer\EntityWriteSubscriber;
1012
use Swh\SmartRelationSync\DataAbstractionLayer\ObsoleteRelationsDeleter;
@@ -34,4 +36,7 @@
3436
// Priority 10 is used to apply this decorator before the CachedEntitySchemaGenerator
3537
$services->set(EntitySchemaGeneratorDecorator::class)
3638
->decorate(EntitySchemaGenerator::class, priority: 10);
39+
40+
$services->set(OpenApiDefinitionSchemaBuilderDecorator::class)
41+
->decorate(OpenApiDefinitionSchemaBuilder::class);
3742
};
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace Swh\SmartRelationSync\Tests\Functional\ApiDefinition;
6+
7+
use PHPUnit\Framework\TestCase;
8+
use Shopware\Core\Framework\Test\TestCaseBase\AdminFunctionalTestBehaviour;
9+
use Symfony\Component\HttpFoundation\JsonResponse;
10+
11+
class OpenApiDefinitionSchemaBuilderDecoratorTest extends TestCase
12+
{
13+
use AdminFunctionalTestBehaviour;
14+
15+
public function testApiSchemaReturnsExpectedProperties(): void
16+
{
17+
$this->getBrowser()->jsonRequest(
18+
'GET',
19+
'/api/_info/openapi3.json?type=json',
20+
);
21+
22+
$response = $this->getBrowser()->getResponse();
23+
24+
self::assertInstanceOf(JsonResponse::class, $response);
25+
26+
$json = $response->getContent();
27+
28+
self::assertIsString($json);
29+
self::assertNotEmpty($json);
30+
31+
$json = json_decode($json, true);
32+
33+
self::assertIsArray($json);
34+
self::assertIsArray($json['components']);
35+
self::assertIsArray($json['components']['schemas']);
36+
self::assertIsArray($json['components']['schemas']['Product']);
37+
self::assertIsArray($json['components']['schemas']['Product']['properties']);
38+
self::assertIsArray($json['components']['schemas']['Product']['properties']['categoriesCleanupRelations']);
39+
self::assertSame('boolean', $json['components']['schemas']['Product']['properties']['categoriesCleanupRelations']['type']);
40+
}
41+
}

0 commit comments

Comments
 (0)