Skip to content

Commit

Permalink
[PHP] update dependencies for php-dt generated code (OpenAPITools#17796)
Browse files Browse the repository at this point in the history
* php-dt update:
- bump minimal required PHP version to 7.4 (8.1 for modern mode)
- bump minimal required DataTransfer version to 0.6
- support for date / date-time string lists and maps
- support for request and response bodies with date / date-time string schema
- minimal file string support

* docs update
  • Loading branch information
Articus authored and kota65535 committed Feb 23, 2024
1 parent 993e9fa commit 4d64f9b
Show file tree
Hide file tree
Showing 52 changed files with 689 additions and 588 deletions.
2 changes: 1 addition & 1 deletion docs/generators/php-dt.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|legacyDiscriminatorBehavior|Set to false for generators with better support for discriminators. (Python, Java, Go, PowerShell, C# have this enabled by default).|<dl><dt>**true**</dt><dd>The mapping in the discriminator includes descendent schemas that allOf inherit from self and the discriminator mapping schemas in the OAS document.</dd><dt>**false**</dt><dd>The mapping in the discriminator includes any descendent schemas that allOf inherit from self, any oneOf schemas, any anyOf schemas, any x-discriminator-values, and the discriminator mapping schemas in the OAS document AND Codegen validates that oneOf and anyOf schemas contain the required discriminator and throws an error if the discriminator is missing.</dd></dl>|true|
|licenseName|The name of the license| |null|
|modelPackage|package for generated models| |null|
|modern|use modern language features (generated code will require PHP 8.0)| |false|
|modern|use modern language features (generated code will require PHP 8.1)| |false|
|packageName|The main package name for classes. e.g. GeneratedPetstore| |null|
|prependFormOrBodyParameters|Add form or body parameters to the beginning of the parameter list.| |false|
|sortModelPropertiesByRequiredFlag|Sort model properties to place required parameters before optional parameters.| |true|
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,12 @@ public PhpDataTransferClientCodegen() {
// remove these from primitive types to make the output works
languageSpecificPrimitives.remove("\\DateTime");
languageSpecificPrimitives.remove("\\SplFileObject");
// fix date and date-time mapping to support both DateTime and DateTimeImmutable
typeMapping.put("date", "\\DateTimeInterface");
typeMapping.put("Date", "\\DateTimeInterface");
typeMapping.put("DateTime", "\\DateTimeInterface");
// TODO provide proper support for "file" string format
typeMapping.put("file", "string");

apiTemplateFiles.clear();
apiTestTemplateFiles.clear();
Expand All @@ -108,7 +114,7 @@ public PhpDataTransferClientCodegen() {

additionalProperties.put(CodegenConstants.ARTIFACT_VERSION, "1.0.0");
//Register custom CLI options
addSwitch(OPT_MODERN, "use modern language features (generated code will require PHP 8.0)", useModernSyntax);
addSwitch(OPT_MODERN, "use modern language features (generated code will require PHP 8.1)", useModernSyntax);
}

@Override
Expand Down Expand Up @@ -153,13 +159,26 @@ public String toApiName(String name) {
return super.toApiName(toModelName(name));
}

@Override
public String toRegularExpression(String pattern) {
String result = super.toRegularExpression(pattern);
if ((result != null) && (!useModernSyntax)) {
//Doctrine Annotations have different string escape rules compared to PHP code
result = result
.replace("\\\\", "\\")
.replace("\\\"", "\"\"")
;
}
return result;
}

@Override
public String getTypeDeclaration(Schema p) {
String result;
Map<String, Object> extensions = p.getExtensions();
if ((extensions != null) && extensions.containsKey(VEN_CONTAINER_DATA_TYPE)) {
result = (String) extensions.get(VEN_CONTAINER_DATA_TYPE);
} else if (useModernSyntax && (ModelUtils.isArraySchema(p) || ModelUtils.isMapSchema(p))) {
} else if (ModelUtils.isArraySchema(p) || ModelUtils.isMapSchema(p)) {
result = "array";
} else {
result = super.getTypeDeclaration(p);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,17 @@ class ApiClient extends OAGAC\AbstractApiClient
$request = $this->addCookies($request, $parameters);
{{/cookieParams.0}}
{{#bodyParam}}
{{#isDate}}
$request = $this->addBody($request, $requestMediaType, $requestContent, ($this->contentStrategies)('Date', []));
{{/isDate}}
{{#isDateTime}}
$request = $this->addBody($request, $requestMediaType, $requestContent, ($this->contentStrategies)('DateTime', []));
{{/isDateTime}}
{{^isDate}}
{{^isDateTime}}
$request = $this->addBody($request, $requestMediaType, $requestContent);
{{/isDateTime}}
{{/isDate}}
{{/bodyParam}}
{{#hasProduces}}
$request = $this->addAcceptHeader($request, $responseMediaType);
Expand All @@ -68,32 +78,44 @@ class ApiClient extends OAGAC\AbstractApiClient
{
$response = $this->{{operationId}}Raw({{>api_arg_call}});
$responseContent = null;
$contentStrategy = null;
$contentValidator = null;
switch ($response->getStatusCode())
{
{{#responses}}
{{#isDefault}}default{{/isDefault}}{{^isDefault}}case {{code}}{{/isDefault}}:
{{#message}}
/* {{&message}} */
{{/message}}
{{#isModel}}
$responseContent = new {{dataType}}();
{{/isModel}}
{{^isModel}}
{{#isArray}}
$responseContent = new {{dataType}}();
{{/isArray}}
{{/isModel}}
{{^isModel}}
{{^isArray}}
{{#isMap}}
$responseContent = new {{dataType}}();
{{/isMap}}
{{/isArray}}
{{#isDate}}
$contentStrategy = ($this->contentStrategies)('Date', []);
$contentValidator = ($this->contentValidators)('Date', []);
{{/isDate}}
{{#isDateTime}}
$contentStrategy = ($this->contentStrategies)('DateTime', []);
$contentValidator = ($this->contentValidators)('DateTime', []);
{{/isDateTime}}
{{^isDate}}
{{^isDateTime}}
{{^isArray}}
{{^isMap}}
{{#isModel}}
$responseContent = new {{dataType}}();
{{/isModel}}
{{/isMap}}
{{/isArray}}
{{/isDateTime}}
{{/isDate}}
break;
{{/responses}}
}
$this->parseBody($response, $responseContent);
$this->parseBody($response, $responseContent, $contentStrategy, $contentValidator);
return [$responseContent, $response->getHeaders(), $response->getStatusCode(), $response->getReasonPhrase()];
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,18 +3,20 @@ declare(strict_types=1);

namespace {{invokerPackage}};

use Articus\DataTransfer as DT;
use Interop\Container\ContainerInterface;
use Articus\PluginManager as PM;
use OpenAPIGenerator\APIClient as OAGAC;
use Psr\Container\ContainerInterface;

class ApiClientFactory extends DT\ConfigAwareFactory
class ApiClientFactory implements PM\ServiceFactoryInterface
{
use PM\ConfigAwareFactoryTrait;
public function __construct(string $configKey = ApiClient::class)
{
parent::__construct($configKey);
$this->configKey = $configKey;
}

public function __invoke(ContainerInterface $container, $requestedName, array $options = null)
public function __invoke(ContainerInterface $container, $requestedName, array $options = null): ApiClient
{
$config = new OAGAC\ApiClientOptions(\array_merge($this->getServiceConfig($container), $options ?? []));
return new ApiClient(
Expand All @@ -24,7 +26,9 @@ class ApiClientFactory extends DT\ConfigAwareFactory
$container->get($config->httpClientServiceName),
$container->get($config->securityProviderFactoryServiceName),
$container->get($config->bodyCoderFactoryServiceName),
$container->get($config->bodyCoderFactoryServiceName)
$container->get($config->bodyCoderFactoryServiceName),
$container->get($config->contentStrategyFactoryServiceName),
$container->get($config->contentValidatorFactoryServiceName)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ Generated by the [OpenAPI Generator](https://openapi-generator.tech) project.
## Overview
This lightweight extensible client library is [PSR-7](https://www.php-fig.org/psr/psr-7), [PSR-11](https://www.php-fig.org/psr/psr-11), [PSR-17](https://www.php-fig.org/psr/psr-17) and [PSR-18](https://www.php-fig.org/psr/psr-18) complaint and relies on:

- PHP: >=8.0
- [Data Transfer](https://github.com/Articus/DataTransfer): >=0.5
- PHP: >=8.1
- [Data Transfer](https://github.com/Articus/DataTransfer): >=0.6


## How to use
Expand All @@ -21,7 +21,7 @@ Then check content types for API requests you intend to send and API responses y

After that review security requirements for API operations you intend to use. For each unique security scheme you will need an implementation of [OpenAPIGenerator\APIClient\SecurityProviderInterface](https://github.com/Articus/OpenAPIGeneratorAPIClient-PHP/blob/master/src/OpenAPIGenerator/APIClient/SecurityProviderInterface.php). Currently, only [HTTP Bearer authentication](https://github.com/Articus/OpenAPIGeneratorAPIClient-PHP/blob/master/src/OpenAPIGenerator/APIClient/SecurityProvider/HttpBearer.php) is supported out-of-the-box.

The last step is to configure and wire all services together. It is highly advisable to use [PSR-11 container](https://packagist.org/packages/psr/container) for that. If you have not selected one for your project yet, https://packagist.org/providers/psr/container-implementation may help to find some suitable options. Here is a sample wiring configuration for `"laminas/laminas-servicemanager"`, `"laminas/laminas-diactoros"` and `"symfony/http-client"` (consult generated `composer.json` for the exact versions of used packages):
The last step is to configure and wire all services together. It is highly advisable to use [PSR-11 container](https://packagist.org/packages/psr/container) for that. If you have not selected one for your project yet, https://packagist.org/providers/psr/container-implementation may help to find some suitable options. Here is a sample wiring configuration for `"laminas/laminas-servicemanager"`, `"nyholm/psr7"` and `"symfony/http-client"` (consult generated `composer.json` for the exact versions of used packages):

```PHP
<?php
Expand All @@ -31,21 +31,24 @@ require_once __DIR__ . '/vendor/autoload.php';

$dependencies = [
'invokables' => [
Psr\Http\Message\RequestFactoryInterface::class => Laminas\Diactoros\RequestFactory::class,
Psr\Http\Message\ResponseFactoryInterface::class => Laminas\Diactoros\ResponseFactory::class,
Psr\Http\Message\StreamFactoryInterface::class => Laminas\Diactoros\StreamFactory::class,
Psr\Http\Message\RequestFactoryInterface::class => Nyholm\Psr7\Factory\Psr17Factory::class,
Psr\Http\Message\ResponseFactoryInterface::class => Nyholm\Psr7\Factory\Psr17Factory::class,
Psr\Http\Message\StreamFactoryInterface::class => Nyholm\Psr7\Factory\Psr17Factory::class,
],
'factories' => [
{{invokerPackage}}\ApiClient::class => {{invokerPackage}}\ApiClientFactory::class,

Articus\DataTransfer\Service::class => Articus\DataTransfer\Factory::class,
Articus\DataTransfer\MetadataProvider\PhpAttribute::class => Articus\DataTransfer\MetadataProvider\Factory\PhpAttribute::class,
Articus\DataTransfer\Strategy\PluginManager::class => Articus\DataTransfer\Strategy\Factory\PluginManager::class,
Articus\DataTransfer\Validator\PluginManager::class => Articus\DataTransfer\Validator\Factory\PluginManager::class,
Laminas\Validator\ValidatorPluginManager::class => Laminas\Validator\ValidatorPluginManagerFactory::class,
Articus\DataTransfer\Options::DEFAULT_STRATEGY_PLUGIN_MANAGER => [Articus\PluginManager\Factory\Chain::class, 'app_dt_strategy_manager_chain'],
'oas_dt_strategy_manager' => OpenAPIGenerator\Common\Strategy\Factory\PluginManager::class,
'app_dt_strategy_manager' => Articus\DataTransfer\Strategy\Factory\SimplePluginManager::class,
Articus\DataTransfer\Options::DEFAULT_VALIDATOR_PLUGIN_MANAGER => [Articus\PluginManager\Factory\Chain::class, 'app_dt_validator_manager_chain'],
'oas_dt_validator_manager' => OpenAPIGenerator\Common\Validator\Factory\PluginManager::class,
'app_dt_validator_manager' => Articus\DataTransfer\Validator\Factory\SimplePluginManager::class,

OpenAPIGenerator\APIClient\SecurityProvider\PluginManager::class => OpenAPIGenerator\APIClient\SecurityProvider\Factory\PluginManager::class,
OpenAPIGenerator\APIClient\BodyCoder\PluginManager::class => OpenAPIGenerator\APIClient\BodyCoder\Factory\PluginManager::class,
OpenAPIGenerator\APIClient\ApiClientOptions::DEFAULT_BODY_CODER_PLUGIN_MANAGER => OpenAPIGenerator\APIClient\BodyCoder\Factory\PluginManager::class,
OpenAPIGenerator\APIClient\ApiClientOptions::DEFAULT_SECURITY_PROVIDER_PLUGIN_MANAGER => OpenAPIGenerator\APIClient\SecurityProvider\Factory\PluginManager::class,

Psr\Http\Client\ClientInterface::class => function (Psr\Container\ContainerInterface $container)
{
Expand All @@ -64,34 +67,17 @@ $dependencies = [
$config = [
'dependencies' => $dependencies,

//Configure DataTransfer library
Articus\DataTransfer\Strategy\PluginManager::class => [
'invokables' => [
'QueryStringScalar' => OpenAPIGenerator\Common\Strategy\QueryStringScalar::class,
'QueryStringScalarArray' => OpenAPIGenerator\Common\Strategy\QueryStringScalarArray::class,
//Configure DataTransfer library: add pack of extra strategies and pack of extra validators
'app_dt_strategy_manager_chain' => [
'managers' => [
'oas_dt_strategy_manager',
'app_dt_strategy_manager',
],
'factories' => [
'Date' => OpenAPIGenerator\Common\Strategy\Factory\ImmutableDate::class,
'DateTime' => OpenAPIGenerator\Common\Strategy\Factory\ImmutableDateTime::class,
'ObjectList' => OpenAPIGenerator\Common\Strategy\Factory\NoArgObjectList::class,
'ObjectMap' => OpenAPIGenerator\Common\Strategy\Factory\NoArgObjectMap::class,
'ScalarList' => OpenAPIGenerator\Common\Strategy\Factory\ScalarList::class,
'ScalarMap' => OpenAPIGenerator\Common\Strategy\Factory\ScalarMap::class,
]
],
Articus\DataTransfer\Validator\PluginManager::class => [
'invokables' => [
'Scalar' => OpenAPIGenerator\Common\Validator\Scalar::class,
'QueryStringScalar' => OpenAPIGenerator\Common\Validator\QueryStringScalar::class,
'QueryStringScalarArray' => OpenAPIGenerator\Common\Validator\QueryStringScalarArray::class,
],
'abstract_factories' => [
Articus\DataTransfer\Validator\Factory\Laminas::class,
],
],
'validators' => [
'invokables' => [
'Count' => Laminas\Validator\IsCountable::class,
'app_dt_validator_manager_chain' => [
'managers' => [
'oas_dt_validator_manager',
'app_dt_validator_manager',
],
],

Expand All @@ -101,19 +87,19 @@ $config = [
],

//Register body coders for used content types here
OpenAPIGenerator\APIClient\BodyCoder\PluginManager::class => [
OpenAPIGenerator\APIClient\ApiClientOptions::DEFAULT_BODY_CODER_PLUGIN_MANAGER => [
'factories' => [
//'another/mime-type' => AnotherMimeTypeBodyCoder::class
],
],

//Register security providers for used security schemes here
OpenAPIGenerator\APIClient\SecurityProvider\PluginManager::class => [
OpenAPIGenerator\APIClient\ApiClientOptions::DEFAULT_SECURITY_PROVIDER_PLUGIN_MANAGER => [
'factories' => [
//'another-security-scheme' => AnotherSecuritySchemeProvider::class,
],
'aliases' => [
//'custom-name-for-htt-bearer' => OpenAPIGenerator\APIClient\SecurityProvider\HttpBearer::class,
//'custom-name-for-http-bearer' => OpenAPIGenerator\APIClient\SecurityProvider\HttpBearer::class,
],
],
];
Expand All @@ -126,10 +112,10 @@ $client = $container->get({{invokerPackage}}\ApiClient::class);
//... and now you can use client methods to call API operations :)

//And one more sample: how to set token for HTTP Bearer authentication
/** @var OpenAPIGenerator\APIClient\SecurityProvider\PluginManager $securityProviders */
$securityProviders = $container->get(OpenAPIGenerator\APIClient\SecurityProvider\PluginManager::class);
/** @var Articus\PluginManager\PluginManagerInterface $securityProviders */
$securityProviders = $container->get(OpenAPIGenerator\APIClient\ApiClientOptions::DEFAULT_SECURITY_PROVIDER_PLUGIN_MANAGER);
/** @var OpenAPIGenerator\APIClient\SecurityProvider\HttpBearer $httpBearer */
$httpBearer = $securityProviders->get(OpenAPIGenerator\APIClient\SecurityProvider\HttpBearer::class);
$httpBearer = $securityProviders(OpenAPIGenerator\APIClient\SecurityProvider\HttpBearer::class, []);
$httpBearer->setToken('some-token');

```
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
* @param {{dataType}} $requestContent
{{/bodyParam}}
{{#hasAuthMethods}}
* @param iterable|string[][] $security
* @param iterable<string, string[]> $security
{{/hasAuthMethods}}
{{#hasConsumes}}
* @param string $requestMediaType
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
{
"name": "{{#lambda.lowercase}}{{gitUserId}}/{{gitRepoId}}{{/lambda.lowercase}}",
"description": "{{description}}",
"version": "{{artifactVersion}}",
"type": "library",
"keywords": [
"openapi",
"php",
Expand All @@ -17,23 +15,24 @@
"homepage": "{{{developerOrganizationUrl}}}"
}
],
"version": "{{artifactVersion}}",
"type": "library",
"require": {
"php": "^8.0",
"articus/data-transfer": "^0.5",
"articus/openapi-generator-common": "^0.2",
"articus/openapi-generator-apiclient": "^0.1",
"php": "^8.1",
"articus/data-transfer": "^0.6",
"articus/openapi-generator-common": "^0.3",
"articus/openapi-generator-apiclient": "^0.2",
"psr/simple-cache": "^1.0",
"laminas/laminas-stdlib": "^3.2",
"laminas/laminas-validator": "^2.13"
"laminas/laminas-stdlib": "^3.18"
},
"autoload": {
"psr-4": {
"": "{{srcBasePath}}/"
}
},
"require-dev": {
"laminas/laminas-servicemanager": "^3.6",
"laminas/laminas-diactoros": "^2.6",
"symfony/http-client": "^5.3"
"laminas/laminas-servicemanager": "^3.22",
"nyholm/psr7": "^1.8",
"symfony/http-client": "^6.4 || ^7.0"
}
}
Loading

0 comments on commit 4d64f9b

Please sign in to comment.