Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce new OpenApi component #49573

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,7 @@
"symfony/mime": "self.version",
"symfony/monolog-bridge": "self.version",
"symfony/notifier": "self.version",
"symfony/openapi": "self.version",
"symfony/options-resolver": "self.version",
"symfony/password-hasher": "self.version",
"symfony/process": "self.version",
Expand Down
4 changes: 4 additions & 0 deletions src/Symfony/Component/OpenApi/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
/Tests export-ignore
/phpunit.xml.dist export-ignore
/.gitattributes export-ignore
/.gitignore export-ignore
4 changes: 4 additions & 0 deletions src/Symfony/Component/OpenApi/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
composer.lock
phpunit.xml
vendor/
.phpunit.result.cache
145 changes: 145 additions & 0 deletions src/Symfony/Component/OpenApi/Builder/OpenApiBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\OpenApi\Builder;

use Symfony\Component\OpenApi\Configurator\CallbackRequestConfigurator;
use Symfony\Component\OpenApi\Configurator\ComponentsConfigurator;
use Symfony\Component\OpenApi\Configurator\EncodingConfigurator;
use Symfony\Component\OpenApi\Configurator\ExampleConfigurator;
use Symfony\Component\OpenApi\Configurator\InfoConfigurator;
use Symfony\Component\OpenApi\Configurator\LinkConfigurator;
use Symfony\Component\OpenApi\Configurator\MediaTypeConfigurator;
use Symfony\Component\OpenApi\Configurator\OperationConfigurator;
use Symfony\Component\OpenApi\Configurator\ParameterConfigurator;
use Symfony\Component\OpenApi\Configurator\PathItemConfigurator;
use Symfony\Component\OpenApi\Configurator\QueryParameterConfigurator;
use Symfony\Component\OpenApi\Configurator\QueryParametersConfigurator;
use Symfony\Component\OpenApi\Configurator\ReferenceConfigurator;
use Symfony\Component\OpenApi\Configurator\RequestBodyConfigurator;
use Symfony\Component\OpenApi\Configurator\ResponseConfigurator;
use Symfony\Component\OpenApi\Configurator\ResponsesConfigurator;
use Symfony\Component\OpenApi\Configurator\SchemaConfigurator;
use Symfony\Component\OpenApi\Configurator\SecuritySchemeConfigurator;
use Symfony\Component\OpenApi\Configurator\ServerConfigurator;
use Symfony\Component\OpenApi\Configurator\TagConfigurator;

/**
* @author Titouan Galopin <galopintitouan@gmail.com>
* @author Selency Team <tech@selency.fr>
*/
class OpenApiBuilder implements OpenApiBuilderInterface
{
public function schema(SchemaConfigurator|ReferenceConfigurator|string $definition = null): SchemaConfigurator|ReferenceConfigurator
{
return SchemaConfigurator::createFromDefinition($definition);
}

public function callbackRequest(): CallbackRequestConfigurator
{
return new CallbackRequestConfigurator();
}

public function components(): ComponentsConfigurator
{
return new ComponentsConfigurator();
}

public function content(): MediaTypeConfigurator
{
return new MediaTypeConfigurator();
}

public function encoding(): EncodingConfigurator
{
return new EncodingConfigurator();
}

public function example(): ExampleConfigurator
{
return new ExampleConfigurator();
}

public function info(): InfoConfigurator
{
return new InfoConfigurator();
}

public function link(): LinkConfigurator
{
return new LinkConfigurator();
}

public function mediaType(): MediaTypeConfigurator
{
return new MediaTypeConfigurator();
}

public function operation(): OperationConfigurator
{
return new OperationConfigurator($this);
}

public function parameter(string $name): ParameterConfigurator
{
return new ParameterConfigurator($name);
}

public function queryParameter(string $name): QueryParameterConfigurator
{
return new QueryParameterConfigurator($name);
}

public function queryParameters(): QueryParametersConfigurator
{
return new QueryParametersConfigurator($this);
}

public function pathItem(): PathItemConfigurator
{
return new PathItemConfigurator($this);
}

public function reference(string $ref): ReferenceConfigurator
{
return new ReferenceConfigurator($ref);
}

public function requestBody(): RequestBodyConfigurator
{
return new RequestBodyConfigurator();
}

public function response(): ResponseConfigurator
{
return new ResponseConfigurator();
}

public function responses(): ResponsesConfigurator
{
return new ResponsesConfigurator();
}

public function securityScheme(): SecuritySchemeConfigurator
{
return new SecuritySchemeConfigurator();
}

public function server(string $url): ServerConfigurator
{
return new ServerConfigurator($url);
}

public function tag(): TagConfigurator
{
return new TagConfigurator();
}
}
82 changes: 82 additions & 0 deletions src/Symfony/Component/OpenApi/Builder/OpenApiBuilderInterface.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\OpenApi\Builder;

