mirror of
https://github.com/Sylius/Sylius.git
synced 2026-07-05 20:57:12 +00:00
[API] Replace Swagger with OpenAPI
This commit is contained in:
parent
da94d80e76
commit
2554fd64f5
30 changed files with 827 additions and 1067 deletions
|
|
@ -41,5 +41,30 @@
|
|||
- `GET /admin/product-variant-translation/{id}` -> `GET /admin/product-variant-translations/{id}`
|
||||
- `GET /shop/product-variant-translation/{id}` -> `GET /shop/product-variant-translations/{id}`
|
||||
|
||||
2. Typo in the constraint validator's alias returned by `Sylius\Bundle\ApiBundle\Validator\Constraints\ChangedItemQuantityInCartValidator::validatedBy` has been fixed.
|
||||
Previously it was `sylius_api_validator_changed_item_guantity_in_cart` and now it is `sylius_api_validator_changed_item_quantity_in_cart`.
|
||||
1. Typo in the constraint validator's alias returned by `Sylius\Bundle\ApiBundle\Validator\Constraints\ChangedItemQuantityInCartValidator::validatedBy` has been fixed.
|
||||
Previously it was `sylius_api_validator_changed_item_guantity_in_cart` and now it is `sylius_api_validator_changed_item_quantity_in_cart`.
|
||||
|
||||
1. The `ApiPlatform\Core\Bridge\Symfony\Bundle\Action\SwaggerUiAction` controller has been removed.
|
||||
Therefore, the `api_platform.swagger.action.ui` service ID points to the API Platform's `SwaggerUiAction` controller.
|
||||
|
||||
1. The following services have been removed:
|
||||
* `Sylius\Bundle\ApiBundle\Swagger\AdminAuthenticationTokenDocumentationNormalizer`
|
||||
* `Sylius\Bundle\ApiBundle\Swagger\ShopAuthenticationTokenDocumentationNormalizer`
|
||||
* `Sylius\Bundle\ApiBundle\Swagger\ProductDocumentationNormalizer`
|
||||
* `Sylius\Bundle\ApiBundle\Swagger\ProductImageDocumentationNormalizer`
|
||||
* `Sylius\Bundle\ApiBundle\Swagger\ProductSlugDocumentationNormalizer`
|
||||
* `Sylius\Bundle\ApiBundle\Swagger\ProductVariantDocumentationNormalizer`
|
||||
* `Sylius\Bundle\ApiBundle\Swagger\ShippingMethodDocumentationNormalizer`
|
||||
* `Sylius\Bundle\ApiBundle\Swagger\PathHiderDocumentationNormalizer`
|
||||
* `Sylius\Bundle\ApiBundle\Swagger\AcceptLanguageHeaderDocumentationNormalizer`
|
||||
|
||||
Responsibility of these services has been moved to the corresponding services tagged with `sylius.open_api.modifier`:
|
||||
* `Sylius\Bundle\ApiBundle\OpenApi\Documentation\AdminAuthenticationTokenDocumentationModifier`
|
||||
* `Sylius\Bundle\ApiBundle\OpenApi\Documentation\ShopAuthenticationTokenDocumentationModifier`
|
||||
* `Sylius\Bundle\ApiBundle\OpenApi\Documentation\ProductDocumentationModifier`
|
||||
* `Sylius\Bundle\ApiBundle\OpenApi\Documentation\ProductImageDocumentationModifier`
|
||||
* `Sylius\Bundle\ApiBundle\OpenApi\Documentation\ProductSlugDocumentationModifier`
|
||||
* `Sylius\Bundle\ApiBundle\OpenApi\Documentation\ProductVariantDocumentationModifier`
|
||||
* `Sylius\Bundle\ApiBundle\OpenApi\Documentation\ShippingMethodDocumentationModifier`
|
||||
* `Sylius\Bundle\ApiBundle\OpenApi\Documentation\PathHiderDocumentationModifier`
|
||||
* `Sylius\Bundle\ApiBundle\OpenApi\Documentation\AcceptLanguageHeaderDocumentationModifier`
|
||||
|
|
|
|||
|
|
@ -280,81 +280,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/ApiPlatform/ApiResourceConfigurationMergerInterface.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\ApiPlatform\\\\Bridge\\\\Symfony\\\\Bundle\\\\Action\\\\SwaggerUiAction\\:\\:__construct\\(\\) has parameter \\$formats with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/ApiPlatform/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\ApiPlatform\\\\Bridge\\\\Symfony\\\\Bundle\\\\Action\\\\SwaggerUiAction\\:\\:__construct\\(\\) has parameter \\$oauthAuthorizationUrl with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/ApiPlatform/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\ApiPlatform\\\\Bridge\\\\Symfony\\\\Bundle\\\\Action\\\\SwaggerUiAction\\:\\:__construct\\(\\) has parameter \\$oauthClientId with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/ApiPlatform/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\ApiPlatform\\\\Bridge\\\\Symfony\\\\Bundle\\\\Action\\\\SwaggerUiAction\\:\\:__construct\\(\\) has parameter \\$oauthClientSecret with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/ApiPlatform/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\ApiPlatform\\\\Bridge\\\\Symfony\\\\Bundle\\\\Action\\\\SwaggerUiAction\\:\\:__construct\\(\\) has parameter \\$oauthEnabled with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/ApiPlatform/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\ApiPlatform\\\\Bridge\\\\Symfony\\\\Bundle\\\\Action\\\\SwaggerUiAction\\:\\:__construct\\(\\) has parameter \\$oauthFlow with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/ApiPlatform/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\ApiPlatform\\\\Bridge\\\\Symfony\\\\Bundle\\\\Action\\\\SwaggerUiAction\\:\\:__construct\\(\\) has parameter \\$oauthScopes with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/ApiPlatform/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\ApiPlatform\\\\Bridge\\\\Symfony\\\\Bundle\\\\Action\\\\SwaggerUiAction\\:\\:__construct\\(\\) has parameter \\$oauthTokenUrl with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/ApiPlatform/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\ApiPlatform\\\\Bridge\\\\Symfony\\\\Bundle\\\\Action\\\\SwaggerUiAction\\:\\:__construct\\(\\) has parameter \\$oauthType with no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/ApiPlatform/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\ApiPlatform\\\\Bridge\\\\Symfony\\\\Bundle\\\\Action\\\\SwaggerUiAction\\:\\:__invoke\\(\\) has no return type specified\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/ApiPlatform/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\ApiPlatform\\\\Bridge\\\\Symfony\\\\Bundle\\\\Action\\\\SwaggerUiAction\\:\\:getContext\\(\\) return type has no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/ApiPlatform/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\ApiPlatform\\\\Bridge\\\\Symfony\\\\Bundle\\\\Action\\\\SwaggerUiAction\\:\\:getPathAndMethod\\(\\) has parameter \\$swaggerData with no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/ApiPlatform/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\ApiPlatform\\\\Bridge\\\\Symfony\\\\Bundle\\\\Action\\\\SwaggerUiAction\\:\\:getPathAndMethod\\(\\) return type has no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/ApiPlatform/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php
|
||||
|
||||
-
|
||||
message: "#^Property Sylius\\\\Bundle\\\\ApiBundle\\\\ApiPlatform\\\\Bridge\\\\Symfony\\\\Bundle\\\\Action\\\\SwaggerUiAction\\:\\:\\$formats type has no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/ApiPlatform/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php
|
||||
|
||||
-
|
||||
message: "#^Property Sylius\\\\Bundle\\\\ApiBundle\\\\ApiPlatform\\\\Bridge\\\\Symfony\\\\Bundle\\\\Action\\\\SwaggerUiAction\\:\\:\\$formatsProvider has no type specified\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/ApiPlatform/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\ApiPlatform\\\\Bridge\\\\Symfony\\\\Routing\\\\RouteNameResolver\\:\\:isSameSubresource\\(\\) has parameter \\$context with no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
|
|
@ -1920,16 +1845,6 @@ parameters:
|
|||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/SerializerContextBuilder/LocaleContextBuilder.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Swagger\\\\AcceptLanguageHeaderDocumentationNormalizer\\:\\:__construct\\(\\) has parameter \\$localeRepository with generic interface Sylius\\\\Component\\\\Resource\\\\Repository\\\\RepositoryInterface but does not specify its types\\: T$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/Swagger/AcceptLanguageHeaderDocumentationNormalizer.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Swagger\\\\PathHiderDocumentationNormalizer\\:\\:__construct\\(\\) has parameter \\$apiRoutes with no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
path: src/Sylius/Bundle/ApiBundle/Swagger/PathHiderDocumentationNormalizer.php
|
||||
|
||||
-
|
||||
message: "#^Method Sylius\\\\Bundle\\\\ApiBundle\\\\Validator\\\\CatalogPromotion\\\\FixedDiscountActionValidator\\:\\:isChannelAmountValid\\(\\) has parameter \\$channelConfiguration with no value type specified in iterable type array\\.$#"
|
||||
count: 1
|
||||
|
|
|
|||
|
|
@ -12,7 +12,6 @@
|
|||
<directory name="src" />
|
||||
<ignoreFiles>
|
||||
<file name="src/Sylius/Bundle/CoreBundle/Application/Kernel.php" />
|
||||
<file name="src/Sylius/Bundle/ApiBundle/ApiPlatform/Bridge/Symfony/Bundle/Action/SwaggerUiAction.php" />
|
||||
|
||||
<directory name="src/Sylius/Behat" />
|
||||
|
||||
|
|
|
|||
|
|
@ -1,173 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\ApiPlatform\Bridge\Symfony\Bundle\Action;
|
||||
|
||||
use ApiPlatform\Core\Api\FormatsProviderInterface;
|
||||
use ApiPlatform\Core\Documentation\Documentation;
|
||||
use ApiPlatform\Core\Exception\RuntimeException;
|
||||
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceMetadataFactoryInterface;
|
||||
use ApiPlatform\Core\Metadata\Resource\Factory\ResourceNameCollectionFactoryInterface;
|
||||
use ApiPlatform\Core\Util\RequestAttributesExtractor;
|
||||
use Symfony\Component\HttpFoundation\Request;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
use Twig\Environment as TwigEnvironment;
|
||||
|
||||
/**
|
||||
* Displays the documentation.
|
||||
*
|
||||
* @internal
|
||||
*
|
||||
* This class will be probably removed in Sylius 1.9
|
||||
*/
|
||||
final class SwaggerUiAction
|
||||
{
|
||||
private ?array $formats;
|
||||
|
||||
private $formatsProvider;
|
||||
|
||||
/**
|
||||
* @param int[] $swaggerVersions
|
||||
*/
|
||||
public function __construct(
|
||||
private ResourceNameCollectionFactoryInterface $resourceNameCollectionFactory,
|
||||
private ResourceMetadataFactoryInterface $resourceMetadataFactory,
|
||||
private NormalizerInterface $normalizer,
|
||||
private TwigEnvironment $twig,
|
||||
private UrlGeneratorInterface $urlGenerator,
|
||||
private string $title = '',
|
||||
private string $description = '',
|
||||
private string $version = '',
|
||||
$formats = [],
|
||||
private $oauthEnabled = false,
|
||||
private $oauthClientId = '',
|
||||
private $oauthClientSecret = '',
|
||||
private $oauthType = '',
|
||||
private $oauthFlow = '',
|
||||
private $oauthTokenUrl = '',
|
||||
private $oauthAuthorizationUrl = '',
|
||||
private $oauthScopes = [],
|
||||
private bool $showWebby = true,
|
||||
private bool $swaggerUiEnabled = false,
|
||||
private bool $reDocEnabled = false,
|
||||
private bool $graphqlEnabled = false,
|
||||
private bool $graphiQlEnabled = false,
|
||||
private bool $graphQlPlaygroundEnabled = false,
|
||||
private array $swaggerVersions = [2, 3],
|
||||
) {
|
||||
if (\is_array($formats)) {
|
||||
$this->formats = $formats;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@trigger_error(sprintf(
|
||||
'Passing an array or an instance of "%s" as 5th parameter of the constructor of "%s" is deprecated since API Platform 2.5, pass an array instead',
|
||||
FormatsProviderInterface::class,
|
||||
__CLASS__,
|
||||
), \E_USER_DEPRECATED);
|
||||
$this->formatsProvider = $formats;
|
||||
}
|
||||
|
||||
public function __invoke(Request $request)
|
||||
{
|
||||
$attributes = RequestAttributesExtractor::extractAttributes($request);
|
||||
|
||||
// BC check to be removed in 3.0
|
||||
if (null === $this->formatsProvider) {
|
||||
$formats = $attributes ? $this
|
||||
->resourceMetadataFactory
|
||||
->create($attributes['resource_class'])
|
||||
->getOperationAttribute($attributes, 'output_formats', [], true) : $this->formats;
|
||||
} else {
|
||||
$formats = $this->formatsProvider->getFormatsFromAttributes($attributes);
|
||||
}
|
||||
|
||||
$documentation = new Documentation($this->resourceNameCollectionFactory->create(), $this->title, $this->description, $this->version);
|
||||
|
||||
return new Response($this->twig->render('@SyliusApi/SwaggerUi/index.html.twig', $this->getContext($request, $documentation) + ['formats' => $formats]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the base Twig context.
|
||||
*/
|
||||
private function getContext(Request $request, Documentation $documentation): array
|
||||
{
|
||||
$context = [
|
||||
'title' => $this->title,
|
||||
'description' => $this->description,
|
||||
'showWebby' => $this->showWebby,
|
||||
'swaggerUiEnabled' => $this->swaggerUiEnabled,
|
||||
'reDocEnabled' => $this->reDocEnabled,
|
||||
'graphqlEnabled' => $this->graphqlEnabled,
|
||||
'graphiQlEnabled' => $this->graphiQlEnabled,
|
||||
'graphQlPlaygroundEnabled' => $this->graphQlPlaygroundEnabled,
|
||||
];
|
||||
|
||||
$swaggerContext = ['spec_version' => $request->query->getInt('spec_version', $this->swaggerVersions[0] ?? 2)];
|
||||
if ('' !== $baseUrl = $request->getBaseUrl()) {
|
||||
$swaggerContext['base_url'] = $baseUrl;
|
||||
}
|
||||
|
||||
$swaggerData = [
|
||||
'url' => $this->urlGenerator->generate('api_doc', ['format' => 'json']),
|
||||
'spec' => $this->normalizer->normalize($documentation, 'json', $swaggerContext),
|
||||
];
|
||||
|
||||
$swaggerData['oauth'] = [
|
||||
'enabled' => $this->oauthEnabled,
|
||||
'clientId' => $this->oauthClientId,
|
||||
'clientSecret' => $this->oauthClientSecret,
|
||||
'type' => $this->oauthType,
|
||||
'flow' => $this->oauthFlow,
|
||||
'tokenUrl' => $this->oauthTokenUrl,
|
||||
'authorizationUrl' => $this->oauthAuthorizationUrl,
|
||||
'scopes' => $this->oauthScopes,
|
||||
];
|
||||
|
||||
if ($request->isMethodSafe() && null !== $resourceClass = $request->attributes->get('_api_resource_class')) {
|
||||
$swaggerData['id'] = $request->attributes->get('id');
|
||||
$swaggerData['queryParameters'] = $request->query->all();
|
||||
|
||||
$metadata = $this->resourceMetadataFactory->create($resourceClass);
|
||||
$swaggerData['shortName'] = $metadata->getShortName();
|
||||
|
||||
if (null !== $collectionOperationName = $request->attributes->get('_api_collection_operation_name')) {
|
||||
$swaggerData['operationId'] = sprintf('%s%sCollection', $collectionOperationName, ucfirst($swaggerData['shortName']));
|
||||
} elseif (null !== $itemOperationName = $request->attributes->get('_api_item_operation_name')) {
|
||||
$swaggerData['operationId'] = sprintf('%s%sItem', $itemOperationName, ucfirst($swaggerData['shortName']));
|
||||
} elseif (null !== $subresourceOperationContext = $request->attributes->get('_api_subresource_context')) {
|
||||
$swaggerData['operationId'] = $subresourceOperationContext['operationId'];
|
||||
}
|
||||
|
||||
[$swaggerData['path'], $swaggerData['method']] = $this->getPathAndMethod($swaggerData);
|
||||
}
|
||||
|
||||
return $context + ['swagger_data' => $swaggerData];
|
||||
}
|
||||
|
||||
private function getPathAndMethod(array $swaggerData): array
|
||||
{
|
||||
foreach ($swaggerData['spec']['paths'] as $path => $operations) {
|
||||
foreach ($operations as $method => $operation) {
|
||||
if ($operation['operationId'] === $swaggerData['operationId']) {
|
||||
return [$path, $method];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new RuntimeException(sprintf('The operation "%s" cannot be found in the Swagger specification.', $swaggerData['operationId']));
|
||||
}
|
||||
}
|
||||
|
|
@ -37,7 +37,10 @@ final class SyliusApiExtension extends Extension implements PrependExtensionInte
|
|||
|
||||
$loader->load('services.xml');
|
||||
|
||||
if ($container->hasParameter('api_platform.enable_swagger_ui') && $container->getParameter('api_platform.enable_swagger_ui')) {
|
||||
// If parameter is not set, it means that Swagger is not enabled (api_platform.enable_swagger set to false)
|
||||
$swaggerEnabled = $container->hasParameter('api_platform.swagger.api_keys');
|
||||
|
||||
if ($swaggerEnabled) {
|
||||
$loader->load('integrations/swagger.xml');
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,73 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\OpenApi\Documentation;
|
||||
|
||||
use ApiPlatform\Core\OpenApi\Model\Parameter;
|
||||
use ApiPlatform\OpenApi\Model\PathItem;
|
||||
use ApiPlatform\OpenApi\OpenApi;
|
||||
use Sylius\Component\Locale\Model\LocaleInterface;
|
||||
use Sylius\Component\Resource\Repository\RepositoryInterface;
|
||||
|
||||
/** @experimental */
|
||||
final class AcceptLanguageHeaderDocumentationModifier implements DocumentationModifierInterface
|
||||
{
|
||||
/**
|
||||
* @param RepositoryInterface<LocaleInterface> $localeRepository
|
||||
*/
|
||||
public function __construct(private RepositoryInterface $localeRepository)
|
||||
{
|
||||
}
|
||||
|
||||
public function modify(OpenApi $docs): OpenApi
|
||||
{
|
||||
$acceptLanguageHeaderParameter = new Parameter(
|
||||
name: 'Accept-Language',
|
||||
in: 'header',
|
||||
description: 'Locales in this enum are all locales defined in the shop and only enabled ones will work in the given channel in the shop.',
|
||||
required: false,
|
||||
schema: [
|
||||
'type' => 'string',
|
||||
'enum' => array_map(
|
||||
fn (LocaleInterface $locale): string => $locale->getCode(),
|
||||
$this->localeRepository->findAll(),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
$pathItems = [];
|
||||
|
||||
/** @var PathItem $pathItem */
|
||||
foreach ($docs->getPaths()->getPaths() as $path => $pathItem) {
|
||||
foreach (PathItem::$methods as $method) {
|
||||
$operation = $pathItem->{'get' . ucfirst($method)}();
|
||||
|
||||
if (null === $operation) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$parameters = $operation->getParameters();
|
||||
$parameters[] = $acceptLanguageHeaderParameter;
|
||||
|
||||
$operation = $operation->withParameters($parameters);
|
||||
$pathItems[$path] = $pathItem->{'with' . ucfirst($method)}($operation);
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($pathItems as $path => $pathItem) {
|
||||
$docs->getPaths()->addPath($path, $pathItem);
|
||||
}
|
||||
|
||||
return $docs;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\OpenApi\Documentation;
|
||||
|
||||
use ApiPlatform\OpenApi\Model\Operation;
|
||||
use ApiPlatform\OpenApi\Model\PathItem;
|
||||
use ApiPlatform\OpenApi\Model\RequestBody;
|
||||
use ApiPlatform\OpenApi\OpenApi;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/** @experimental */
|
||||
final class AdminAuthenticationTokenDocumentationModifier implements DocumentationModifierInterface
|
||||
{
|
||||
public function __construct(private string $apiRoute)
|
||||
{
|
||||
}
|
||||
|
||||
public function modify(OpenApi $docs): OpenApi
|
||||
{
|
||||
$components = $docs->getComponents();
|
||||
$schemas = $components->getSchemas();
|
||||
|
||||
$schemas['AdminUserToken'] = [
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'token' => [
|
||||
'type' => 'string',
|
||||
'readOnly' => true,
|
||||
],
|
||||
'adminUser' => [
|
||||
'type' => 'string',
|
||||
'readOnly' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$schemas['AdminUserCredentials'] = [
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'email' => [
|
||||
'type' => 'string',
|
||||
'example' => 'api@example.com',
|
||||
],
|
||||
'password' => [
|
||||
'type' => 'string',
|
||||
'example' => 'sylius-api',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$components = $components->withSchemas($schemas);
|
||||
$docs = $docs->withComponents($components);
|
||||
|
||||
$docs->getPaths()->addPath(
|
||||
$this->apiRoute . '/admin/authentication-token',
|
||||
new PathItem(
|
||||
post: new Operation(
|
||||
operationId: 'postCredentialsItem',
|
||||
tags: ['AdminUserToken'],
|
||||
responses: [
|
||||
Response::HTTP_OK => [
|
||||
'description' => 'Get JWT token',
|
||||
'content' => [
|
||||
'application/json' => [
|
||||
'schema' => [
|
||||
'$ref' => '#/components/schemas/AdminUserToken',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
summary: 'Get JWT token to login.',
|
||||
requestBody: new RequestBody(
|
||||
description: 'Create new JWT Token',
|
||||
content: new \ArrayObject([
|
||||
'application/json' => [
|
||||
'schema' => [
|
||||
'$ref' => '#/components/schemas/AdminUserCredentials',
|
||||
],
|
||||
],
|
||||
]),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $docs;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\OpenApi\Documentation;
|
||||
|
||||
use ApiPlatform\OpenApi\OpenApi;
|
||||
|
||||
/** @experimental */
|
||||
interface DocumentationModifierInterface
|
||||
{
|
||||
public function modify(OpenApi $docs): OpenApi;
|
||||
}
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\OpenApi\Documentation;
|
||||
|
||||
use ApiPlatform\OpenApi\Model\PathItem;
|
||||
use ApiPlatform\OpenApi\Model\Paths;
|
||||
use ApiPlatform\OpenApi\OpenApi;
|
||||
|
||||
/** @experimental */
|
||||
final class PathHiderDocumentationModifier implements DocumentationModifierInterface
|
||||
{
|
||||
/**
|
||||
* @param string[] $apiRoutes
|
||||
*/
|
||||
public function __construct(private array $apiRoutes)
|
||||
{
|
||||
}
|
||||
|
||||
public function modify(OpenApi $docs): OpenApi
|
||||
{
|
||||
/** @var array<string, PathItem> $pathItems */
|
||||
$pathItems = $docs->getPaths()->getPaths();
|
||||
|
||||
foreach ($this->apiRoutes as $apiRoute) {
|
||||
if (array_key_exists($apiRoute, $pathItems)) {
|
||||
unset($pathItems[$apiRoute]);
|
||||
}
|
||||
}
|
||||
|
||||
$paths = new Paths();
|
||||
|
||||
foreach ($pathItems as $path => $pathItem) {
|
||||
$paths->addPath($path, $pathItem);
|
||||
}
|
||||
|
||||
return $docs->withPaths($paths);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\OpenApi\Documentation;
|
||||
|
||||
use ApiPlatform\OpenApi\Model\PathItem;
|
||||
use ApiPlatform\OpenApi\Model\Paths;
|
||||
use ApiPlatform\OpenApi\OpenApi;
|
||||
|
||||
/** @experimental */
|
||||
final class ProductDocumentationModifier implements DocumentationModifierInterface
|
||||
{
|
||||
public function modify(OpenApi $docs): OpenApi
|
||||
{
|
||||
$components = $docs->getComponents();
|
||||
$schemas = $components->getSchemas();
|
||||
|
||||
$schemas['Product.jsonld-shop.product.read']['properties']['defaultVariant'] = [
|
||||
'type' => 'string',
|
||||
'format' => 'iri-reference',
|
||||
'nullable' => true,
|
||||
'readOnly' => true,
|
||||
];
|
||||
|
||||
return $docs->withComponents(
|
||||
$components->withSchemas($schemas)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,55 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\OpenApi\Documentation;
|
||||
|
||||
use ApiPlatform\OpenApi\Model\Parameter;
|
||||
use ApiPlatform\OpenApi\OpenApi;
|
||||
use Sylius\Bundle\ApiBundle\Provider\ProductImageFilterProviderInterface;
|
||||
|
||||
/** @experimental */
|
||||
final class ProductImageDocumentationModifier implements DocumentationModifierInterface
|
||||
{
|
||||
public function __construct(
|
||||
private ProductImageFilterProviderInterface $filterProvider,
|
||||
private string $apiRoute,
|
||||
) {
|
||||
}
|
||||
|
||||
public function modify(OpenApi $docs): OpenApi
|
||||
{
|
||||
$enums = array_keys($this->filterProvider->provideShopFilters());
|
||||
|
||||
$path = sprintf('%s/shop/product-images/{id}', $this->apiRoute);
|
||||
|
||||
$paths = $docs->getPaths();
|
||||
$pathItem = $paths->getPath($path);
|
||||
$operation = $pathItem->getGet();
|
||||
/** @var Parameter[] $parameters */
|
||||
$parameters = $operation->getParameters();
|
||||
|
||||
foreach ($parameters as &$parameter) {
|
||||
if ($parameter->getIn() === 'query' && $parameter->getName() === 'filter') {
|
||||
$schema = $parameter->getSchema();
|
||||
$schema['enum'] = $enums;
|
||||
$parameter = $parameter->withSchema($schema);
|
||||
}
|
||||
}
|
||||
|
||||
$operation = $operation->withParameters($parameters);
|
||||
$pathItem = $pathItem->withGet($operation);
|
||||
$paths->addPath($path, $pathItem);
|
||||
|
||||
return $docs;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\OpenApi\Documentation;
|
||||
|
||||
use ApiPlatform\OpenApi\Model\Parameter;
|
||||
use ApiPlatform\OpenApi\OpenApi;
|
||||
use Sylius\Bundle\ApiBundle\Provider\ProductImageFilterProviderInterface;
|
||||
|
||||
/** @experimental */
|
||||
final class ProductSlugDocumentationModifier implements DocumentationModifierInterface
|
||||
{
|
||||
public function __construct(private string $apiRoute)
|
||||
{
|
||||
}
|
||||
|
||||
public function modify(OpenApi $docs): OpenApi
|
||||
{
|
||||
$path = sprintf('%s/shop/products-by-slug/{slug}', $this->apiRoute);
|
||||
|
||||
$paths = $docs->getPaths();
|
||||
$pathItem = $paths->getPath($path);
|
||||
$operation = $pathItem->getGet();
|
||||
/** @var Parameter[] $parameters */
|
||||
$parameters = $operation->getParameters();
|
||||
|
||||
foreach ($parameters as $key => $parameter) {
|
||||
if ($parameter->getName() === 'code') {
|
||||
unset($parameters[$key]);
|
||||
}
|
||||
}
|
||||
|
||||
$operation = $operation->withParameters(array_values($parameters));
|
||||
$pathItem = $pathItem->withGet($operation);
|
||||
$paths->addPath($path, $pathItem);
|
||||
|
||||
return $docs;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,49 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\OpenApi\Documentation;
|
||||
|
||||
use ApiPlatform\OpenApi\Model\PathItem;
|
||||
use ApiPlatform\OpenApi\Model\Paths;
|
||||
use ApiPlatform\OpenApi\OpenApi;
|
||||
|
||||
/** @experimental */
|
||||
final class ProductVariantDocumentationModifier implements DocumentationModifierInterface
|
||||
{
|
||||
public function modify(OpenApi $docs): OpenApi
|
||||
{
|
||||
$components = $docs->getComponents();
|
||||
$schemas = $components->getSchemas();
|
||||
|
||||
$schemas['ProductVariant.jsonld-shop.product_variant.read']['properties']['price'] = [
|
||||
'type' => 'integer',
|
||||
'readOnly' => true,
|
||||
'default' => 0,
|
||||
];
|
||||
|
||||
$schemas['ProductVariant.jsonld-shop.product_variant.read']['properties']['inStock'] = [
|
||||
'type' => 'boolean',
|
||||
'readOnly' => true,
|
||||
];
|
||||
|
||||
$schemas['ProductVariant.jsonld-shop.product_variant.read']['properties']['originalPrice'] = [
|
||||
'type' => 'integer',
|
||||
'readOnly' => true,
|
||||
'default' => 0,
|
||||
];
|
||||
|
||||
return $docs->withComponents(
|
||||
$components->withSchemas($schemas)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\OpenApi\Documentation;
|
||||
|
||||
use ApiPlatform\OpenApi\Model\PathItem;
|
||||
use ApiPlatform\OpenApi\Model\Paths;
|
||||
use ApiPlatform\OpenApi\OpenApi;
|
||||
|
||||
/** @experimental */
|
||||
final class ShippingMethodDocumentationModifier implements DocumentationModifierInterface
|
||||
{
|
||||
public function modify(OpenApi $docs): OpenApi
|
||||
{
|
||||
$components = $docs->getComponents();
|
||||
$schemas = $components->getSchemas();
|
||||
|
||||
$schemas['ShippingMethod.jsonld-shop.shipping_method.read']['properties']['price'] = [
|
||||
'type' => 'integer',
|
||||
'readOnly' => true,
|
||||
'default' => 0,
|
||||
];
|
||||
|
||||
return $docs->withComponents(
|
||||
$components->withSchemas($schemas)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,91 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\OpenApi\Documentation;
|
||||
|
||||
use ApiPlatform\OpenApi\Model\Operation;
|
||||
use ApiPlatform\OpenApi\Model\PathItem;
|
||||
use ApiPlatform\OpenApi\Model\RequestBody;
|
||||
use ApiPlatform\OpenApi\OpenApi;
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
|
||||
/** @experimental */
|
||||
final class ShopAuthenticationTokenDocumentationModifier implements DocumentationModifierInterface
|
||||
{
|
||||
public function __construct(private string $apiRoute)
|
||||
{
|
||||
}
|
||||
|
||||
public function modify(OpenApi $docs): OpenApi
|
||||
{
|
||||
$components = $docs->getComponents();
|
||||
$schemas = $components->getSchemas();
|
||||
|
||||
$schemas['ShopUserToken'] = [
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'token' => [
|
||||
'type' => 'string',
|
||||
'readOnly' => true,
|
||||
],
|
||||
'customer' => [
|
||||
'type' => 'string',
|
||||
'readOnly' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$schemas['ShopUserCredentials'] = [
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'email' => [
|
||||
'type' => 'string',
|
||||
'example' => 'shop@example.com',
|
||||
],
|
||||
'password' => [
|
||||
'type' => 'string',
|
||||
'example' => 'sylius',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$components = $components->withSchemas($schemas);
|
||||
$docs = $docs->withComponents($components);
|
||||
|
||||
$docs->getPaths()->addPath(
|
||||
$this->apiRoute . '/shop/authentication-token',
|
||||
new PathItem(
|
||||
post: new Operation(
|
||||
operationId: 'postCredentialsItem',
|
||||
tags: ['ShopUserToken'],
|
||||
responses: [
|
||||
Response::HTTP_OK => [
|
||||
'description' => 'Get JWT token',
|
||||
'content' => [
|
||||
'application/json' => [
|
||||
'schema' => [
|
||||
'$ref' => '#/components/schemas/ShopUserToken',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
summary: 'Get JWT token to login.',
|
||||
requestBody: new RequestBody(
|
||||
description: 'Create new JWT Token',
|
||||
content: new \ArrayObject([
|
||||
'application/json' => [
|
||||
'schema' => [
|
||||
'$ref' => '#/components/schemas/ShopUserCredentials',
|
||||
],
|
||||
],
|
||||
]),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return $docs;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\OpenApi\Factory;
|
||||
|
||||
use ApiPlatform\OpenApi\Factory\OpenApiFactoryInterface;
|
||||
use ApiPlatform\OpenApi\OpenApi;
|
||||
use Sylius\Bundle\ApiBundle\OpenApi\Documentation\DocumentationModifierInterface;
|
||||
use Webmozart\Assert\Assert;
|
||||
|
||||
/** @experimental */
|
||||
final class OpenApiFactory implements OpenApiFactoryInterface
|
||||
{
|
||||
public function __construct(
|
||||
private OpenApiFactoryInterface $decorated,
|
||||
/** @var iterable<DocumentationModifierInterface> */
|
||||
private iterable $openApiModifiers,
|
||||
) {
|
||||
Assert::allIsInstanceOf($openApiModifiers, DocumentationModifierInterface::class);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<string, mixed> $context
|
||||
*/
|
||||
public function __invoke(array $context = []): OpenApi
|
||||
{
|
||||
$openApi = ($this->decorated)($context);
|
||||
|
||||
foreach ($this->openApiModifiers as $openApiModifier) {
|
||||
$openApi = $openApiModifier->modify($openApi);
|
||||
}
|
||||
|
||||
return $openApi;
|
||||
}
|
||||
}
|
||||
|
|
@ -16,121 +16,54 @@
|
|||
xsi:schemaLocation="http://symfony.com/schema/dic/services http://symfony.com/schema/dic/services/services-1.0.xsd"
|
||||
>
|
||||
<services>
|
||||
<defaults public="true" />
|
||||
<defaults public="false" />
|
||||
|
||||
<service id="api_platform.swagger.action.ui" class="Sylius\Bundle\ApiBundle\ApiPlatform\Bridge\Symfony\Bundle\Action\SwaggerUiAction">
|
||||
<argument type="service" id="api_platform.metadata.resource.name_collection_factory" />
|
||||
<argument type="service" id="api_platform.metadata.resource.metadata_factory" />
|
||||
<argument type="service" id="api_platform.serializer" />
|
||||
<argument type="service" id="twig" />
|
||||
<argument type="service" id="router" />
|
||||
<argument>%api_platform.title%</argument>
|
||||
<argument>%api_platform.description%</argument>
|
||||
<argument>%api_platform.version%</argument>
|
||||
<argument>%api_platform.formats%</argument>
|
||||
<argument>%api_platform.oauth.enabled%</argument>
|
||||
<argument>%api_platform.oauth.clientId%</argument>
|
||||
<argument>%api_platform.oauth.clientSecret%</argument>
|
||||
<argument>%api_platform.oauth.type%</argument>
|
||||
<argument>%api_platform.oauth.flow%</argument>
|
||||
<argument>%api_platform.oauth.tokenUrl%</argument>
|
||||
<argument>%api_platform.oauth.authorizationUrl%</argument>
|
||||
<argument>%api_platform.oauth.scopes%</argument>
|
||||
<argument>%api_platform.show_webby%</argument>
|
||||
<argument>%api_platform.enable_swagger_ui%</argument>
|
||||
<argument>%api_platform.enable_re_doc%</argument>
|
||||
<argument>%api_platform.graphql.enabled%</argument>
|
||||
<argument>%api_platform.graphql.graphiql.enabled%</argument>
|
||||
<argument>%api_platform.graphql.graphql_playground.enabled%</argument>
|
||||
<argument>%api_platform.swagger.versions%</argument>
|
||||
<service id="Sylius\Bundle\ApiBundle\OpenApi\Factory\OpenApiFactory" decorates="api_platform.openapi.factory">
|
||||
<argument type="service" id="Sylius\Bundle\ApiBundle\OpenApi\Factory\OpenApiFactory.inner" />
|
||||
<argument type="tagged_iterator" tag="sylius.open_api.modifier" />
|
||||
</service>
|
||||
|
||||
<service
|
||||
id="Sylius\Bundle\ApiBundle\Swagger\AdminAuthenticationTokenDocumentationNormalizer"
|
||||
decorates="api_platform.swagger.normalizer.documentation"
|
||||
autoconfigure="false"
|
||||
decoration-priority="20"
|
||||
>
|
||||
<argument type="service" id="Sylius\Bundle\ApiBundle\Swagger\AdminAuthenticationTokenDocumentationNormalizer.inner" />
|
||||
<service id="Sylius\Bundle\ApiBundle\OpenApi\Documentation\AcceptLanguageHeaderDocumentationModifier">
|
||||
<argument type="service" id="sylius.repository.locale" />
|
||||
<tag name="sylius.open_api.modifier" />
|
||||
</service>
|
||||
|
||||
<service id="Sylius\Bundle\ApiBundle\OpenApi\Documentation\AdminAuthenticationTokenDocumentationModifier">
|
||||
<argument>%sylius.security.new_api_route%</argument>
|
||||
<tag name="sylius.open_api.modifier" />
|
||||
</service>
|
||||
|
||||
<service
|
||||
id="Sylius\Bundle\ApiBundle\Swagger\ShopAuthenticationTokenDocumentationNormalizer"
|
||||
decorates="api_platform.swagger.normalizer.documentation"
|
||||
autoconfigure="false"
|
||||
decoration-priority="10"
|
||||
>
|
||||
<argument type="service" id="Sylius\Bundle\ApiBundle\Swagger\ShopAuthenticationTokenDocumentationNormalizer.inner" />
|
||||
<argument>%sylius.security.new_api_route%</argument>
|
||||
<service id="Sylius\Bundle\ApiBundle\OpenApi\Documentation\PathHiderDocumentationModifier">
|
||||
<argument>%sylius.api.paths_to_hide%</argument>
|
||||
<tag name="sylius.open_api.modifier" />
|
||||
</service>
|
||||
|
||||
<service
|
||||
id="Sylius\Bundle\ApiBundle\Swagger\ProductDocumentationNormalizer"
|
||||
decorates="api_platform.swagger.normalizer.documentation"
|
||||
autoconfigure="false"
|
||||
decoration-priority="20"
|
||||
>
|
||||
<argument type="service" id="Sylius\Bundle\ApiBundle\Swagger\ProductDocumentationNormalizer.inner" />
|
||||
<service id="Sylius\Bundle\ApiBundle\OpenApi\Documentation\ProductDocumentationModifier">
|
||||
<tag name="sylius.open_api.modifier" />
|
||||
</service>
|
||||
|
||||
<service
|
||||
id="Sylius\Bundle\ApiBundle\Swagger\ProductImageDocumentationNormalizer"
|
||||
decorates="api_platform.swagger.normalizer.documentation"
|
||||
autoconfigure="false"
|
||||
decoration-priority="20"
|
||||
>
|
||||
<argument type="service" id="Sylius\Bundle\ApiBundle\Swagger\ProductImageDocumentationNormalizer.inner" />
|
||||
<service id="Sylius\Bundle\ApiBundle\OpenApi\Documentation\ProductImageDocumentationModifier">
|
||||
<argument type="service" id="Sylius\Bundle\ApiBundle\Provider\ProductImageFilterProviderInterface" />
|
||||
<argument>%sylius.security.new_api_route%</argument>
|
||||
<tag name="sylius.open_api.modifier" />
|
||||
</service>
|
||||
|
||||
<service
|
||||
id="Sylius\Bundle\ApiBundle\Swagger\ProductSlugDocumentationNormalizer"
|
||||
decorates="api_platform.swagger.normalizer.documentation"
|
||||
autoconfigure="false"
|
||||
decoration-priority="20"
|
||||
>
|
||||
<argument type="service" id="Sylius\Bundle\ApiBundle\Swagger\ProductSlugDocumentationNormalizer.inner" />
|
||||
<service id="Sylius\Bundle\ApiBundle\OpenApi\Documentation\ProductSlugDocumentationModifier">
|
||||
<argument>%sylius.security.new_api_route%</argument>
|
||||
<tag name="sylius.open_api.modifier" />
|
||||
</service>
|
||||
|
||||
<service
|
||||
id="Sylius\Bundle\ApiBundle\Swagger\ProductVariantDocumentationNormalizer"
|
||||
decorates="api_platform.swagger.normalizer.documentation"
|
||||
autoconfigure="false"
|
||||
decoration-priority="20"
|
||||
>
|
||||
<argument type="service" id="Sylius\Bundle\ApiBundle\Swagger\ProductVariantDocumentationNormalizer.inner" />
|
||||
<service id="Sylius\Bundle\ApiBundle\OpenApi\Documentation\ProductVariantDocumentationModifier">
|
||||
<tag name="sylius.open_api.modifier" />
|
||||
</service>
|
||||
|
||||
<service
|
||||
id="Sylius\Bundle\ApiBundle\Swagger\ShippingMethodDocumentationNormalizer"
|
||||
decorates="api_platform.swagger.normalizer.documentation"
|
||||
autoconfigure="false"
|
||||
decoration-priority="20"
|
||||
>
|
||||
<argument type="service" id="Sylius\Bundle\ApiBundle\Swagger\ShippingMethodDocumentationNormalizer.inner" />
|
||||
<service id="Sylius\Bundle\ApiBundle\OpenApi\Documentation\ShippingMethodDocumentationModifier">
|
||||
<tag name="sylius.open_api.modifier" />
|
||||
</service>
|
||||
|
||||
<service
|
||||
id="Sylius\Bundle\ApiBundle\Swagger\PathHiderDocumentationNormalizer"
|
||||
decorates="api_platform.swagger.normalizer.documentation"
|
||||
autoconfigure="false"
|
||||
decoration-priority="20"
|
||||
>
|
||||
<argument type="service" id="Sylius\Bundle\ApiBundle\Swagger\PathHiderDocumentationNormalizer.inner" />
|
||||
<argument>%sylius.api.paths_to_hide%</argument>
|
||||
</service>
|
||||
|
||||
<service
|
||||
id="Sylius\Bundle\ApiBundle\Swagger\AcceptLanguageHeaderDocumentationNormalizer"
|
||||
decorates="api_platform.swagger.normalizer.documentation"
|
||||
autoconfigure="false"
|
||||
decoration-priority="20"
|
||||
>
|
||||
<argument type="service" id="Sylius\Bundle\ApiBundle\Swagger\AcceptLanguageHeaderDocumentationNormalizer.inner" />
|
||||
<argument type="service" id="sylius.repository.locale" />
|
||||
<service id="Sylius\Bundle\ApiBundle\OpenApi\Documentation\ShopAuthenticationTokenDocumentationModifier">
|
||||
<argument>%sylius.security.new_api_route%</argument>
|
||||
<tag name="sylius.open_api.modifier" />
|
||||
</service>
|
||||
</services>
|
||||
</container>
|
||||
|
|
|
|||
|
|
@ -1,65 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\Swagger;
|
||||
|
||||
use Sylius\Component\Locale\Model\LocaleInterface;
|
||||
use Sylius\Component\Resource\Repository\RepositoryInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
/** @experimental */
|
||||
final class AcceptLanguageHeaderDocumentationNormalizer implements NormalizerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private NormalizerInterface $decoratedNormalizer,
|
||||
private RepositoryInterface $localeRepository,
|
||||
) {
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, $format = null): bool
|
||||
{
|
||||
return $this->decoratedNormalizer->supportsNormalization($data, $format);
|
||||
}
|
||||
|
||||
public function normalize($object, $format = null, array $context = [])
|
||||
{
|
||||
$docs = $this->decoratedNormalizer->normalize($object, $format, $context);
|
||||
|
||||
$acceptLanguageHeader = [
|
||||
'name' => 'Accept-Language',
|
||||
'in' => 'header',
|
||||
'required' => false,
|
||||
'description' => 'Locales in this enum are all locales defined in the shop and only enabled ones will work in the given channel in the shop.',
|
||||
'schema' => [
|
||||
'type' => 'string',
|
||||
'enum' => array_map(
|
||||
fn (LocaleInterface $locale): string => $locale->getCode(),
|
||||
$this->localeRepository->findAll(),
|
||||
),
|
||||
],
|
||||
];
|
||||
|
||||
foreach ($docs['paths'] as $path => $methods) {
|
||||
foreach ($methods as $methodName => $methodBody) {
|
||||
if (is_object($methodBody)) {
|
||||
$methodBody = $methodBody->getArrayCopy();
|
||||
$methodBody['parameters'][] = $acceptLanguageHeader;
|
||||
|
||||
$docs['paths'][$path][$methodName] = $methodBody;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $docs;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\Swagger;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
/** @experimental */
|
||||
final class AdminAuthenticationTokenDocumentationNormalizer implements NormalizerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private NormalizerInterface $decoratedNormalizer,
|
||||
private string $apiRoute,
|
||||
) {
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, $format = null): bool
|
||||
{
|
||||
return $this->decoratedNormalizer->supportsNormalization($data, $format);
|
||||
}
|
||||
|
||||
public function normalize($object, $format = null, array $context = [])
|
||||
{
|
||||
$docs = $this->decoratedNormalizer->normalize($object, $format, $context);
|
||||
|
||||
$docs['components']['schemas']['AdminUserToken'] = [
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'token' => [
|
||||
'type' => 'string',
|
||||
'readOnly' => true,
|
||||
],
|
||||
'adminUser' => [
|
||||
'type' => 'string',
|
||||
'readOnly' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$docs['components']['schemas']['AdminUserCredentials'] = [
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'email' => [
|
||||
'type' => 'string',
|
||||
'example' => 'api@example.com',
|
||||
],
|
||||
'password' => [
|
||||
'type' => 'string',
|
||||
'example' => 'sylius-api',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$tokenDocumentation = [
|
||||
'paths' => [
|
||||
$this->apiRoute . '/admin/authentication-token' => [
|
||||
'post' => [
|
||||
'tags' => ['AdminUserToken'],
|
||||
'operationId' => 'postCredentialsItem',
|
||||
'summary' => 'Get JWT token to login.',
|
||||
'requestBody' => [
|
||||
'description' => 'Create new JWT Token',
|
||||
'content' => [
|
||||
'application/json' => [
|
||||
'schema' => [
|
||||
'$ref' => '#/components/schemas/AdminUserCredentials',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'responses' => [
|
||||
Response::HTTP_OK => [
|
||||
'description' => 'Get JWT token',
|
||||
'content' => [
|
||||
'application/json' => [
|
||||
'schema' => [
|
||||
'$ref' => '#/components/schemas/AdminUserToken',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
return array_merge_recursive($tokenDocumentation, $docs);
|
||||
}
|
||||
}
|
||||
|
|
@ -1,46 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\Swagger;
|
||||
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
class PathHiderDocumentationNormalizer implements NormalizerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private NormalizerInterface $decoratedNormalizer,
|
||||
private array $apiRoutes,
|
||||
) {
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, $format = null): bool
|
||||
{
|
||||
return $this->decoratedNormalizer->supportsNormalization($data, $format);
|
||||
}
|
||||
|
||||
public function normalize($object, $format = null, array $context = [])
|
||||
{
|
||||
$docs = $this->decoratedNormalizer->normalize($object, $format, $context);
|
||||
$paths = (array) $docs['paths'];
|
||||
|
||||
foreach ($this->apiRoutes as $apiRoute) {
|
||||
if (array_key_exists($apiRoute, $paths)) {
|
||||
unset($paths[$apiRoute]);
|
||||
}
|
||||
}
|
||||
|
||||
$docs['paths'] = $paths;
|
||||
|
||||
return $docs;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,45 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\Swagger;
|
||||
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
/** @experimental */
|
||||
final class ProductDocumentationNormalizer implements NormalizerInterface
|
||||
{
|
||||
public function __construct(private NormalizerInterface $decoratedNormalizer)
|
||||
{
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, $format = null)
|
||||
{
|
||||
return $this->decoratedNormalizer->supportsNormalization($data, $format);
|
||||
}
|
||||
|
||||
public function normalize($object, $format = null, array $context = [])
|
||||
{
|
||||
$docs = $this->decoratedNormalizer->normalize($object, $format, $context);
|
||||
|
||||
$defaultVariantSchema = [
|
||||
'type' => 'string',
|
||||
'format' => 'iri-reference',
|
||||
'nullable' => true,
|
||||
'readOnly' => true,
|
||||
];
|
||||
|
||||
$docs['components']['schemas']['Product.jsonld-shop.product.read']['properties']['defaultVariant'] = $defaultVariantSchema;
|
||||
|
||||
return $docs;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,51 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\Swagger;
|
||||
|
||||
use Sylius\Bundle\ApiBundle\Provider\ProductImageFilterProviderInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
/** @experimental */
|
||||
final class ProductImageDocumentationNormalizer implements NormalizerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private NormalizerInterface $decoratedNormalizer,
|
||||
private ProductImageFilterProviderInterface $filterProvider,
|
||||
private string $apiRoute,
|
||||
) {
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, $format = null)
|
||||
{
|
||||
return $this->decoratedNormalizer->supportsNormalization($data, $format);
|
||||
}
|
||||
|
||||
public function normalize($object, $format = null, array $context = [])
|
||||
{
|
||||
$docs = $this->decoratedNormalizer->normalize($object, $format, $context);
|
||||
|
||||
$enums = $this->filterProvider->provideShopFilters();
|
||||
$enums = array_keys($enums);
|
||||
|
||||
$shopProductImagePath = $this->apiRoute . '/shop/product-images/{id}';
|
||||
|
||||
foreach ($docs['paths'][$shopProductImagePath]['get']['parameters'] as &$param) {
|
||||
if ($param['in'] === 'query' && $param['name'] === 'filter') {
|
||||
$param['schema']['enum'] = $enums;
|
||||
}
|
||||
}
|
||||
|
||||
return $docs;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,50 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\Swagger;
|
||||
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
/** @experimental */
|
||||
final class ProductSlugDocumentationNormalizer implements NormalizerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private NormalizerInterface $decoratedNormalizer,
|
||||
private string $apiRoute,
|
||||
) {
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, $format = null): bool
|
||||
{
|
||||
return $this->decoratedNormalizer->supportsNormalization($data, $format);
|
||||
}
|
||||
|
||||
public function normalize($object, $format = null, array $context = [])
|
||||
{
|
||||
$docs = $this->decoratedNormalizer->normalize($object, $format, $context);
|
||||
|
||||
$shopProductBySlugPath = $this->apiRoute . '/shop/products-by-slug/{slug}';
|
||||
$params = $docs['paths'][$shopProductBySlugPath]['get']['parameters'];
|
||||
|
||||
foreach ($params as $index => $param) {
|
||||
if ($param['name'] === 'code') {
|
||||
unset($docs['paths'][$shopProductBySlugPath]['get']['parameters'][$index]);
|
||||
}
|
||||
}
|
||||
|
||||
// reset key index after unset
|
||||
$docs['paths'][$shopProductBySlugPath]['get']['parameters'] = array_values($docs['paths'][$shopProductBySlugPath]['get']['parameters']);
|
||||
|
||||
return $docs;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,53 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\Swagger;
|
||||
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
/** @experimental */
|
||||
final class ProductVariantDocumentationNormalizer implements NormalizerInterface
|
||||
{
|
||||
public function __construct(private NormalizerInterface $decoratedNormalizer)
|
||||
{
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, $format = null)
|
||||
{
|
||||
return $this->decoratedNormalizer->supportsNormalization($data, $format);
|
||||
}
|
||||
|
||||
public function normalize($object, $format = null, array $context = [])
|
||||
{
|
||||
$docs = $this->decoratedNormalizer->normalize($object, $format, $context);
|
||||
|
||||
$docs['components']['schemas']['ProductVariant.jsonld-shop.product_variant.read']['properties']['price'] = [
|
||||
'type' => 'integer',
|
||||
'readOnly' => true,
|
||||
'default' => 0,
|
||||
];
|
||||
|
||||
$docs['components']['schemas']['ProductVariant.jsonld-shop.product_variant.read']['properties']['inStock'] = [
|
||||
'type' => 'boolean',
|
||||
'readOnly' => true,
|
||||
];
|
||||
|
||||
$docs['components']['schemas']['ProductVariant.jsonld-shop.product_variant.read']['properties']['originalPrice'] = [
|
||||
'type' => 'integer',
|
||||
'readOnly' => true,
|
||||
'default' => 0,
|
||||
];
|
||||
|
||||
return $docs;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\Swagger;
|
||||
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
/** @experimental */
|
||||
final class ShippingMethodDocumentationNormalizer implements NormalizerInterface
|
||||
{
|
||||
public function __construct(private NormalizerInterface $decoratedNormalizer)
|
||||
{
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, $format = null): bool
|
||||
{
|
||||
return $this->decoratedNormalizer->supportsNormalization($data, $format);
|
||||
}
|
||||
|
||||
public function normalize($object, $format = null, array $context = [])
|
||||
{
|
||||
$docs = $this->decoratedNormalizer->normalize($object, $format, $context);
|
||||
|
||||
$docs['components']['schemas']['ShippingMethod.jsonld-shop.shipping_method.read']['properties']['price'] = [
|
||||
'type' => 'integer',
|
||||
'readOnly' => true,
|
||||
'default' => 0,
|
||||
];
|
||||
|
||||
return $docs;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,101 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace Sylius\Bundle\ApiBundle\Swagger;
|
||||
|
||||
use Symfony\Component\HttpFoundation\Response;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
/** @experimental */
|
||||
final class ShopAuthenticationTokenDocumentationNormalizer implements NormalizerInterface
|
||||
{
|
||||
public function __construct(
|
||||
private NormalizerInterface $decoratedNormalizer,
|
||||
private string $apiRoute,
|
||||
) {
|
||||
}
|
||||
|
||||
public function supportsNormalization($data, $format = null): bool
|
||||
{
|
||||
return $this->decoratedNormalizer->supportsNormalization($data, $format);
|
||||
}
|
||||
|
||||
public function normalize($object, $format = null, array $context = [])
|
||||
{
|
||||
$docs = $this->decoratedNormalizer->normalize($object, $format, $context);
|
||||
|
||||
$docs['components']['schemas']['ShopUserToken'] = [
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'token' => [
|
||||
'type' => 'string',
|
||||
'readOnly' => true,
|
||||
],
|
||||
'customer' => [
|
||||
'type' => 'string',
|
||||
'readOnly' => true,
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$docs['components']['schemas']['ShopUserCredentials'] = [
|
||||
'type' => 'object',
|
||||
'properties' => [
|
||||
'email' => [
|
||||
'type' => 'string',
|
||||
'example' => 'shop@example.com',
|
||||
],
|
||||
'password' => [
|
||||
'type' => 'string',
|
||||
'example' => 'sylius',
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$tokenDocumentation = [
|
||||
'paths' => [
|
||||
$this->apiRoute . '/shop/authentication-token' => [
|
||||
'post' => [
|
||||
'tags' => ['ShopUserToken'],
|
||||
'operationId' => 'postCredentialsItem',
|
||||
'summary' => 'Get JWT token to login.',
|
||||
'requestBody' => [
|
||||
'description' => 'Create new JWT Token',
|
||||
'content' => [
|
||||
'application/json' => [
|
||||
'schema' => [
|
||||
'$ref' => '#/components/schemas/ShopUserCredentials',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
'responses' => [
|
||||
Response::HTTP_OK => [
|
||||
'description' => 'Get JWT token',
|
||||
'content' => [
|
||||
'application/json' => [
|
||||
'schema' => [
|
||||
'$ref' => '#/components/schemas/ShopUserToken',
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
return array_merge_recursive($docs, $tokenDocumentation);
|
||||
}
|
||||
}
|
||||
|
|
@ -14,7 +14,6 @@ declare(strict_types=1);
|
|||
namespace Sylius\Bundle\ApiBundle\Tests\DependencyInjection;
|
||||
|
||||
use Matthias\SymfonyDependencyInjectionTest\PhpUnit\AbstractExtensionTestCase;
|
||||
use Sylius\Bundle\ApiBundle\ApiPlatform\Bridge\Symfony\Bundle\Action\SwaggerUiAction;
|
||||
use Sylius\Bundle\ApiBundle\DependencyInjection\SyliusApiExtension;
|
||||
|
||||
final class SyliusApiExtensionTest extends AbstractExtensionTestCase
|
||||
|
|
@ -24,10 +23,10 @@ final class SyliusApiExtensionTest extends AbstractExtensionTestCase
|
|||
{
|
||||
$this->container->setParameter('kernel.bundles_metadata', ['SyliusApiBundle' => ['path' => __DIR__ . '../..']]);
|
||||
|
||||
$this->setParameter('api_platform.enable_swagger_ui', true);
|
||||
$this->setParameter('api_platform.swagger.api_keys', []);
|
||||
$this->load();
|
||||
|
||||
$this->assertContainerBuilderHasService('api_platform.swagger.action.ui', SwaggerUiAction::class);
|
||||
$this->assertContainerBuilderHasService('Sylius\Bundle\ApiBundle\OpenApi\Documentation\AcceptLanguageHeaderDocumentationModifier');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
|
|
@ -35,20 +34,9 @@ final class SyliusApiExtensionTest extends AbstractExtensionTestCase
|
|||
{
|
||||
$this->container->setParameter('kernel.bundles_metadata', ['SyliusApiBundle' => ['path' => __DIR__ . '../..']]);
|
||||
|
||||
$this->setParameter('api_platform.enable_swagger_ui', false);
|
||||
$this->load();
|
||||
|
||||
$this->assertContainerBuilderNotHasService('api_platform.swagger.action.ui');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
public function it_does_not_load_swagger_integration_if_it_does_not_exists(): void
|
||||
{
|
||||
$this->container->setParameter('kernel.bundles_metadata', ['SyliusApiBundle' => ['path' => __DIR__ . '../..']]);
|
||||
|
||||
$this->load();
|
||||
|
||||
$this->assertContainerBuilderNotHasService('api_platform.swagger.action.ui');
|
||||
$this->assertContainerBuilderNotHasService('Sylius\Bundle\ApiBundle\OpenApi\Documentation\AcceptLanguageHeaderDocumentationModifier');
|
||||
}
|
||||
|
||||
/** @test */
|
||||
|
|
|
|||
|
|
@ -1,142 +0,0 @@
|
|||
<?php
|
||||
|
||||
/*
|
||||
* This file is part of the Sylius package.
|
||||
*
|
||||
* (c) Sylius Sp. z o.o.
|
||||
*
|
||||
* For the full copyright and license information, please view the LICENSE
|
||||
* file that was distributed with this source code.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace spec\Sylius\Bundle\ApiBundle\Swagger;
|
||||
|
||||
use ApiPlatform\Core\Documentation\Documentation;
|
||||
use ApiPlatform\Core\Metadata\Resource\ResourceNameCollection;
|
||||
use PhpSpec\ObjectBehavior;
|
||||
use Sylius\Component\Locale\Model\LocaleInterface;
|
||||
use Sylius\Component\Resource\Repository\RepositoryInterface;
|
||||
use Symfony\Component\Serializer\Normalizer\NormalizerInterface;
|
||||
|
||||
final class AcceptLanguageHeaderDocumentationNormalizerSpec extends ObjectBehavior
|
||||
{
|
||||
function let(NormalizerInterface $decoratedNormalizer, RepositoryInterface $localeRepository): void
|
||||
{
|
||||
$this->beConstructedWith($decoratedNormalizer, $localeRepository);
|
||||
}
|
||||
|
||||
function it_supports_normalization(NormalizerInterface $decoratedNormalizer): void
|
||||
{
|
||||
$documentation = new Documentation(new ResourceNameCollection());
|
||||
|
||||
$decoratedNormalizer->supportsNormalization($documentation, null)->willReturn(true);
|
||||
|
||||
$this->supportsNormalization($documentation)->shouldReturn(true);
|
||||
}
|
||||
|
||||
function it_does_not_support_normalization(NormalizerInterface $decoratedNormalizer): void
|
||||
{
|
||||
$decoratedNormalizer->supportsNormalization(null, null)->willReturn(false);
|
||||
|
||||
$this->supportsNormalization(null)->shouldReturn(false);
|
||||
}
|
||||
|
||||
function it_does_not_add_accept_language_header_to_paths_which_are_not_objects(
|
||||
NormalizerInterface $decoratedNormalizer,
|
||||
RepositoryInterface $localeRepository,
|
||||
LocaleInterface $locale1,
|
||||
LocaleInterface $locale2,
|
||||
): void {
|
||||
$docs = [
|
||||
'paths' => [
|
||||
'/api/v2/admin/addresses/{id}' => [
|
||||
'get' => [
|
||||
'parameters' => [],
|
||||
],
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$documentation = new Documentation(new ResourceNameCollection());
|
||||
|
||||
$localeRepository->findAll()->willReturn([$locale1, $locale2]);
|
||||
|
||||
$locale1->getCode()->willReturn('en_US');
|
||||
$locale2->getCode()->willReturn('de_DE');
|
||||
|
||||
$decoratedNormalizer
|
||||
->normalize($documentation, null, ['spec_version' => 3])
|
||||
->willReturn($docs)
|
||||
;
|
||||
|
||||
$this
|
||||
->normalize($documentation, null, ['spec_version' => 3])
|
||||
->shouldReturn([
|
||||
'paths' => [
|
||||
'/api/v2/admin/addresses/{id}' => [
|
||||
'get' => [
|
||||
'parameters' => [],
|
||||
],
|
||||
],
|
||||
],
|
||||
])
|
||||
;
|
||||
}
|
||||
|
||||
function it_adds_accept_language_header_to_paths_which_are_objects(
|
||||
NormalizerInterface $decoratedNormalizer,
|
||||
RepositoryInterface $localeRepository,
|
||||
LocaleInterface $locale1,
|
||||
LocaleInterface $locale2,
|
||||
): void {
|
||||
$docs = [
|
||||
'paths' => [
|
||||
'/api/v2/admin/addresses/{id}' => [
|
||||
'get' => new \ArrayObject(
|
||||
[
|
||||
'parameters' => [],
|
||||
],
|
||||
),
|
||||
],
|
||||
],
|
||||
];
|
||||
|
||||
$documentation = new Documentation(new ResourceNameCollection());
|
||||
|
||||
$localeRepository->findAll()->willReturn([$locale1, $locale2]);
|
||||
|
||||
$locale1->getCode()->willReturn('en_US');
|
||||
$locale2->getCode()->willReturn('de_DE');
|
||||
|
||||
$decoratedNormalizer
|
||||
->normalize($documentation, null, ['spec_version' => 3])
|
||||
->willReturn($docs)
|
||||
;
|
||||
|
||||
$this
|
||||
->normalize($documentation, null, ['spec_version' => 3])
|
||||
->shouldReturn([
|
||||
'paths' => [
|
||||
'/api/v2/admin/addresses/{id}' => [
|
||||
'get' => [
|
||||
'parameters' => [
|
||||
[
|
||||
'name' => 'Accept-Language',
|
||||
'in' => 'header',
|
||||
'required' => false,
|
||||
'description' => 'Locales in this enum are all locales defined in the shop and only enabled ones will work in the given channel in the shop.',
|
||||
'schema' => [
|
||||
'type' => 'string',
|
||||
'enum' => ['en_US', 'de_DE'],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
],
|
||||
])
|
||||
;
|
||||
}
|
||||
}
|
||||
192
templates/bundles/ApiPlatformBundle/SwaggerUi/index.html.twig
Normal file
192
templates/bundles/ApiPlatformBundle/SwaggerUi/index.html.twig
Normal file
|
|
@ -0,0 +1,192 @@
|
|||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<title>{% if title %}{{ title }} - {% endif %}API Platform</title>
|
||||
|
||||
{% block stylesheet %}
|
||||
<link rel="stylesheet" href="{{ asset('bundles/apiplatform/fonts/open-sans/400.css', assetPackage) }}">
|
||||
<link rel="stylesheet" href="{{ asset('bundles/apiplatform/fonts/open-sans/700.css', assetPackage) }}">
|
||||
<link rel="stylesheet" href="{{ asset('bundles/apiplatform/swagger-ui/swagger-ui.css', assetPackage) }}">
|
||||
<link rel="stylesheet" href="{{ asset('bundles/apiplatform/style.css', assetPackage) }}">
|
||||
{% endblock %}
|
||||
|
||||
{% set oauth_data = {'oauth': swagger_data.oauth|merge({'redirectUrl' : absolute_url(asset('bundles/apiplatform/swagger-ui/oauth2-redirect.html', assetPackage)) })} %}
|
||||
{# json_encode(65) is for JSON_UNESCAPED_SLASHES|JSON_HEX_TAG to avoid JS XSS #}
|
||||
<script id="swagger-data" type="application/json">{{ swagger_data|merge(oauth_data)|json_encode(65)|raw }}</script>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" style="position:absolute;width:0;height:0">
|
||||
<defs>
|
||||
<symbol viewBox="0 0 20 20" id="unlocked">
|
||||
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V6h2v-.801C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8z"></path>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="locked">
|
||||
<path d="M15.8 8H14V5.6C14 2.703 12.665 1 10 1 7.334 1 6 2.703 6 5.6V8H4c-.553 0-1 .646-1 1.199V17c0 .549.428 1.139.951 1.307l1.197.387C5.672 18.861 6.55 19 7.1 19h5.8c.549 0 1.428-.139 1.951-.307l1.196-.387c.524-.167.953-.757.953-1.306V9.199C17 8.646 16.352 8 15.8 8zM12 8H8V5.199C8 3.754 8.797 3 10 3c1.203 0 2 .754 2 2.199V8z"></path>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="close">
|
||||
<path d="M14.348 14.849c-.469.469-1.229.469-1.697 0L10 11.819l-2.651 3.029c-.469.469-1.229.469-1.697 0-.469-.469-.469-1.229 0-1.697l2.758-3.15-2.759-3.152c-.469-.469-.469-1.228 0-1.697.469-.469 1.228-.469 1.697 0L10 8.183l2.651-3.031c.469-.469 1.228-.469 1.697 0 .469.469.469 1.229 0 1.697l-2.758 3.152 2.758 3.15c.469.469.469 1.229 0 1.698z"></path>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="large-arrow">
|
||||
<path d="M13.25 10L6.109 2.58c-.268-.27-.268-.707 0-.979.268-.27.701-.27.969 0l7.83 7.908c.268.271.268.709 0 .979l-7.83 7.908c-.268.271-.701.27-.969 0-.268-.269-.268-.707 0-.979L13.25 10z"></path>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 20 20" id="large-arrow-down">
|
||||
<path d="M17.418 6.109c.272-.268.709-.268.979 0s.271.701 0 .969l-7.908 7.83c-.27.268-.707.268-.979 0l-7.908-7.83c-.27-.268-.27-.701 0-.969.271-.268.709-.268.979 0L10 13.25l7.418-7.141z"></path>
|
||||
</symbol>
|
||||
|
||||
|
||||
<symbol viewBox="0 0 24 24" id="jump-to">
|
||||
<path d="M19 7v4H5.83l3.58-3.59L8 6l-6 6 6 6 1.41-1.41L5.83 13H21V7z"></path>
|
||||
</symbol>
|
||||
|
||||
<symbol viewBox="0 0 24 24" id="expand">
|
||||
<path d="M10 18h4v-2h-4v2zM3 6v2h18V6H3zm3 7h12v-2H6v2z"></path>
|
||||
</symbol>
|
||||
|
||||
</defs>
|
||||
</svg>
|
||||
<header>
|
||||
<a id="logo" href="https://api-platform.com"><img src="{{ asset('bundles/apiplatform/logo-header.svg', assetPackage) }}" alt="API Platform"></a>
|
||||
{# > Sylius #}
|
||||
<a href="https://docs.sylius.com/en/latest/book/api/introduction.html">
|
||||
<div style="align-items: center; display: flex; height: 70px; font-size: 14px; color: #fff; font-weight: 700; font-family: sans-serif; padding: 10px 40px; position: fixed; top: 0; left: 0; background: #ed6a5a; z-index: 103;"><svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-alert-circle" style="margin-right: 10px;"><circle cx="12" cy="12" r="10"></circle><line x1="12" y1="8" x2="12" y2="12"></line><line x1="12" y1="16" x2="12.01" y2="16"></line></svg>EXPERIMENTAL</div>
|
||||
</a>
|
||||
{# Sylius < #}
|
||||
</header>
|
||||
|
||||
{% if showWebby %}
|
||||
<div class="web"><img src="{{ asset('bundles/apiplatform/web.png', assetPackage) }}"></div>
|
||||
<div class="webby"><img src="{{ asset('bundles/apiplatform/webby.png', assetPackage) }}"></div>
|
||||
{% endif %}
|
||||
|
||||
<div id="swagger-ui" class="api-platform"></div>
|
||||
|
||||
<div class="swagger-ui" id="formats">
|
||||
<div class="information-container wrapper">
|
||||
<div class="info">
|
||||
Available formats:
|
||||
{% for format in formats|keys %}
|
||||
<a href="{{ path(app.request.attributes.get('_route'), app.request.attributes.get('_route_params')|merge({'_format': format})) }}">{{ format }}</a>
|
||||
{% endfor %}
|
||||
<br>
|
||||
Other API docs:
|
||||
{% set active_ui = app.request.get('ui', 'swagger_ui') %}
|
||||
{% if swaggerUiEnabled and active_ui != 'swagger_ui' %}<a href="{{ path('api_doc') }}">Swagger UI</a>{% endif %}
|
||||
{% if reDocEnabled and active_ui != 're_doc' %}<a href="{{ path('api_doc', {'ui': 're_doc'}) }}">ReDoc</a>{% endif %}
|
||||
{# FIXME: Typo in graphql => graphQl in SwaggerUiAction #}
|
||||
{% if not graphqlEnabled %}<a href="javascript:alert('GraphQL support is not enabled, see https://api-platform.com/docs/core/graphql/')">GraphiQL</a>{% endif %}
|
||||
{% if graphiQlEnabled %}<a href="{{ path('api_graphql_graphiql') }}">GraphiQL</a>{% endif %}
|
||||
{% if graphQlPlaygroundEnabled %}<a href="{{ path('api_graphql_graphql_playground') }}">GraphQL Playground</a>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% block javascript %}
|
||||
{% if (reDocEnabled and not swaggerUiEnabled) or (reDocEnabled and 're_doc' == active_ui) %}
|
||||
<script src="{{ asset('bundles/apiplatform/redoc/redoc.standalone.js', assetPackage) }}"></script>
|
||||
<script src="{{ asset('bundles/apiplatform/init-redoc-ui.js', assetPackage) }}"></script>
|
||||
{% else %}
|
||||
<script src="{{ asset('bundles/apiplatform/swagger-ui/swagger-ui-bundle.js', assetPackage) }}"></script>
|
||||
<script src="{{ asset('bundles/apiplatform/swagger-ui/swagger-ui-standalone-preset.js', assetPackage) }}"></script>
|
||||
<script src="{{ asset('bundles/apiplatform/init-swagger-ui.js', assetPackage) }}"></script>
|
||||
{% endif %}
|
||||
|
||||
{# > Sylius #}
|
||||
<script>
|
||||
class ClassWatcher {
|
||||
constructor(targetNode, classToWatch, classAddedCallback, classRemovedCallback) {
|
||||
this.targetNode = targetNode
|
||||
this.classToWatch = classToWatch
|
||||
this.classAddedCallback = classAddedCallback
|
||||
this.classRemovedCallback = classRemovedCallback
|
||||
this.observer = null
|
||||
this.lastClassState = targetNode.classList.contains(this.classToWatch)
|
||||
|
||||
this.init()
|
||||
}
|
||||
|
||||
init() {
|
||||
this.observer = new MutationObserver(this.mutationCallback)
|
||||
this.observe()
|
||||
}
|
||||
|
||||
observe() {
|
||||
this.observer.observe(this.targetNode, { attributes: true })
|
||||
}
|
||||
|
||||
disconnect() {
|
||||
this.observer.disconnect()
|
||||
}
|
||||
|
||||
mutationCallback = mutationsList => {
|
||||
for(let mutation of mutationsList) {
|
||||
if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
|
||||
let currentClassState = mutation.target.classList.contains(this.classToWatch)
|
||||
if(this.lastClassState !== currentClassState) {
|
||||
this.lastClassState = currentClassState
|
||||
if(currentClassState) {
|
||||
this.classAddedCallback()
|
||||
}
|
||||
else {
|
||||
this.classRemovedCallback()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let tokenRequestContainer = null;
|
||||
|
||||
function credentialsRequestReady() {
|
||||
const tokenRequestContainer2 = document.querySelector('#operations-AdminUserToken-postCredentialsItem').getElementsByClassName('opblock-body')[0];
|
||||
|
||||
const executeWrapper = tokenRequestContainer2.getElementsByClassName('execute-wrapper')[0];
|
||||
new ClassWatcher(executeWrapper, 'btn-group', credentialsRequestFinished, () => {});
|
||||
}
|
||||
|
||||
function credentialsRequestFinished() {
|
||||
const tokenElement = JSON.parse(tokenRequestContainer.querySelector('.highlight-code').getElementsByTagName('code')[0].innerText)
|
||||
|
||||
const buttonLogin = document.querySelector("#swagger-ui > section > div.swagger-ui > div:nth-child(2) > div.scheme-container > section > div > button");
|
||||
|
||||
const mouseEvent = new MouseEvent('click', {
|
||||
view: window,
|
||||
bubbles: true,
|
||||
cancelable: true
|
||||
});
|
||||
|
||||
buttonLogin.dispatchEvent(mouseEvent);
|
||||
|
||||
const authFormField = document.querySelector("#swagger-ui > section > div.swagger-ui > div:nth-child(2) > div.scheme-container > section > div > div > div.modal-ux > div > div > div.modal-ux-content > div > form > div:nth-child(1) > div > div:nth-child(5) > section > input[type=text]");
|
||||
|
||||
const authorizeSubmitButton = document.querySelector("#swagger-ui > section > div.swagger-ui > div:nth-child(2) > div.scheme-container > section > div > div > div.modal-ux > div > div > div.modal-ux-content > div > form > div.auth-btn-wrapper > button.btn.modal-btn.auth.authorize.button");
|
||||
|
||||
const nativeInputValueSetter = Object.getOwnPropertyDescriptor(window.HTMLInputElement.prototype, "value").set;
|
||||
nativeInputValueSetter.call(authFormField, `Bearer ${tokenElement.token}`);
|
||||
|
||||
authFormField.dispatchEvent(new Event('input', { bubbles: true }));
|
||||
|
||||
authorizeSubmitButton.dispatchEvent(mouseEvent);
|
||||
|
||||
const closeAuthFormButton = document.querySelector("#swagger-ui > section > div.swagger-ui > div:nth-child(2) > div.scheme-container > section > div > div > div.modal-ux > div > div > div.modal-ux-content > div > form > div.auth-btn-wrapper > button.btn.modal-btn.auth.btn-done.button");
|
||||
|
||||
closeAuthFormButton.dispatchEvent(mouseEvent);
|
||||
}
|
||||
|
||||
window.addEventListener('load', event => {
|
||||
tokenRequestContainer = document.querySelector('#operations-AdminUserToken-postCredentialsItem');
|
||||
|
||||
new ClassWatcher(tokenRequestContainer, 'is-open', credentialsRequestReady, function(){});
|
||||
});
|
||||
</script>
|
||||
{# Sylius < #}
|
||||
{% endblock %}
|
||||
|
||||
</body>
|
||||
</html>
|
||||
Loading…
Add table
Reference in a new issue