use Symfony\Component\OpenApi\Configurator\CallbackRequestConfigurator;
use Symfony\Component\OpenApi\Configurator\ComponentsConfigurator;
use Symfony\Component\OpenApi\Configurator\EncodingConfigurator;
use Symfony\Component\OpenApi\Configurator\ExampleConfigurator;
use Symfony\Component\OpenApi\Configurator\InfoConfigurator;
use Symfony\Component\OpenApi\Configurator\LinkConfigurator;
use Symfony\Component\OpenApi\Configurator\MediaTypeConfigurator;
use Symfony\Component\OpenApi\Configurator\OperationConfigurator;
use Symfony\Component\OpenApi\Configurator\ParameterConfigurator;
use Symfony\Component\OpenApi\Configurator\PathItemConfigurator;
use Symfony\Component\OpenApi\Configurator\QueryParameterConfigurator;
use Symfony\Component\OpenApi\Configurator\QueryParametersConfigurator;
use Symfony\Component\OpenApi\Configurator\ReferenceConfigurator;
use Symfony\Component\OpenApi\Configurator\RequestBodyConfigurator;
use Symfony\Component\OpenApi\Configurator\ResponseConfigurator;
use Symfony\Component\OpenApi\Configurator\ResponsesConfigurator;
use Symfony\Component\OpenApi\Configurator\SchemaConfigurator;
use Symfony\Component\OpenApi\Configurator\SecuritySchemeConfigurator;
use Symfony\Component\OpenApi\Configurator\ServerConfigurator;
use Symfony\Component\OpenApi\Configurator\TagConfigurator;

/**
* @author Titouan Galopin <galopintitouan@gmail.com>
* @author Selency Team <tech@selency.fr>
*/
interface OpenApiBuilderInterface
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this be an interface (for which we cannot add methods outside major versions) ? Or just having the OpenApiBuilder allowing us to add more methods if new versions of OpenApi add new features ?

{
public function schema(SchemaConfigurator|ReferenceConfigurator|string $definition = null): SchemaConfigurator|ReferenceConfigurator;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As SchemaConfigurator and ReferenceConfigurator don't have the same API and the are returned for different kind of input, I'm wondering whether it is a good idea to have such a union type as return type. SA tools will force you to restrict the type when the method you want to use is not one of the common ones, and IDE completion will generally suggest methods from both classes while this won't always be valid either.


public function callbackRequest(): CallbackRequestConfigurator;

public function components(): ComponentsConfigurator;

public function content(): MediaTypeConfigurator;

public function encoding(): EncodingConfigurator;

public function example(): ExampleConfigurator;

public function info(): InfoConfigurator;

public function link(): LinkConfigurator;

public function mediaType(): MediaTypeConfigurator;

public function operation(): OperationConfigurator;

public function parameter(string $name): ParameterConfigurator;

public function queryParameter(string $name): QueryParameterConfigurator;

public function queryParameters(): QueryParametersConfigurator;

public function pathItem(): PathItemConfigurator;

public function reference(string $ref): ReferenceConfigurator;

public function requestBody(): RequestBodyConfigurator;

public function response(): ResponseConfigurator;

public function responses(): ResponsesConfigurator;

public function securityScheme(): SecuritySchemeConfigurator;

public function server(string $url): ServerConfigurator;

public function tag(): TagConfigurator;
}
8 changes: 8 additions & 0 deletions src/Symfony/Component/OpenApi/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
CHANGELOG
=========

6.3
---

* Add the component as experimental

48 changes: 48 additions & 0 deletions src/Symfony/Component/OpenApi/Compiler/DocumentationCompiler.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\OpenApi\Compiler;

use Symfony\Component\OpenApi\Configurator\DocumentationConfigurator;
use Symfony\Component\OpenApi\Documentation\DocumentationInterface;
use Symfony\Component\OpenApi\Loader\ComponentsLoaderInterface;
use Symfony\Component\OpenApi\Model\OpenApi;

/**
* @author Titouan Galopin <galopintitouan@gmail.com>
* @author Selency Team <tech@selency.fr>
*/
class DocumentationCompiler implements DocumentationCompilerInterface
{
/**
* @param iterable<ComponentsLoaderInterface> $componentsLoaders
*/
public function __construct(private iterable $componentsLoaders = [])
{
}

public function compile(DocumentationInterface $doc): OpenApi
{
// Instanciate root configurator
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Typo here. this is Instantiate.
but I would remove the comment entirely as the next line is clear enough

$rootConfigurator = new DocumentationConfigurator();

// Load components for this doc
foreach ($this->componentsLoaders as $loader) {
$doc->loadComponents($rootConfigurator, $loader);
}

// Apply user documentation details
$doc->configure($rootConfigurator);

// Compile the documentation
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this comment is confusing, as the whole method is about compiling the documentation (otherwise the name is bad)

return $rootConfigurator->build($doc->getIdentifier(), $doc->getVersion());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\OpenApi\Compiler;

use Symfony\Component\OpenApi\Documentation\DocumentationInterface;
use Symfony\Component\OpenApi\Model\OpenApi;

/**
* @author Titouan Galopin <galopintitouan@gmail.com>
* @author Selency Team <tech@selency.fr>
*/
interface DocumentationCompilerInterface
{
public function compile(DocumentationInterface $doc): OpenApi;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
<?php

/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <fabien@symfony.com>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Symfony\Component\OpenApi\Configurator;

use Symfony\Component\OpenApi\Model\CallbackRequest;
use Symfony\Component\OpenApi\Model\PathItem;
use Symfony\Component\OpenApi\Model\Reference;

/**
* @author Titouan Galopin <galopintitouan@gmail.com>
* @author Selency Team <tech@selency.fr>
*/
class CallbackRequestConfigurator
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should all those configurator classes be final ?

{
use Traits\ExtensionsTrait;

private string $expression = '';
private PathItem|Reference|null $definition = null;

public function build(): CallbackRequest
{
return new CallbackRequest($this->expression, $this->definition, $this->specificationExtensions);
}

public function expression(string $expression): static
{
$this->expression = $expression;

return $this;
}

public function definition(ReferenceConfigurator|PathItemConfigurator $definition): static
{
$this->definition = $definition->build();

return $this;
}
}