[php-mezzio-ph] PHP 8 support (#9445)

* Huge update for php-mezzio-ph generator:
- proper container support for data types
- support for query parameter references and query parameter schema references
- dependency update (PHP 7.3+, PathHandler 0.7+, DataTransfer 0.5+)

* Sample regeneration after rebasing for php-mezzio-ph

* - added custom CLI option for php-mezzio-ph to generate code using modern PHP syntax
- removed obsolete php-mezzio-ph samples in samples/openapi3/server/petstore/php-mezzio-ph

* - fixes for JavaDoc declarations that seems to break CI

* - fix for outdated sample file
This commit is contained in:
Arthur Mogliev 2021-05-21 10:40:38 +04:00 committed by GitHub
parent 4948ce78ed
commit ab6d66147b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
190 changed files with 2970 additions and 1224 deletions

1
.gitignore vendored
View File

@ -177,7 +177,6 @@ samples/client/petstore/python-tornado/.venv/
# PHP
samples/client/petstore/php/OpenAPIClient-php/composer.lock
samples/openapi3/server/petstore/php-symfony/SymfonyBundle-php/composer.lock
samples/openapi3/server/petstore/php-mezzio-ph/composer.lock
samples/server/petstore/php-laravel/lib/composer.lock
samples/server/petstore/php-lumen/lib/composer.lock
samples/server/petstore/php-slim4/composer.lock

View File

@ -0,0 +1,6 @@
generatorName: php-mezzio-ph
outputDir: samples/server/petstore/php-mezzio-ph-modern
inputSpec: modules/openapi-generator/src/test/resources/3_0/petstore.yaml
templateDir: modules/openapi-generator/src/main/resources/php-mezzio-ph-modern
additionalProperties:
modern: "true"

View File

@ -15,6 +15,7 @@ These options may be applied as additional-properties (cli) or configOptions (pl
|invokerPackage|The main namespace to use for all classes. e.g. Yay\Pets| |null|
|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|
|modelPackage|package for generated models| |null|
|modern|use modern language features (generated code will require PHP 8.0)| |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|

View File

@ -21,9 +21,13 @@ import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.Operation;
import io.swagger.v3.oas.models.PathItem;
import io.swagger.v3.oas.models.PathItem.HttpMethod;
import io.swagger.v3.oas.models.Paths;
import io.swagger.v3.oas.models.media.*;
import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.oas.models.parameters.QueryParameter;
import io.swagger.v3.oas.models.parameters.RequestBody;
import io.swagger.v3.oas.models.responses.ApiResponse;
import io.swagger.v3.oas.models.responses.ApiResponses;
import org.openapitools.codegen.*;
import org.openapitools.codegen.meta.features.*;
import org.openapitools.codegen.utils.ModelUtils;
@ -35,12 +39,17 @@ import java.util.*;
public class PhpMezzioPathHandlerServerCodegen extends AbstractPhpCodegen {
private final Logger LOGGER = LoggerFactory.getLogger(PhpMezzioPathHandlerServerCodegen.class);
// TODO: Rename to x- prefixed vendor extensions, per specification.
// Custom generator option names
public static final String OPT_MODERN = "modern";
// Internal vendor extension names for extra template data that should not be set in specification
public static final String VEN_FROM_QUERY = "internal.ze-ph.fromQuery";
public static final String VEN_COLLECTION_FORMAT = "internal.ze-ph.collectionFormat";
public static final String VEN_QUERY_DATA_TYPE = "internal.ze-ph.queryDataType";
public static final String VEN_HAS_QUERY_DATA = "internal.ze-ph.hasQueryData";
public static final String VEN_FROM_CONTAINER = "internal.ze-ph.fromContainer";
public static final String VEN_CONTAINER_DATA_TYPE = "internal.ze-ph.containerDataType";
private boolean useModernSyntax = false;
@Override
public CodegenType getTag() {
@ -85,6 +94,8 @@ public class PhpMezzioPathHandlerServerCodegen extends AbstractPhpCodegen {
modelDirName = "DTO";
apiPackage = invokerPackage + "\\" + apiDirName;
modelPackage = invokerPackage + "\\" + modelDirName;
//"Api" classes have dedicated namespace so there is no need to add non-empty suffix by default
apiNameSuffix = "";
apiTestTemplateFiles.clear();
modelTestTemplateFiles.clear();
@ -103,6 +114,17 @@ public class PhpMezzioPathHandlerServerCodegen extends AbstractPhpCodegen {
supportingFiles.add(new SupportingFile("InternalServerError.php.mustache", srcBasePath + File.separator + "Middleware", "InternalServerError.php"));
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);
}
@Override
public void processOpts() {
super.processOpts();
if (additionalProperties.containsKey(OPT_MODERN)) {
embeddedTemplateDir = templateDir = "php-mezzio-ph-modern";
useModernSyntax = true;
}
}
/**
@ -136,29 +158,31 @@ public class PhpMezzioPathHandlerServerCodegen extends AbstractPhpCodegen {
}
}
/**
* Return the file name of the Api Test
*
* @param name the file name of the Api
* @return the file name of the Api
*/
@Override
public String toApiFilename(String name) {
return toApiName(name);
}
/**
* Output the API (class) name (capitalized) ending with "Api"
* Return DefaultApi if name is empty
*
* @param name the name of the Api
* @return capitalized Api name ending with "Api"
*/
@Override
public String toApiName(String name) {
//Remove }
name = name.replaceAll("[\\}]", "");
return super.toModelName(name);
return super.toApiName(toModelName(name));
}
@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))) {
result = "array";
} else {
result = super.getTypeDeclaration(p);
}
return result;
}
@Override
public void preprocessOpenAPI(OpenAPI openAPI) {
super.preprocessOpenAPI(openAPI);
generateParameterSchemas(openAPI);
generateContainerSchemas(openAPI);
}
/**
@ -166,10 +190,7 @@ public class PhpMezzioPathHandlerServerCodegen extends AbstractPhpCodegen {
*
* @param openAPI OpenAPI object
*/
@Override
public void preprocessOpenAPI(OpenAPI openAPI) {
super.preprocessOpenAPI(openAPI);
protected void generateParameterSchemas(OpenAPI openAPI) {
Map<String, PathItem> paths = openAPI.getPaths();
if (paths != null) {
for (String pathname : paths.keySet()) {
@ -178,34 +199,34 @@ public class PhpMezzioPathHandlerServerCodegen extends AbstractPhpCodegen {
if (operationMap != null) {
for (HttpMethod method : operationMap.keySet()) {
Operation operation = operationMap.get(method);
Map<String, Schema> schemas = new HashMap<>();
Map<String, Schema> propertySchemas = new HashMap<>();
if (operation == null || operation.getParameters() == null) {
continue;
}
List<String> requiredProperties = new ArrayList<>();
for (Parameter parameter : operation.getParameters()) {
Schema schema = convertParameterToSchema(parameter);
if (schema != null) {
schemas.put(schema.getName(), schema);
if (Boolean.TRUE.equals(parameter.getRequired())) {
requiredProperties.add(schema.getName());
Parameter referencedParameter = ModelUtils.getReferencedParameter(openAPI, parameter);
Schema propertySchema = convertParameterToSchema(openAPI, referencedParameter);
if (propertySchema != null) {
propertySchemas.put(propertySchema.getName(), propertySchema);
if (Boolean.TRUE.equals(referencedParameter.getRequired())) {
requiredProperties.add(propertySchema.getName());
}
}
}
if (!schemas.isEmpty()) {
ObjectSchema model = new ObjectSchema();
if (!propertySchemas.isEmpty()) {
ObjectSchema schema = new ObjectSchema();
String operationId = getOrGenerateOperationId(operation, pathname, method.name());
model.setDescription("Query parameters for " + operationId);
model.setProperties(schemas);
model.setRequired(requiredProperties);
//Add internal extension directly, because addExtension filters extension names
addInternalExtensionToSchema(model, VEN_FROM_QUERY, Boolean.TRUE);
String definitionName = generateUniqueDefinitionName(operationId + "QueryData", openAPI);
openAPI.getComponents().addSchemas(definitionName, model);
String definitionModel = "\\" + modelPackage + "\\" + toModelName(definitionName);
addInternalExtensionToOperation(operation, VEN_QUERY_DATA_TYPE, definitionModel);
schema.setDescription("Query parameters for " + operationId);
schema.setProperties(propertySchemas);
schema.setRequired(requiredProperties);
addInternalExtensionToSchema(schema, VEN_FROM_QUERY, Boolean.TRUE);
String schemaName = generateUniqueSchemaName(openAPI, operationId + "QueryData");
openAPI.getComponents().addSchemas(schemaName, schema);
String schemaDataType = getTypeDeclaration(toModelName(schemaName));
addInternalExtensionToOperation(operation, VEN_QUERY_DATA_TYPE, schemaDataType);
addInternalExtensionToOperation(operation, VEN_HAS_QUERY_DATA, Boolean.TRUE);
}
}
@ -214,17 +235,18 @@ public class PhpMezzioPathHandlerServerCodegen extends AbstractPhpCodegen {
}
}
protected Schema convertParameterToSchema(Parameter parameter) {
protected Schema convertParameterToSchema(OpenAPI openAPI, Parameter parameter) {
Schema property = null;
if (parameter instanceof QueryParameter) {
QueryParameter queryParameter = (QueryParameter) parameter;
Schema parameterSchema = ModelUtils.getReferencedSchema(openAPI, queryParameter.getSchema());
// array
if (ModelUtils.isArraySchema(queryParameter.getSchema())) {
Schema inner = ((ArraySchema) queryParameter.getSchema()).getItems();
if (ModelUtils.isArraySchema(parameterSchema)) {
Schema itemSchema = ((ArraySchema) parameterSchema).getItems();
ArraySchema arraySchema = new ArraySchema();
arraySchema.setMinItems(queryParameter.getSchema().getMinItems());
arraySchema.setMaxItems(queryParameter.getSchema().getMaxItems());
arraySchema.setItems(inner);
arraySchema.setMinItems(parameterSchema.getMinItems());
arraySchema.setMaxItems(parameterSchema.getMaxItems());
arraySchema.setItems(itemSchema);
String collectionFormat = getCollectionFormat(queryParameter);
if (collectionFormat == null) {
collectionFormat = "csv";
@ -232,25 +254,25 @@ public class PhpMezzioPathHandlerServerCodegen extends AbstractPhpCodegen {
addInternalExtensionToSchema(arraySchema, VEN_COLLECTION_FORMAT, collectionFormat);
property = arraySchema;
} else { // non-array e.g. string, integer
switch (queryParameter.getSchema().getType()) {
switch (parameterSchema.getType()) {
case "string":
StringSchema stringSchema = new StringSchema();
stringSchema.setMinLength(queryParameter.getSchema().getMinLength());
stringSchema.setMaxLength(queryParameter.getSchema().getMaxLength());
stringSchema.setPattern(queryParameter.getSchema().getPattern());
stringSchema.setEnum(queryParameter.getSchema().getEnum());
stringSchema.setMinLength(parameterSchema.getMinLength());
stringSchema.setMaxLength(parameterSchema.getMaxLength());
stringSchema.setPattern(parameterSchema.getPattern());
stringSchema.setEnum(parameterSchema.getEnum());
property = stringSchema;
break;
case "integer":
IntegerSchema integerSchema = new IntegerSchema();
integerSchema.setMinimum(queryParameter.getSchema().getMinimum());
integerSchema.setMaximum(queryParameter.getSchema().getMaximum());
integerSchema.setMinimum(parameterSchema.getMinimum());
integerSchema.setMaximum(parameterSchema.getMaximum());
property = integerSchema;
break;
case "number":
NumberSchema floatSchema = new NumberSchema();
floatSchema.setMinimum(queryParameter.getSchema().getMinimum());
floatSchema.setMaximum(queryParameter.getSchema().getMaximum());
floatSchema.setMinimum(parameterSchema.getMinimum());
floatSchema.setMaximum(parameterSchema.getMaximum());
property = floatSchema;
break;
case "boolean":
@ -264,6 +286,7 @@ public class PhpMezzioPathHandlerServerCodegen extends AbstractPhpCodegen {
break;
}
}
if (property != null) {
property.setName(queryParameter.getName());
property.setDescription(queryParameter.getDescription());
@ -289,7 +312,7 @@ public class PhpMezzioPathHandlerServerCodegen extends AbstractPhpCodegen {
operation.getExtensions().put(name, value);
}
protected String generateUniqueDefinitionName(String name, OpenAPI openAPI) {
protected String generateUniqueSchemaName(OpenAPI openAPI, String name) {
String result = name;
if (openAPI.getComponents().getSchemas() != null) {
int count = 1;
@ -301,6 +324,90 @@ public class PhpMezzioPathHandlerServerCodegen extends AbstractPhpCodegen {
return result;
}
/**
* Generate additional model definitions for containers in whole specification
*
* @param openAPI OpenAPI object
*/
protected void generateContainerSchemas(OpenAPI openAPI) {
Paths paths = openAPI.getPaths();
for (String pathName : paths.keySet()) {
for (Operation operation : paths.get(pathName).readOperations()) {
List<Parameter> parameters = operation.getParameters();
if (parameters != null) {
for (Parameter parameter : parameters) {
generateContainerSchemas(openAPI, ModelUtils.getReferencedParameter(openAPI, parameter).getSchema());
}
}
RequestBody requestBody = ModelUtils.getReferencedRequestBody(openAPI, operation.getRequestBody());
if (requestBody != null) {
Content requestBodyContent = requestBody.getContent();
if (requestBodyContent != null) {
for (String mediaTypeName : requestBodyContent.keySet()) {
generateContainerSchemas(openAPI, requestBodyContent.get(mediaTypeName).getSchema());
}
}
}
ApiResponses responses = operation.getResponses();
for (String responseCode : responses.keySet()) {
ApiResponse response = ModelUtils.getReferencedApiResponse(openAPI, responses.get(responseCode));
Content responseContent = response.getContent();
if (responseContent != null) {
for (String mediaTypeName : responseContent.keySet()) {
generateContainerSchemas(openAPI, responseContent.get(mediaTypeName).getSchema());
}
}
}
}
}
}
/**
* Generate additional model definitions for containers in specified schema
*
* @param openAPI OpenAPI object
* @param schema OAS schema to process
*/
protected void generateContainerSchemas(OpenAPI openAPI, Schema schema) {
if (schema != null) {
//Dereference schema
schema = ModelUtils.getReferencedSchema(openAPI, schema);
Boolean isContainer = Boolean.FALSE;
if (ModelUtils.isObjectSchema(schema)) {
//Recursively process all schemas of object properties
Map<String, Schema> properties = schema.getProperties();
if (properties != null) {
for (String propertyName: properties.keySet()) {
generateContainerSchemas(openAPI, properties.get(propertyName));
}
}
} else if (ModelUtils.isArraySchema(schema)) {
//Recursively process schema of array items
generateContainerSchemas(openAPI, ((ArraySchema) schema).getItems());
isContainer = Boolean.TRUE;
} else if (ModelUtils.isMapSchema(schema)) {
//Recursively process schema of map items
Object itemSchema = schema.getAdditionalProperties();
if (itemSchema instanceof Schema) {
generateContainerSchemas(openAPI, (Schema) itemSchema);
}
isContainer = Boolean.TRUE;
}
if (isContainer) {
//Generate special component schema for container
String containerSchemaName = generateUniqueSchemaName(openAPI, "Collection");
Schema containerSchema = new ObjectSchema();
containerSchema.addProperties("inner", schema);
addInternalExtensionToSchema(containerSchema, VEN_FROM_CONTAINER, Boolean.TRUE);
openAPI.getComponents().addSchemas(containerSchemaName, containerSchema);
String containerDataType = getTypeDeclaration(toModelName(containerSchemaName));
addInternalExtensionToSchema(schema, VEN_CONTAINER_DATA_TYPE, containerDataType);
}
}
}
@Override
public Map<String, Object> postProcessOperationsWithModels(Map<String, Object> objs, List<Object> allModels) {
objs = super.postProcessOperationsWithModels(objs, allModels);

View File

@ -0,0 +1,53 @@
<?php
declare(strict_types=1);
namespace {{invokerPackage}};
use {{invokerPackage}}\Middleware;
use Interop\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Mezzio\Application;
use Mezzio\Handler\NotFoundHandler;
use Mezzio\MiddlewareFactory;
use Mezzio\Router\Middleware\DispatchMiddleware;
use Mezzio\Router\Middleware\MethodNotAllowedMiddleware;
use Mezzio\Router\Middleware\RouteMiddleware;
use Mezzio\Router\RouteCollector;
use Laminas\HttpHandlerRunner\Emitter\EmitterInterface;
use Laminas\HttpHandlerRunner\RequestHandlerRunner;
use Laminas\ServiceManager\Factory\FactoryInterface;
use Laminas\Stratigility\MiddlewarePipe;
class Factory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null): Application
{
$errorMiddleware = self::getErrorMiddleware($container);
$pipeline = new MiddlewarePipe();
$runner = new RequestHandlerRunner(
$pipeline,
$container->get(EmitterInterface::class),
$container->get(ServerRequestInterface::class),
static fn(\Throwable $error): ResponseInterface => $errorMiddleware->handleError($error)
);
$application = new Application(
$container->get(MiddlewareFactory::class),
$pipeline,
$container->get(RouteCollector::class),
$runner
);
$application->pipe($errorMiddleware);
$application->pipe(RouteMiddleware::class);
$application->pipe(MethodNotAllowedMiddleware::class);
$application->pipe(DispatchMiddleware::class);
$application->pipe(NotFoundHandler::class);
return $application;
}
protected static function getErrorMiddleware(ContainerInterface $container): Middleware\InternalServerError
{
return $container->get(Middleware\InternalServerError::class);
}
}

View File

@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
namespace {{invokerPackage}}\Middleware;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Psr\Http\Server\MiddlewareInterface;
use Psr\Http\Server\RequestHandlerInterface;
use Laminas\Stdlib\ErrorHandler;
class InternalServerError implements MiddlewareInterface
{
public function __construct(protected \Closure $responseGenerator)
{
}
/**
* @inheritdoc
*/
public function process(ServerRequestInterface $request, RequestHandlerInterface $handler): ResponseInterface
{
$result = null;
try {
ErrorHandler::start();
$result = $handler->handle($request);
ErrorHandler::stop(true);
}
catch (\Throwable $error) {
$result = $this->handleError($error);
}
return $result;
}
public function handleError(\Throwable $error): ResponseInterface
{
\error_log((string)$error);
return $this->generateEmptyResponse()->withStatus(500, 'Internal server error');
}
protected function generateEmptyResponse(): ResponseInterface
{
return ($this->responseGenerator)();
}
}

View File

@ -0,0 +1,34 @@
# OpenAPI generated server
Generated by the [OpenAPI Generator](https://openapi-generator.tech) project.
## Overview
This server stub aims to provide light, yet comprehensive structure for your API project using:
- PHP: >=8.0
- [Laminas Mezzio](https://docs.mezzio.dev/mezzio/): >=3.3
- [Path Handler](https://github.com/Articus/PathHandler): >=0.7
## How to use
All you have to do to start development is:
- install dependencies via [Composer](https://getcomposer.org/) (small note: [ext-yaml](https://pecl.php.net/package/yaml) is used only for configuration parsing, so if you want to drop this dependency, simply adjust `./application/container.php`)
- create cache folder: `mkdir -p ./data/cache` (you will need it later for configuration and metadata caches - check comments in `./application/config.yml`)
- start PHP development server: `php -S 0.0.0.0:8080 -t ./public` (or any other SAPI you prefer, just make sure that you configure webroot to `./public` and rewrites to `./public/index.php`)
After that you should be able to call all methods from your API spec. Most of the negative scenarios should be handled:
- `404 Not found` for unknown routes
- `406 Not acceptable` for invalid `Accept` header
- `415 Unsupported media type` for invalid `Content-Type` header
- `400 Malformed JSON` for unparsable JSON body
- `422 Unprocessable entity` for parsable JSON body that fails validation
But for obvious reason you will not get any `200 OK`, only `501 Not implemented`. So your next steps are:
- check all TODOs left in the stub code where generator was not smart enough and could not guarantee correct implementation
- implement your API security mechanism (either special attribute or separate middleware) - generator does not do anything about it yet
- implement your handlers - the most tricky part :)
## Enjoy!
Hopefully this stub will reduce the amount of boilerplate code you have to write manually. If you have any suggestions or questions about `php-mezzio-ph` generator, feel free to create issue either in [Path Handler repository](https://github.com/Articus/PathHandler/issues) or in [OpenAPI Generator repository](https://openapi-generator.tech/issues).

View File

@ -0,0 +1,73 @@
<?php
declare(strict_types=1);
namespace {{package}};
use Articus\PathHandler\PhpAttribute as PHA;
use Articus\PathHandler\Consumer as PHConsumer;
use Articus\PathHandler\Producer as PHProducer;
use Articus\PathHandler\Attribute as PHAttribute;
use Articus\PathHandler\Exception as PHException;
use Psr\Http\Message\ServerRequestInterface;
{{#operations}}
{{#description}}
/**
* {{&description}}
*/
{{/description}}
#[PHA\Route("{{pathPattern}}")]
class {{classname}}
{
{{#operation}}
/**
{{#summary}}
* {{summary}}
{{/summary}}
{{#description}}
* {{description}}
{{/description}}
*/
#[PHA\{{httpMethod}}]
{{#vendorExtensions}}
{{#internal.ze-ph.hasQueryData}}
#[PHA\Attribute(PHAttribute\Transfer::class, [
"type" => {{internal.ze-ph.queryDataType}}::class,
"objectAttr" => "queryData",
"source" => PHAttribute\Transfer::SOURCE_GET
])]
{{/internal.ze-ph.hasQueryData}}
{{/vendorExtensions}}
{{#bodyParam}}
{{#consumes}}
// TODO check if consumer is valid, if it has correct priority and if it can be moved to class annotation
#[PHA\Consumer("{{{mediaType}}}", PHConsumer\Json::class)]
{{/consumes}}
{{^isPrimitiveType}}
#[PHA\Attribute(PHAttribute\Transfer::class, ["type" => {{dataType}}::class, "objectAttr" => "bodyData"])]
{{/isPrimitiveType}}
{{/bodyParam}}
{{#produces}}
// TODO check if producer is valid, if it has correct priority and if it can be moved to class annotation
#[PHA\Producer("{{{mediaType}}}", PHProducer\Transfer::class)]
{{/produces}}
public function {{operationId}}(ServerRequestInterface $request){{#returnType}}: {{returnType}}{{/returnType}}
{
//TODO implement method
{{#vendorExtensions}}
{{#internal.ze-ph.hasQueryData}}
/** @var {{internal.ze-ph.queryDataType}} $queryData */
$queryData = $request->getAttribute("queryData");
{{/internal.ze-ph.hasQueryData}}
{{/vendorExtensions}}
{{#bodyParam}}
{{^isPrimitiveType}}
/** @var {{dataType}} $bodyData */
$bodyData = $request->getAttribute("bodyData");
{{/isPrimitiveType}}
{{/bodyParam}}
throw new PHException\HttpCode(501, "Not implemented");
}
{{/operation}}
}
{{/operations}}

View File

@ -0,0 +1,26 @@
{
"name": "{{#lambda.lowercase}}{{gitUserId}}/{{gitRepoId}}{{/lambda.lowercase}}",
"description": "{{description}}",
"license": "unlicense",
"version": "{{artifactVersion}}",
"type": "project",
"require": {
"php": "^8.0",
"ext-yaml": "^2.2",
"mezzio/mezzio": "^3.3",
"laminas/laminas-diactoros": "^2.5",
"articus/path-handler": "^0.7",
"articus/data-transfer": "^0.5",
"articus/openapi-generator-common": "^0.2",
"psr/simple-cache": "^1.0",
"laminas/laminas-config": "^3.4",
"laminas/laminas-stdlib": "^3.3",
"laminas/laminas-validator": "^2.14",
"nikic/fast-route": "^1.3"
},
"autoload": {
"psr-4": {
"": "src/"
}
}
}

View File

@ -9,12 +9,13 @@
# router:
# cache:
# directory: ./data/cache/PathHandler
# #Enable handler metadata cache
# metadata:
# cache:
# directory: ./data/cache/PathHandler
#Enable handler metadata cache
#Articus\PathHandler\MetadataProvider\PhpAttribute:
# cache:
# directory: ./data/cache/PathHandler
#Enable data transfer metadata cache for DTOs
#Articus\DataTransfer\MetadataProvider\Annotation:
#Articus\DataTransfer\MetadataProvider\PhpAttribute:
# cache:
# directory: ./data/cache/DataTransfer

View File

@ -6,9 +6,6 @@ use Laminas\Config\Factory as ConfigFactory;
//Use Composer autoload that includes code both from ../src and ../vendor
require __DIR__ . '/../vendor/autoload.php';
//Register Doctrine annotation autoload
\Doctrine\Common\Annotations\AnnotationRegistry::registerLoader('class_exists');
//Path to file for caching full configuration
const CONFIG_CACHE_PATH = __DIR__ . '/../data/cache/config.php';

View File

@ -0,0 +1,34 @@
dependencies:
factories:
Articus\DataTransfer\Service: Articus\DataTransfer\Factory
Articus\DataTransfer\MetadataProvider\PhpAttribute: Articus\DataTransfer\MetadataProvider\Factory\PhpAttribute
Articus\DataTransfer\Strategy\PluginManager: Articus\DataTransfer\Strategy\Factory\PluginManager
Articus\DataTransfer\Validator\PluginManager: Articus\DataTransfer\Validator\Factory\PluginManager
Laminas\Validator\ValidatorPluginManager: Laminas\Validator\ValidatorPluginManagerFactory
aliases:
Articus\DataTransfer\ClassMetadataProviderInterface: Articus\DataTransfer\MetadataProvider\PhpAttribute
Articus\DataTransfer\FieldMetadataProviderInterface: Articus\DataTransfer\MetadataProvider\PhpAttribute
Articus\DataTransfer\Strategy\PluginManager:
invokables:
QueryStringScalar: OpenAPIGenerator\Common\Strategy\QueryStringScalar
QueryStringScalarArray: OpenAPIGenerator\Common\Strategy\QueryStringScalarArray
factories:
Date: OpenAPIGenerator\Common\Strategy\Factory\MutableDate
DateTime: OpenAPIGenerator\Common\Strategy\Factory\MutableDateTime
ObjectList: OpenAPIGenerator\Common\Strategy\Factory\NoArgObjectList
ObjectMap: OpenAPIGenerator\Common\Strategy\Factory\NoArgObjectMap
ScalarList: OpenAPIGenerator\Common\Strategy\Factory\ScalarList
ScalarMap: OpenAPIGenerator\Common\Strategy\Factory\ScalarMap
Articus\DataTransfer\Validator\PluginManager:
invokables:
Scalar: OpenAPIGenerator\Common\Validator\Scalar
QueryStringScalar: OpenAPIGenerator\Common\Validator\QueryStringScalar
QueryStringScalarArray: OpenAPIGenerator\Common\Validator\QueryStringScalarArray
abstract_factories:
- Articus\DataTransfer\Validator\Factory\Laminas
validators:
invokables:
Count: Laminas\Validator\IsCountable

View File

@ -0,0 +1,8 @@
{{#items
}}{{^isContainer
}}{{#isPrimitiveType}}"{{dataType}}"{{/isPrimitiveType
}}{{^isPrimitiveType}}{{dataType}}::class{{/isPrimitiveType
}}{{/isContainer
}}{{#isContainer
}}{{dataType}}::class{{/isContainer
}}{{/items}}

View File

@ -0,0 +1,8 @@
{{#additionalProperties
}}{{^isContainer
}}{{#isPrimitiveType}}"{{dataType}}"{{/isPrimitiveType
}}{{^isPrimitiveType}}{{dataType}}::class{{/isPrimitiveType
}}{{/isContainer
}}{{#isContainer
}}{{dataType}}::class{{/isContainer
}}{{/additionalProperties}}

View File

@ -0,0 +1,13 @@
<?php
declare(strict_types=1);
{{#models}}{{#model}}
namespace {{package}};
use Articus\DataTransfer\PhpAttribute as DTA;
{{#vendorExtensions
}}{{#internal.ze-ph.fromContainer}}{{>model_container}}{{/internal.ze-ph.fromContainer
}}{{^internal.ze-ph.fromContainer}}{{>model_object}}{{/internal.ze-ph.fromContainer
}}{{/vendorExtensions
}}{{^vendorExtensions}}{{>model_object}}{{/vendorExtensions
}}{{/model}}{{/models}}

View File

@ -0,0 +1,57 @@
{{#vars
}}{{#isArray
}}#[DTA\Strategy("{{#isPrimitiveType}}ScalarList{{/isPrimitiveType}}{{^isPrimitiveType}}ObjectList{{/isPrimitiveType}}", ["type" => {{>list_item_type}}])]
{{#minItems}}{{^maxItems
}}#[DTA\Validator("Count", ["min" => {{minItems}}], blocker: true)]
{{/maxItems}}{{/minItems
}}{{^minItems}}{{#maxItems
}}#[DTA\Validator("Count", ["max" => {{maxItems}}], blocker: true)]
{{/maxItems}}{{/minItems
}}{{#minItems}}{{#maxItems
}}#[DTA\Validator("Count", ["min" => {{minItems}}, "max" => {{maxItems}}], blocker: true)]
{{/maxItems}}{{/minItems
}}#[DTA\Validator("Collection", ["validators" => [
{{#isPrimitiveType
}} ["name" => "Scalar", "options" => ["type" => {{>list_item_type}}]]
{{/isPrimitiveType
}}{{#isDate
}} ["name" => "Date"]
{{/isDate
}}{{#isDateTime
}} ["name" => "Date", "options" => ["format" => \DateTime::RFC3339]]
{{/isDateTime
}}{{^isPrimitiveType}}{{^isDate}}{{^isDateTime
}} ["name" => "TypeCompliant", "options" => ["type" => {{>list_item_type}}]]
{{/isDateTime}}{{/isDate}}{{/isPrimitiveType
}}]])]
{{/isArray
}}{{#isMap
}}#[DTA\Strategy("{{#isPrimitiveType}}ScalarMap{{/isPrimitiveType}}{{^isPrimitiveType}}ObjectMap{{/isPrimitiveType}}", ["type" => {{>map_item_type}}])]
{{#minProperties}}{{^maxProperties
}}#[DTA\Validator("Count", ["min" => {{minProperties}}], blocker: true)]
{{/maxProperties}}{{/minProperties
}}{{^minProperties}}{{#maxProperties
}}#[DTA\Validator("Count", ["max" => {{maxProperties}}], blocker: true)]
{{/maxProperties}}{{/minProperties
}}{{#minProperties}}{{#maxProperties
}}#[DTA\Validator("Count", ["min" => {{minProperties}}, "max" => {{maxProperties}}], blocker: true)]
{{/maxProperties}}{{/minProperties
}}#[DTA\Validator("Collection", ["validators" => [
{{#isPrimitiveType
}} ["name" => "Scalar", "options" => ["type" => {{>map_item_type}}]]
{{/isPrimitiveType
}}{{#isDate
}} ["name" => "Date"]
{{/isDate
}}{{#isDateTime
}} ["name" => "Date", "options" => ["format" => \DateTime::RFC3339]]
{{/isDateTime
}}{{^isPrimitiveType}}{{^isDate}}{{^isDateTime
}} ["name" => "TypeCompliant", "options" => ["type" => {{>map_item_type}}]]
{{/isDateTime}}{{/isDate}}{{/isPrimitiveType
}}]])]
{{/isMap
}}{{/vars
}}class {{classname}} extends \ArrayObject
{
}

View File

@ -0,0 +1,45 @@
{{#isContainer
}} #[DTA\Strategy("Object", ["type" => {{internal.ze-ph.containerDataType}}::class])]
#[DTA\Validator("TypeCompliant", ["type" => {{internal.ze-ph.containerDataType}}::class])]
{{/isContainer
}}{{^isContainer
}}{{#isPrimitiveType
}} #[DTA\Validator("Scalar", ["type" => "{{dataType}}"])]
{{/isPrimitiveType
}}{{#isDate
}} #[DTA\Strategy("Date")]
#[DTA\Validator("Date")]
{{/isDate
}}{{#isDateTime
}} #[DTA\Strategy("DateTime")]
#[DTA\Validator("Date", ["format" => \DateTime::RFC3339])]
{{/isDateTime
}}{{^isPrimitiveType
}}{{^isDate
}}{{^isDateTime
}} #[DTA\Strategy("Object", ["type" => {{dataType}}::class])]
#[DTA\Validator("TypeCompliant", ["type" => {{dataType}}::class])]
{{/isDateTime
}}{{/isDate
}}{{/isPrimitiveType
}}{{/isContainer
}}{{#hasValidation
}}{{#minLength}}{{#maxLength
}} #[DTA\Validator("StringLength", ["min" => {{minLength}}, "max" => {{maxLength}}])]
{{/maxLength}}{{/minLength
}}{{^minLength}}{{#maxLength
}} #[DTA\Validator("StringLength", ["max" => {{maxLength}}])]
{{/maxLength}}{{/minLength
}}{{#minLength}}{{^maxLength
}} #[DTA\Validator("StringLength", ["min" => {{minLength}}])]
{{/maxLength}}{{/minLength
}}{{#minimum
}} #[DTA\Validator("GreaterThan", ["min" => {{minimum}}{{^exclusiveMinimum}}, "inclusive" => true{{/exclusiveMinimum}}])]
{{/minimum
}}{{#maximum
}} #[DTA\Validator("LessThan", ["max" => {{maximum}}{{^exclusiveMaximum}}, "inclusive" => true{{/exclusiveMaximum}}])]
{{/maximum
}}{{#pattern
}} #[DTA\Validator("Regex", ["pattern" => "{{{pattern}}}"])]
{{/pattern
}}{{/hasValidation}}

View File

@ -0,0 +1,23 @@
{{#description
}}/**
* {{description}}
*/
{{/description
}}class {{classname}}
{
{{#vars
}}{{#description
}} /**
* {{description}}
*/
{{/description
}} #[DTA\Data(field: "{{baseName}}"{{^required}}, nullable: true{{/required}})]
{{#vendorExtensions
}}{{#internal.ze-ph.fromQuery}}{{>model_query_var}}{{/internal.ze-ph.fromQuery
}}{{^internal.ze-ph.fromQuery}}{{>model_normal_var}}{{/internal.ze-ph.fromQuery
}}{{/vendorExtensions
}}{{^vendorExtensions}}{{>model_normal_var}}{{/vendorExtensions
}} public {{dataType}}|null ${{name}} = null;
{{/vars
}}}

View File

@ -0,0 +1,51 @@
{{#isArray
}}{{#isPrimitiveType
}} #[DTA\Strategy("QueryStringScalarArray", ["type" => {{>list_item_type}}, "format" => "{{internal.ze-ph.collectionFormat}}"])]
#[DTA\Validator("QueryStringScalarArray", ["type" => {{>list_item_type}}, "format" => "{{internal.ze-ph.collectionFormat}}"{{#minItems}}, "min_items" => {{minItems}}{{/minItems}}{{#maxItems}}, "max_items" => {{maxItems}}{{/maxItems}}])]
{{/isPrimitiveType
}}{{^isPrimitiveType
}} // TODO add validator(s) and strategy for list of {{>list_item_type}} and collection format {{internal.ze-ph.collectionFormat}} inside query string
{{/isPrimitiveType
}}{{/isArray
}}{{#isMap
}} // TODO add validator(s) and strategy for map of {{>map_item_type}} and collection format {{internal.ze-ph.collectionFormat}} inside query string
{{/isMap
}}{{^isContainer
}}{{#isPrimitiveType
}} #[DTA\Strategy("QueryStringScalar", ["type" => "{{dataType}}"])]
#[DTA\Validator("QueryStringScalar", ["type" => "{{dataType}}"])]
{{/isPrimitiveType
}}{{#isDate
}} #[DTA\Strategy("Date")]
#[DTA\Validator("Date")]
{{/isDate
}}{{#isDateTime
}} #[DTA\Strategy("DateTime")]
#[DTA\Validator("Date", ["format" => \DateTime::RFC3339])]
{{/isDateTime
}}{{^isPrimitiveType
}}{{^isDate}}{{^isDateTime
}} // TODO add validator(s) and strategy for {{dataType}} inside query string
{{/isDateTime}}{{/isDate
}}{{/isPrimitiveType
}}{{/isContainer
}}{{#hasValidation
}}{{#minLength}}{{#maxLength
}} #[DTA\Validator("StringLength", ["min" => {{minLength}}, "max" => {{maxLength}}])]
{{/maxLength}}{{/minLength
}}{{^minLength}}{{#maxLength
}} #[DTA\Validator("StringLength", ["max" => {{maxLength}}])]
{{/maxLength}}{{/minLength
}}{{#minLength}}{{^maxLength
}} #[DTA\Validator("StringLength", ["min" => {{minLength}}])]
{{/maxLength}}{{/minLength
}}{{#minimum
}} #[DTA\Validator("GreaterThan", ["min" => {{minimum}}{{^exclusiveMinimum}}, "inclusive" => true{{/exclusiveMinimum}}])]
{{/minimum
}}{{#maximum
}} #[DTA\Validator("LessThan", ["max" => {{maximum}}{{^exclusiveMaximum}}, "inclusive" => true{{/exclusiveMaximum}}])]
{{/maximum
}}{{#pattern
}} #[DTA\Validator("Regex", ["pattern" => "{{{pattern}}}"])]
{{/pattern
}}{{/hasValidation}}

View File

@ -0,0 +1,44 @@
dependencies:
factories:
Mezzio\Router\RouterInterface: Articus\PathHandler\RouteInjectionFactory
Articus\PathHandler\MetadataProviderInterface: Articus\PathHandler\MetadataProvider\Factory\PhpAttribute
Articus\PathHandler\Handler\PluginManager: Articus\PathHandler\Handler\Factory\PluginManager
Articus\PathHandler\Consumer\PluginManager: Articus\PathHandler\Consumer\Factory\PluginManager
Articus\PathHandler\Attribute\PluginManager: Articus\PathHandler\Attribute\Factory\PluginManager
Articus\PathHandler\Producer\PluginManager: Articus\PathHandler\Producer\Factory\PluginManager
Articus\PathHandler\RouteInjectionFactory:
paths:
'{{basePathWithoutHost}}':
{{#apiInfo}}
{{#apis}}
{{#operations}}
- {{package}}\{{classname}}
{{/operations}}
{{/apis}}
{{/apiInfo}}
Articus\PathHandler\Handler\PluginManager:
abstract_factories:
- Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory
#Articus\PathHandler\Consumer\PluginManager:
# factories:
# invokables:
#Articus\PathHandler\Attribute\PluginManager:
# factories:
# invokables:
#Articus\PathHandler\Producer\PluginManager:
# factories:
# invokables:
Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory:
{{#apiInfo}}
{{#apis}}
{{#operations}}
{{package}}\{{classname}}: []
{{/operations}}
{{/apis}}
{{/apiInfo}}

View File

@ -23,20 +23,13 @@ class Factory implements FactoryInterface
{
public function __invoke(ContainerInterface $container, $requestedName, array $options = null): Application
{
$errorMiddleware = $container->get(Middleware\InternalServerError::class);
if (!($errorMiddleware instanceof Middleware\InternalServerError)) {
throw new \LogicException(\sprintf(
'Invalid error middleware: expecting %s, not %s.',
Middleware\InternalServerError::class,
\is_object($errorMiddleware) ? \get_class($errorMiddleware) : \gettype($errorMiddleware)
));
}
$errorMiddleware = self::getErrorMiddleware($container);
$pipeline = new MiddlewarePipe();
$runner = new RequestHandlerRunner(
$pipeline,
$container->get(EmitterInterface::class),
$container->get(ServerRequestInterface::class),
function(\Throwable $error) use ($errorMiddleware) : ResponseInterface
static function(\Throwable $error) use ($errorMiddleware) : ResponseInterface
{
return $errorMiddleware->handleError($error);
}
@ -55,4 +48,9 @@ class Factory implements FactoryInterface
return $application;
}
protected static function getErrorMiddleware(ContainerInterface $container): Middleware\InternalServerError
{
return $container->get(Middleware\InternalServerError::class);
}
}

View File

@ -5,9 +5,9 @@ Generated by the [OpenAPI Generator](https://openapi-generator.tech) project.
## Overview
This server stub aims to provide light, yet comprehensive structure for your API project using:
- PHP: >=7.2
- PHP: >=7.3
- [Laminas Mezzio](https://docs.mezzio.dev/mezzio/): >=3.2
- [Path Handler](https://github.com/Articus/PathHandler): >=0.6
- [Path Handler](https://github.com/Articus/PathHandler): >=0.7
## How to use
All you have to do to start development is:

View File

@ -43,13 +43,7 @@ class {{classname}}
* @PHA\Consumer(name=PHConsumer\Json::class, mediaRange="{{{mediaType}}}")
{{/consumes}}
{{^isPrimitiveType}}
{{#isContainer}}
* TODO check if attribute is valid and can handle your container type
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={"type":"{{{dataType}}}","objectAttr":"bodyData"})
{{/isContainer}}
{{^isContainer}}
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={"type":{{{dataType}}}::class,"objectAttr":"bodyData"})
{{/isContainer}}
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={"type":{{dataType}}::class,"objectAttr":"bodyData"})
{{/isPrimitiveType}}
{{/bodyParam}}
{{#produces}}
@ -61,13 +55,10 @@ class {{classname}}
* @throws PHException\HttpCode 501 if the method is not implemented
{{#returnType}}
*
{{#returnContainer}}
* TODO check if generated return container type is valid
{{/returnContainer}}
* @return {{{returnType}}}
* @return {{returnType}}
{{/returnType}}
*/
public function {{operationId}}(ServerRequestInterface $request){{#returnType}}: {{#returnContainer}}array{{/returnContainer}}{{^returnContainer}}{{returnType}}{{/returnContainer}}{{/returnType}}
public function {{operationId}}(ServerRequestInterface $request){{#returnType}}: {{returnType}}{{/returnType}}
{
//TODO implement method
{{#vendorExtensions}}
@ -78,7 +69,7 @@ class {{classname}}
{{/vendorExtensions}}
{{#bodyParam}}
{{^isPrimitiveType}}
/** @var {{{dataType}}} $bodyData */
/** @var {{dataType}} $bodyData */
$bodyData = $request->getAttribute("bodyData");
{{/isPrimitiveType}}
{{/bodyParam}}

View File

@ -5,13 +5,13 @@
"version": "{{artifactVersion}}",
"type": "project",
"require": {
"php": "^7.2",
"php": "^7.3 || ^8.0",
"ext-yaml": "^2.0",
"mezzio/mezzio": "^3.2",
"laminas/laminas-diactoros": "^2.1",
"articus/path-handler": "^0.6",
"articus/data-transfer": "^0.4",
"articus/openapi-generator-common": "^0.1",
"articus/path-handler": "^0.7",
"articus/data-transfer": "^0.5",
"articus/openapi-generator-common": "^0.2",
"doctrine/annotations": "^1.10",
"psr/simple-cache": "^1.0",
"laminas/laminas-config": "^3.4",

View File

@ -9,10 +9,11 @@
# router:
# cache:
# directory: ./data/cache/PathHandler
# #Enable handler metadata cache
# metadata:
# cache:
# directory: ./data/cache/PathHandler
#Enable handler metadata cache
#Articus\PathHandler\MetadataProvider\Annotation:
# cache:
# directory: ./data/cache/PathHandler
#Enable data transfer metadata cache for DTOs
#Articus\DataTransfer\MetadataProvider\Annotation:

View File

@ -16,6 +16,10 @@ Articus\DataTransfer\Strategy\PluginManager:
factories:
Date: OpenAPIGenerator\Common\Strategy\Factory\MutableDate
DateTime: OpenAPIGenerator\Common\Strategy\Factory\MutableDateTime
ObjectList: OpenAPIGenerator\Common\Strategy\Factory\NoArgObjectList
ObjectMap: OpenAPIGenerator\Common\Strategy\Factory\NoArgObjectMap
ScalarList: OpenAPIGenerator\Common\Strategy\Factory\ScalarList
ScalarMap: OpenAPIGenerator\Common\Strategy\Factory\ScalarMap
Articus\DataTransfer\Validator\PluginManager:
invokables:
@ -24,3 +28,7 @@ Articus\DataTransfer\Validator\PluginManager:
QueryStringScalarArray: OpenAPIGenerator\Common\Validator\QueryStringScalarArray
abstract_factories:
- Articus\DataTransfer\Validator\Factory\Laminas
validators:
invokables:
Count: Laminas\Validator\IsCountable

View File

@ -0,0 +1,8 @@
{{#items
}}{{^isContainer
}}{{#isPrimitiveType}}"{{dataType}}"{{/isPrimitiveType
}}{{^isPrimitiveType}}{{dataType}}::class{{/isPrimitiveType
}}{{/isContainer
}}{{#isContainer
}}{{dataType}}::class{{/isContainer
}}{{/items}}

View File

@ -0,0 +1,8 @@
{{#additionalProperties
}}{{^isContainer
}}{{#isPrimitiveType}}"{{dataType}}"{{/isPrimitiveType
}}{{^isPrimitiveType}}{{dataType}}::class{{/isPrimitiveType
}}{{/isContainer
}}{{#isContainer
}}{{dataType}}::class{{/isContainer
}}{{/additionalProperties}}

View File

@ -5,23 +5,9 @@ namespace {{package}};
use Articus\DataTransfer\Annotation as DTA;
/**
{{#description}}
* {{description}}
{{/description}}
*/
class {{classname}}
{
{{#vars}}
/**
{{#description}}
* {{description}}
{{/description}}
* @DTA\Data(field="{{baseName}}"{{^required}}, nullable=true{{/required}}){{#vendorExtensions}}{{#internal.ze-ph.fromQuery}}
{{>model_query_var}}{{/internal.ze-ph.fromQuery}}{{/vendorExtensions}}{{#vendorExtensions}}{{^internal.ze-ph.fromQuery}}
{{>model_normal_var}}{{/internal.ze-ph.fromQuery}}{{/vendorExtensions}}{{^vendorExtensions}}
{{>model_normal_var}}{{/vendorExtensions}} * @var {{dataType}}|null
*/
public ${{name}};
{{/vars}}
}{{/model}}{{/models}}
{{#vendorExtensions
}}{{#internal.ze-ph.fromContainer}}{{>model_container}}{{/internal.ze-ph.fromContainer
}}{{^internal.ze-ph.fromContainer}}{{>model_object}}{{/internal.ze-ph.fromContainer
}}{{/vendorExtensions
}}{{^vendorExtensions}}{{>model_object}}{{/vendorExtensions
}}{{/model}}{{/models}}

View File

@ -0,0 +1,59 @@
/**
{{#vars
}}{{#isArray
}} * @DTA\Strategy(name="{{#isPrimitiveType}}ScalarList{{/isPrimitiveType}}{{^isPrimitiveType}}ObjectList{{/isPrimitiveType}}", options={"type":{{>list_item_type}}})
{{#minItems}}{{^maxItems
}} * @DTA\Validator(name="Count", options={"min":{{minItems}}}, blocker=true)
{{/maxItems}}{{/minItems
}}{{^minItems}}{{#maxItems
}} * @DTA\Validator(name="Count", options={"max":{{maxItems}}}, blocker=true)
{{/maxItems}}{{/minItems
}}{{#minItems}}{{#maxItems
}} * @DTA\Validator(name="Count", options={"min":{{minItems}},"max":{{maxItems}}}, blocker=true)
{{/maxItems}}{{/minItems
}} * @DTA\Validator(name="Collection", options={"validators":{
{{#isPrimitiveType
}} * {"name":"Scalar", "options":{"type":{{>list_item_type}}}}
{{/isPrimitiveType
}}{{#isDate
}} * {"name":"Date"}
{{/isDate
}}{{#isDateTime
}} * {"name":"Date", "options":{"format": \DateTime::RFC3339}}
{{/isDateTime
}}{{^isPrimitiveType}}{{^isDate}}{{^isDateTime
}} * {"name":"TypeCompliant", "options":{"type":{{>list_item_type}}}}
{{/isDateTime}}{{/isDate}}{{/isPrimitiveType
}} * }})
{{/isArray
}}{{#isMap
}} * @DTA\Strategy(name="{{#isPrimitiveType}}ScalarMap{{/isPrimitiveType}}{{^isPrimitiveType}}ObjectMap{{/isPrimitiveType}}", options={"type":{{>map_item_type}}})
{{#minProperties}}{{^maxProperties
}} * @DTA\Validator(name="Count", options={"min":{{minProperties}}}, blocker=true)
{{/maxProperties}}{{/minProperties
}}{{^minProperties}}{{#maxProperties
}} * @DTA\Validator(name="Count", options={"max":{{maxProperties}}}, blocker=true)
{{/maxProperties}}{{/minProperties
}}{{#minProperties}}{{#maxProperties
}} * @DTA\Validator(name="Count", options={"min":{{minProperties}},"max":{{maxProperties}}}, blocker=true)
{{/maxProperties}}{{/minProperties
}} * @DTA\Validator(name="Collection", options={"validators":{
{{#isPrimitiveType
}} * {"name":"Scalar", "options":{"type":{{>map_item_type}}}}
{{/isPrimitiveType
}}{{#isDate
}} * {"name":"Date"}
{{/isDate
}}{{#isDateTime
}} * {"name":"Date", "options":{"format": \DateTime::RFC3339}}
{{/isDateTime
}}{{^isPrimitiveType}}{{^isDate}}{{^isDateTime
}} * {"name":"TypeCompliant", "options":{"type":{{>map_item_type}}}}
{{/isDateTime}}{{/isDate}}{{/isPrimitiveType
}} * }})
{{/isMap
}}{{/vars
}} */
class {{classname}} extends \ArrayObject
{
}

View File

@ -1,64 +1,45 @@
{{^isPrimitiveType}}
{{^isContainer}}
{{^isDate}}
{{^isDateTime}}
* @DTA\Strategy(name="Object", options={"type":{{dataType}}::class})
* @DTA\Validator(name="TypeCompliant", options={"type":{{dataType}}::class})
{{/isDateTime}}
{{/isDate}}
{{#isDate}}
* @DTA\Strategy(name="Date")
{{#isContainer
}} * @DTA\Strategy(name="Object", options={"type":{{internal.ze-ph.containerDataType}}::class})
* @DTA\Validator(name="TypeCompliant", options={"type":{{internal.ze-ph.containerDataType}}::class})
{{/isContainer
}}{{^isContainer
}}{{#isPrimitiveType
}} * @DTA\Validator(name="Scalar", options={"type":"{{dataType}}"})
{{/isPrimitiveType
}}{{#isDate
}} * @DTA\Strategy(name="Date")
* @DTA\Validator(name="Date")
{{/isDate}}
{{#isDateTime}}
* @DTA\Strategy(name="DateTime")
{{/isDate
}}{{#isDateTime
}} * @DTA\Strategy(name="DateTime")
* @DTA\Validator(name="Date", options={"format": \DateTime::RFC3339})
{{/isDateTime}}
{{/isContainer}}
{{#isContainer}}
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Strategy(name="ObjectArray", options={"type":{{#items}}{{dataType}}{{/items}}::class})
* @DTA\Validator(name="Collection", options={"validators":{
* {"name":"TypeCompliant", "options":{"type":{{#items}}{{dataType}}{{/items}}::class}}
* }})
{{/isContainer}}
{{/isPrimitiveType}}
{{#isPrimitiveType}}
{{#isContainer}}
{{#items}}
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Validator(name="Collection", options={"validators":{
* {"name":"Scalar", "options":{"type":"{{dataType}}"}}
* }})
{{/items}}
{{/isContainer}}
{{^isContainer}}
* @DTA\Validator(name="Scalar", options={"type":"{{dataType}}"})
{{/isContainer}}
{{/isPrimitiveType}}
{{#hasValidation}}
{{#minLength}}
{{#maxLength}}
* @DTA\Validator(name="StringLength", options={"min":{{minLength}}, "max":{{maxLength}}})
{{/maxLength}}
{{/minLength}}
{{^minLength}}
{{#maxLength}}
* @DTA\Validator(name="StringLength", options={"max":{{maxLength}}})
{{/maxLength}}
{{/minLength}}
{{#minLength}}
{{^maxLength}}
* @DTA\Validator(name="StringLength", options={"min":{{minLength}}})
{{/maxLength}}
{{/minLength}}
{{#minimum}}
* @DTA\Validator(name="GreaterThan", options={"min":{{minimum}}{{^exclusiveMinimum}}, "inclusive":true{{/exclusiveMinimum}}})
{{/minimum}}
{{#maximum}}
* @DTA\Validator(name="LessThan", options={"max":{{maximum}}{{^exclusiveMaximum}}, "inclusive":true{{/exclusiveMaximum}}})
{{/maximum}}
{{#pattern}}
* @DTA\Validator(name="Regex", options={"pattern":"{{{pattern}}}"})
{{/pattern}}
{{/hasValidation}}
{{/isDateTime
}}{{^isPrimitiveType
}}{{^isDate
}}{{^isDateTime
}} * @DTA\Strategy(name="Object", options={"type":{{dataType}}::class})
* @DTA\Validator(name="TypeCompliant", options={"type":{{dataType}}::class})
{{/isDateTime
}}{{/isDate
}}{{/isPrimitiveType
}}{{/isContainer
}}{{#hasValidation
}}{{#minLength}}{{#maxLength
}} * @DTA\Validator(name="StringLength", options={"min":{{minLength}}, "max":{{maxLength}}})
{{/maxLength}}{{/minLength
}}{{^minLength}}{{#maxLength
}} * @DTA\Validator(name="StringLength", options={"max":{{maxLength}}})
{{/maxLength}}{{/minLength
}}{{#minLength}}{{^maxLength
}} * @DTA\Validator(name="StringLength", options={"min":{{minLength}}})
{{/maxLength}}{{/minLength
}}{{#minimum
}} * @DTA\Validator(name="GreaterThan", options={"min":{{minimum}}{{^exclusiveMinimum}}, "inclusive":true{{/exclusiveMinimum}}})
{{/minimum
}}{{#maximum
}} * @DTA\Validator(name="LessThan", options={"max":{{maximum}}{{^exclusiveMaximum}}, "inclusive":true{{/exclusiveMaximum}}})
{{/maximum
}}{{#pattern
}} * @DTA\Validator(name="Regex", options={"pattern":"{{{pattern}}}"})
{{/pattern
}}{{/hasValidation}}

View File

@ -0,0 +1,24 @@
/**
{{#description
}} * {{description}}
{{/description
}} */
class {{classname}}
{
{{#vars
}} /**
{{#description
}} * {{description}}
{{/description
}} * @DTA\Data(field="{{baseName}}"{{^required}}, nullable=true{{/required}})
{{#vendorExtensions
}}{{#internal.ze-ph.fromQuery}}{{>model_query_var}}{{/internal.ze-ph.fromQuery
}}{{^internal.ze-ph.fromQuery}}{{>model_normal_var}}{{/internal.ze-ph.fromQuery
}}{{/vendorExtensions
}}{{^vendorExtensions}}{{>model_normal_var}}{{/vendorExtensions
}} * @var {{dataType}}|null
*/
public ${{name}};
{{/vars
}}}

View File

@ -1,52 +1,51 @@
{{^isPrimitiveType}}
{{^isContainer}}
{{#isDate}}
* @DTA\Strategy(name="Date")
* @DTA\Validator(name="Date")
{{/isDate}}
{{#isDateTime}}
* @DTA\Strategy(name="DateTime")
* @DTA\Validator(name="Date", options={"format": \DateTime::RFC3339})
{{/isDateTime}}
{{/isContainer}}
{{#isContainer}}
* TODO add validator(s) and strategy for {{dataType}} and collection format {{internal.ze-ph.collectionFormat}}
{{/isContainer}}
{{/isPrimitiveType}}
{{#isPrimitiveType}}
{{#isContainer}}
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Strategy(name="QueryStringScalarArray", options={"type":"{{#items}}{{dataType}}{{/items}}", "format":"{{internal.ze-ph.collectionFormat}}"})
* @DTA\Validator(name="QueryStringScalarArray", options={"type":"{{#items}}{{dataType}}{{/items}}", "format":"{{internal.ze-ph.collectionFormat}}"{{#minItems}}, "min_items":{{minItems}}{{/minItems}}{{#maxItems}}, "max_items":{{maxItems}}{{/maxItems}}})
{{/isContainer}}
{{^isContainer}}
* @DTA\Strategy(name="QueryStringScalar", options={"type":"{{dataType}}"})
{{#isArray
}}{{#isPrimitiveType
}} * @DTA\Strategy(name="QueryStringScalarArray", options={"type":{{>list_item_type}}, "format":"{{internal.ze-ph.collectionFormat}}"})
* @DTA\Validator(name="QueryStringScalarArray", options={"type":{{>list_item_type}}, "format":"{{internal.ze-ph.collectionFormat}}"{{#minItems}}, "min_items":{{minItems}}{{/minItems}}{{#maxItems}}, "max_items":{{maxItems}}{{/maxItems}}})
{{/isPrimitiveType
}}{{^isPrimitiveType
}} * TODO add validator(s) and strategy for list of {{>list_item_type}} and collection format {{internal.ze-ph.collectionFormat}} inside query string
{{/isPrimitiveType
}}{{/isArray
}}{{#isMap
}} * TODO add validator(s) and strategy for map of {{>map_item_type}} and collection format {{internal.ze-ph.collectionFormat}} inside query string
{{/isMap
}}{{^isContainer
}}{{#isPrimitiveType
}} * @DTA\Strategy(name="QueryStringScalar", options={"type":"{{dataType}}"})
* @DTA\Validator(name="QueryStringScalar", options={"type":"{{dataType}}"})
{{/isContainer}}
{{/isPrimitiveType}}
{{#hasValidation}}
{{#minLength}}
{{#maxLength}}
* @DTA\Validator(name="StringLength", options={"min":{{minLength}}, "max":{{maxLength}}})
{{/maxLength}}
{{/minLength}}
{{^minLength}}
{{#maxLength}}
* @DTA\Validator(name="StringLength", options={"max":{{maxLength}}})
{{/maxLength}}
{{/minLength}}
{{#minLength}}
{{^maxLength}}
* @DTA\Validator(name="StringLength", options={"min":{{minLength}}})
{{/maxLength}}
{{/minLength}}
{{#minimum}}
* @DTA\Validator(name="GreaterThan", options={"min":{{minimum}}{{^exclusiveMinimum}}, "inclusive":true{{/exclusiveMinimum}}})
{{/minimum}}
{{#maximum}}
* @DTA\Validator(name="LessThan", options={"max":{{maximum}}{{^exclusiveMaximum}}, "inclusive":true{{/exclusiveMaximum}}})
{{/maximum}}
{{#pattern}}
* @DTA\Validator(name="Regex", options={"pattern":"{{{pattern}}}"})
{{/pattern}}
{{/hasValidation}}
{{/isPrimitiveType
}}{{#isDate
}} * @DTA\Strategy(name="Date")
* @DTA\Validator(name="Date")
{{/isDate
}}{{#isDateTime
}} * @DTA\Strategy(name="DateTime")
* @DTA\Validator(name="Date", options={"format": \DateTime::RFC3339})
{{/isDateTime
}}{{^isPrimitiveType
}}{{^isDate}}{{^isDateTime
}} * TODO add validator(s) and strategy for {{dataType}} inside query string
{{/isDateTime}}{{/isDate
}}{{/isPrimitiveType
}}{{/isContainer
}}{{#hasValidation
}}{{#minLength}}{{#maxLength
}} * @DTA\Validator(name="StringLength", options={"min":{{minLength}}, "max":{{maxLength}}})
{{/maxLength}}{{/minLength
}}{{^minLength}}{{#maxLength
}} * @DTA\Validator(name="StringLength", options={"max":{{maxLength}}})
{{/maxLength}}{{/minLength
}}{{#minLength}}{{^maxLength
}} * @DTA\Validator(name="StringLength", options={"min":{{minLength}}})
{{/maxLength}}{{/minLength
}}{{#minimum
}} * @DTA\Validator(name="GreaterThan", options={"min":{{minimum}}{{^exclusiveMinimum}}, "inclusive":true{{/exclusiveMinimum}}})
{{/minimum
}}{{#maximum
}} * @DTA\Validator(name="LessThan", options={"max":{{maximum}}{{^exclusiveMaximum}}, "inclusive":true{{/exclusiveMaximum}}})
{{/maximum
}}{{#pattern
}} * @DTA\Validator(name="Regex", options={"pattern":"{{{pattern}}}"})
{{/pattern
}}{{/hasValidation}}

View File

@ -1,8 +1,13 @@
dependencies:
factories:
Mezzio\Router\RouterInterface: Articus\PathHandler\RouteInjection\Factory
Mezzio\Router\RouterInterface: Articus\PathHandler\RouteInjectionFactory
Articus\PathHandler\MetadataProviderInterface: Articus\PathHandler\MetadataProvider\Factory\Annotation
Articus\PathHandler\Handler\PluginManager: Articus\PathHandler\Handler\Factory\PluginManager
Articus\PathHandler\Consumer\PluginManager: Articus\PathHandler\Consumer\Factory\PluginManager
Articus\PathHandler\Attribute\PluginManager: Articus\PathHandler\Attribute\Factory\PluginManager
Articus\PathHandler\Producer\PluginManager: Articus\PathHandler\Producer\Factory\PluginManager
Articus\PathHandler\RouteInjection\Factory:
Articus\PathHandler\RouteInjectionFactory:
paths:
'{{basePathWithoutHost}}':
{{#apiInfo}}
@ -12,18 +17,22 @@ Articus\PathHandler\RouteInjection\Factory:
{{/operations}}
{{/apis}}
{{/apiInfo}}
handlers:
abstract_factories:
- Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory
# consumers:
# factories:
# invokables:
# attributes:
# factories:
# invokables:
# producers:
# factories:
# invokables:
Articus\PathHandler\Handler\PluginManager:
abstract_factories:
- Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory
#Articus\PathHandler\Consumer\PluginManager:
# factories:
# invokables:
#Articus\PathHandler\Attribute\PluginManager:
# factories:
# invokables:
#Articus\PathHandler\Producer\PluginManager:
# factories:
# invokables:
Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory:
{{#apiInfo}}

View File

@ -1,36 +0,0 @@
.gitignore
README.md
application/config.yml
application/config/app.yml
application/config/data_transfer.yml
application/config/path_handler.yml
application/container.php
composer.json
public/index.php
src/App/DTO/ApiResponse.php
src/App/DTO/Category.php
src/App/DTO/FindPetsByStatusQueryData.php
src/App/DTO/FindPetsByTagsQueryData.php
src/App/DTO/InlineObject.php
src/App/DTO/InlineObject1.php
src/App/DTO/LoginUserQueryData.php
src/App/DTO/Order.php
src/App/DTO/Pet.php
src/App/DTO/Tag.php
src/App/DTO/User.php
src/App/Factory.php
src/App/Handler/Pet.php
src/App/Handler/PetFindByStatus.php
src/App/Handler/PetFindByTags.php
src/App/Handler/PetPetId.php
src/App/Handler/PetPetIdUploadImage.php
src/App/Handler/StoreInventory.php
src/App/Handler/StoreOrder.php
src/App/Handler/StoreOrderOrderId.php
src/App/Handler/User.php
src/App/Handler/UserCreateWithArray.php
src/App/Handler/UserCreateWithList.php
src/App/Handler/UserLogin.php
src/App/Handler/UserLogout.php
src/App/Handler/UserUsername.php
src/App/Middleware/InternalServerError.php

View File

@ -1,27 +0,0 @@
{
"name": "git_user_id/git_repo_id",
"description": "",
"license": "unlicense",
"version": "1.0.0",
"type": "project",
"require": {
"php": "^7.2",
"ext-yaml": "^2.0",
"mezzio/mezzio": "^3.2",
"laminas/laminas-diactoros": "^2.1",
"articus/path-handler": "^0.6",
"articus/data-transfer": "^0.4",
"articus/openapi-generator-common": "^0.1",
"doctrine/annotations": "^1.10",
"psr/simple-cache": "^1.0",
"laminas/laminas-config": "^3.4",
"laminas/laminas-stdlib": "^3.2",
"laminas/laminas-validator": "^2.13",
"nikic/fast-route": "^1.3"
},
"autoload": {
"psr-4": {
"": "src/"
}
}
}

View File

@ -1,31 +0,0 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
* Describes the result of uploading an image resource
*/
class ApiResponse
{
/**
* @DTA\Data(field="code", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"int"})
* @var int|null
*/
public $code;
/**
* @DTA\Data(field="type", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"string"})
* @var string|null
*/
public $type;
/**
* @DTA\Data(field="message", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"string"})
* @var string|null
*/
public $message;
}

View File

@ -1,26 +0,0 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
* A category for a pet
*/
class Category
{
/**
* @DTA\Data(field="id", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"int"})
* @var int|null
*/
public $id;
/**
* @DTA\Data(field="name", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"string"})
* @DTA\Validator(name="Regex", options={"pattern":"/^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$/"})
* @var string|null
*/
public $name;
}

View File

@ -1,22 +0,0 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
* Query parameters for findPetsByStatus
*/
class FindPetsByStatusQueryData
{
/**
* Status values that need to be considered for filter
* @DTA\Data(field="status")
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Strategy(name="QueryStringScalarArray", options={"type":"string", "format":"csv"})
* @DTA\Validator(name="QueryStringScalarArray", options={"type":"string", "format":"csv"})
* @var string[]|null
*/
public $status;
}

View File

@ -1,22 +0,0 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
* Query parameters for findPetsByTags
*/
class FindPetsByTagsQueryData
{
/**
* Tags to filter by
* @DTA\Data(field="tags")
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Strategy(name="QueryStringScalarArray", options={"type":"string", "format":"csv"})
* @DTA\Validator(name="QueryStringScalarArray", options={"type":"string", "format":"csv"})
* @var string[]|null
*/
public $tags;
}

View File

@ -1,26 +0,0 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class InlineObject
{
/**
* Updated name of the pet
* @DTA\Data(field="name", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"string"})
* @var string|null
*/
public $name;
/**
* Updated status of the pet
* @DTA\Data(field="status", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"string"})
* @var string|null
*/
public $status;
}

View File

@ -1,27 +0,0 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class InlineObject1
{
/**
* Additional data to pass to server
* @DTA\Data(field="additionalMetadata", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"string"})
* @var string|null
*/
public $additional_metadata;
/**
* file to upload
* @DTA\Data(field="file", nullable=true)
* @DTA\Strategy(name="Object", options={"type":\SplFileObject::class})
* @DTA\Validator(name="TypeCompliant", options={"type":\SplFileObject::class})
* @var \SplFileObject|null
*/
public $file;
}

View File

@ -1,30 +0,0 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
* Query parameters for loginUser
*/
class LoginUserQueryData
{
/**
* The password for login in clear text
* @DTA\Data(field="password")
* @DTA\Strategy(name="QueryStringScalar", options={"type":"string"})
* @DTA\Validator(name="QueryStringScalar", options={"type":"string"})
* @var string|null
*/
public $password;
/**
* The user name for login
* @DTA\Data(field="username")
* @DTA\Strategy(name="QueryStringScalar", options={"type":"string"})
* @DTA\Validator(name="QueryStringScalar", options={"type":"string"})
* @DTA\Validator(name="Regex", options={"pattern":"/^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$/"})
* @var string|null
*/
public $username;
}

View File

@ -1,51 +0,0 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
* An order for a pets from the pet store
*/
class Order
{
/**
* @DTA\Data(field="id", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"int"})
* @var int|null
*/
public $id;
/**
* @DTA\Data(field="petId", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"int"})
* @var int|null
*/
public $pet_id;
/**
* @DTA\Data(field="quantity", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"int"})
* @var int|null
*/
public $quantity;
/**
* @DTA\Data(field="shipDate", nullable=true)
* @DTA\Strategy(name="DateTime")
* @DTA\Validator(name="Date", options={"format": \DateTime::RFC3339})
* @var \DateTime|null
*/
public $ship_date;
/**
* Order Status
* @DTA\Data(field="status", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"string"})
* @var string|null
*/
public $status;
/**
* @DTA\Data(field="complete", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"bool"})
* @var bool|null
*/
public $complete;
}

View File

@ -1,58 +0,0 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
* A pet for sale in the pet store
*/
class Pet
{
/**
* @DTA\Data(field="id", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"int"})
* @var int|null
*/
public $id;
/**
* @DTA\Data(field="category", nullable=true)
* @DTA\Strategy(name="Object", options={"type":\App\DTO\Category::class})
* @DTA\Validator(name="TypeCompliant", options={"type":\App\DTO\Category::class})
* @var \App\DTO\Category|null
*/
public $category;
/**
* @DTA\Data(field="name")
* @DTA\Validator(name="Scalar", options={"type":"string"})
* @var string|null
*/
public $name;
/**
* @DTA\Data(field="photoUrls")
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Validator(name="Collection", options={"validators":{
* {"name":"Scalar", "options":{"type":"string"}}
* }})
* @var string[]|null
*/
public $photo_urls;
/**
* @DTA\Data(field="tags", nullable=true)
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Strategy(name="ObjectArray", options={"type":\App\DTO\Tag::class})
* @DTA\Validator(name="Collection", options={"validators":{
* {"name":"TypeCompliant", "options":{"type":\App\DTO\Tag::class}}
* }})
* @var \App\DTO\Tag[]|null
*/
public $tags;
/**
* pet status in the store
* @DTA\Data(field="status", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"string"})
* @var string|null
*/
public $status;
}

View File

@ -1,25 +0,0 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
* A tag for a pet
*/
class Tag
{
/**
* @DTA\Data(field="id", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"int"})
* @var int|null
*/
public $id;
/**
* @DTA\Data(field="name", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"string"})
* @var string|null
*/
public $name;
}

View File

@ -1,62 +0,0 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
* A User who is purchasing from the pet store
*/
class User
{
/**
* @DTA\Data(field="id", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"int"})
* @var int|null
*/
public $id;
/**
* @DTA\Data(field="username", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"string"})
* @var string|null
*/
public $username;
/**
* @DTA\Data(field="firstName", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"string"})
* @var string|null
*/
public $first_name;
/**
* @DTA\Data(field="lastName", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"string"})
* @var string|null
*/
public $last_name;
/**
* @DTA\Data(field="email", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"string"})
* @var string|null
*/
public $email;
/**
* @DTA\Data(field="password", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"string"})
* @var string|null
*/
public $password;
/**
* @DTA\Data(field="phone", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"string"})
* @var string|null
*/
public $phone;
/**
* User Status
* @DTA\Data(field="userStatus", nullable=true)
* @DTA\Validator(name="Scalar", options={"type":"int"})
* @var int|null
*/
public $user_status;
}

View File

@ -1,68 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Handler;
use Articus\PathHandler\Annotation as PHA;
use Articus\PathHandler\Consumer as PHConsumer;
use Articus\PathHandler\Producer as PHProducer;
use Articus\PathHandler\Attribute as PHAttribute;
use Articus\PathHandler\Exception as PHException;
use Psr\Http\Message\ServerRequestInterface;
/**
* @PHA\Route(pattern="/pet")
*/
class Pet
{
/**
* Add a new pet to the store
* @PHA\Post()
* TODO check if consumer is valid, if it has correct priority and if it can be moved to class annotation
* @PHA\Consumer(name=PHConsumer\Json::class, mediaRange="application/json")
* TODO check if consumer is valid, if it has correct priority and if it can be moved to class annotation
* @PHA\Consumer(name=PHConsumer\Json::class, mediaRange="application/xml")
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={"type":\App\DTO\Pet::class,"objectAttr":"bodyData"})
* TODO check if producer is valid, if it has correct priority and if it can be moved to class annotation
* @PHA\Producer(name=PHProducer\Transfer::class, mediaType="application/xml")
* TODO check if producer is valid, if it has correct priority and if it can be moved to class annotation
* @PHA\Producer(name=PHProducer\Transfer::class, mediaType="application/json")
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*
* @return \App\DTO\Pet
*/
public function addPet(ServerRequestInterface $request): \App\DTO\Pet
{
//TODO implement method
/** @var \App\DTO\Pet $bodyData */
$bodyData = $request->getAttribute("bodyData");
throw new PHException\HttpCode(501, "Not implemented");
}
/**
* Update an existing pet
* @PHA\Put()
* TODO check if consumer is valid, if it has correct priority and if it can be moved to class annotation
* @PHA\Consumer(name=PHConsumer\Json::class, mediaRange="application/json")
* TODO check if consumer is valid, if it has correct priority and if it can be moved to class annotation
* @PHA\Consumer(name=PHConsumer\Json::class, mediaRange="application/xml")
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={"type":\App\DTO\Pet::class,"objectAttr":"bodyData"})
* TODO check if producer is valid, if it has correct priority and if it can be moved to class annotation
* @PHA\Producer(name=PHProducer\Transfer::class, mediaType="application/xml")
* TODO check if producer is valid, if it has correct priority and if it can be moved to class annotation
* @PHA\Producer(name=PHProducer\Transfer::class, mediaType="application/json")
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*
* @return \App\DTO\Pet
*/
public function updatePet(ServerRequestInterface $request): \App\DTO\Pet
{
//TODO implement method
/** @var \App\DTO\Pet $bodyData */
$bodyData = $request->getAttribute("bodyData");
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -1,44 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Handler;
use Articus\PathHandler\Annotation as PHA;
use Articus\PathHandler\Consumer as PHConsumer;
use Articus\PathHandler\Producer as PHProducer;
use Articus\PathHandler\Attribute as PHAttribute;
use Articus\PathHandler\Exception as PHException;
use Psr\Http\Message\ServerRequestInterface;
/**
* @PHA\Route(pattern="/pet/findByStatus")
*/
class PetFindByStatus
{
/**
* Finds Pets by status
* @PHA\Get()
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={
* "type":\App\DTO\FindPetsByStatusQueryData::class,
* "objectAttr":"queryData",
* "source": PHAttribute\Transfer::SOURCE_GET
* })
* TODO check if producer is valid, if it has correct priority and if it can be moved to class annotation
* @PHA\Producer(name=PHProducer\Transfer::class, mediaType="application/xml")
* TODO check if producer is valid, if it has correct priority and if it can be moved to class annotation
* @PHA\Producer(name=PHProducer\Transfer::class, mediaType="application/json")
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*
* TODO check if generated return container type is valid
* @return \App\DTO\Pet[]
*/
public function findPetsByStatus(ServerRequestInterface $request): array
{
//TODO implement method
/** @var \App\DTO\FindPetsByStatusQueryData $queryData */
$queryData = $request->getAttribute("queryData");
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -1,44 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Handler;
use Articus\PathHandler\Annotation as PHA;
use Articus\PathHandler\Consumer as PHConsumer;
use Articus\PathHandler\Producer as PHProducer;
use Articus\PathHandler\Attribute as PHAttribute;
use Articus\PathHandler\Exception as PHException;
use Psr\Http\Message\ServerRequestInterface;
/**
* @PHA\Route(pattern="/pet/findByTags")
*/
class PetFindByTags
{
/**
* Finds Pets by tags
* @PHA\Get()
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={
* "type":\App\DTO\FindPetsByTagsQueryData::class,
* "objectAttr":"queryData",
* "source": PHAttribute\Transfer::SOURCE_GET
* })
* TODO check if producer is valid, if it has correct priority and if it can be moved to class annotation
* @PHA\Producer(name=PHProducer\Transfer::class, mediaType="application/xml")
* TODO check if producer is valid, if it has correct priority and if it can be moved to class annotation
* @PHA\Producer(name=PHProducer\Transfer::class, mediaType="application/json")
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*
* TODO check if generated return container type is valid
* @return \App\DTO\Pet[]
*/
public function findPetsByTags(ServerRequestInterface $request): array
{
//TODO implement method
/** @var \App\DTO\FindPetsByTagsQueryData $queryData */
$queryData = $request->getAttribute("queryData");
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -1,41 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Handler;
use Articus\PathHandler\Annotation as PHA;
use Articus\PathHandler\Consumer as PHConsumer;
use Articus\PathHandler\Producer as PHProducer;
use Articus\PathHandler\Attribute as PHAttribute;
use Articus\PathHandler\Exception as PHException;
use Psr\Http\Message\ServerRequestInterface;
/**
* @PHA\Route(pattern="/store/order")
*/
class StoreOrder
{
/**
* Place an order for a pet
* @PHA\Post()
* TODO check if consumer is valid, if it has correct priority and if it can be moved to class annotation
* @PHA\Consumer(name=PHConsumer\Json::class, mediaRange="application/json")
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={"type":\App\DTO\Order::class,"objectAttr":"bodyData"})
* TODO check if producer is valid, if it has correct priority and if it can be moved to class annotation
* @PHA\Producer(name=PHProducer\Transfer::class, mediaType="application/xml")
* TODO check if producer is valid, if it has correct priority and if it can be moved to class annotation
* @PHA\Producer(name=PHProducer\Transfer::class, mediaType="application/json")
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*
* @return \App\DTO\Order
*/
public function placeOrder(ServerRequestInterface $request): \App\DTO\Order
{
//TODO implement method
/** @var \App\DTO\Order $bodyData */
$bodyData = $request->getAttribute("bodyData");
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -1,43 +0,0 @@
<?php
declare(strict_types=1);
namespace App\Handler;
use Articus\PathHandler\Annotation as PHA;
use Articus\PathHandler\Consumer as PHConsumer;
use Articus\PathHandler\Producer as PHProducer;
use Articus\PathHandler\Attribute as PHAttribute;
use Articus\PathHandler\Exception as PHException;
use Psr\Http\Message\ServerRequestInterface;
/**
* @PHA\Route(pattern="/user/login")
*/
class UserLogin
{
/**
* Logs user into the system
* @PHA\Get()
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={
* "type":\App\DTO\LoginUserQueryData::class,
* "objectAttr":"queryData",
* "source": PHAttribute\Transfer::SOURCE_GET
* })
* TODO check if producer is valid, if it has correct priority and if it can be moved to class annotation
* @PHA\Producer(name=PHProducer\Transfer::class, mediaType="application/xml")
* TODO check if producer is valid, if it has correct priority and if it can be moved to class annotation
* @PHA\Producer(name=PHProducer\Transfer::class, mediaType="application/json")
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*
* @return string
*/
public function loginUser(ServerRequestInterface $request): string
{
//TODO implement method
/** @var \App\DTO\LoginUserQueryData $queryData */
$queryData = $request->getAttribute("queryData");
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -0,0 +1,9 @@
#based on .gitignore generated by https://github.com/zendframework/zend-expressive-skeleton
.idea
# Composer files
composer.phar
vendor/
# Default cache folder
data/cache/

View File

@ -0,0 +1,71 @@
.gitignore
README.md
application/config.yml
application/config/app.yml
application/config/data_transfer.yml
application/config/path_handler.yml
application/container.php
composer.json
public/index.php
src/App/DTO/ApiResponse.php
src/App/DTO/Category.php
src/App/DTO/Collection.php
src/App/DTO/Collection1.php
src/App/DTO/Collection10.php
src/App/DTO/Collection11.php
src/App/DTO/Collection12.php
src/App/DTO/Collection13.php
src/App/DTO/Collection14.php
src/App/DTO/Collection15.php
src/App/DTO/Collection16.php
src/App/DTO/Collection17.php
src/App/DTO/Collection18.php
src/App/DTO/Collection19.php
src/App/DTO/Collection2.php
src/App/DTO/Collection20.php
src/App/DTO/Collection21.php
src/App/DTO/Collection22.php
src/App/DTO/Collection23.php
src/App/DTO/Collection24.php
src/App/DTO/Collection25.php
src/App/DTO/Collection26.php
src/App/DTO/Collection27.php
src/App/DTO/Collection28.php
src/App/DTO/Collection29.php
src/App/DTO/Collection3.php
src/App/DTO/Collection30.php
src/App/DTO/Collection31.php
src/App/DTO/Collection32.php
src/App/DTO/Collection33.php
src/App/DTO/Collection34.php
src/App/DTO/Collection35.php
src/App/DTO/Collection36.php
src/App/DTO/Collection4.php
src/App/DTO/Collection5.php
src/App/DTO/Collection6.php
src/App/DTO/Collection7.php
src/App/DTO/Collection8.php
src/App/DTO/Collection9.php
src/App/DTO/FindPetsByStatusQueryData.php
src/App/DTO/FindPetsByTagsQueryData.php
src/App/DTO/LoginUserQueryData.php
src/App/DTO/Order.php
src/App/DTO/Pet.php
src/App/DTO/Tag.php
src/App/DTO/User.php
src/App/Factory.php
src/App/Handler/Pet.php
src/App/Handler/PetFindByStatus.php
src/App/Handler/PetFindByTags.php
src/App/Handler/PetPetId.php
src/App/Handler/PetPetIdUploadImage.php
src/App/Handler/StoreInventory.php
src/App/Handler/StoreOrder.php
src/App/Handler/StoreOrderOrderId.php
src/App/Handler/User.php
src/App/Handler/UserCreateWithArray.php
src/App/Handler/UserCreateWithList.php
src/App/Handler/UserLogin.php
src/App/Handler/UserLogout.php
src/App/Handler/UserUsername.php
src/App/Middleware/InternalServerError.php

View File

@ -0,0 +1 @@
5.2.0-SNAPSHOT

View File

@ -5,9 +5,9 @@ Generated by the [OpenAPI Generator](https://openapi-generator.tech) project.
## Overview
This server stub aims to provide light, yet comprehensive structure for your API project using:
- PHP: >=7.2
- [Laminas Mezzio](https://docs.mezzio.dev/mezzio/): >=3.2
- [Path Handler](https://github.com/Articus/PathHandler): >=0.6
- PHP: >=8.0
- [Laminas Mezzio](https://docs.mezzio.dev/mezzio/): >=3.3
- [Path Handler](https://github.com/Articus/PathHandler): >=0.7
## How to use
All you have to do to start development is:

View File

@ -0,0 +1,21 @@
#Empty configuration placeholder, remove when you add any real configuration settings to this file
{}
#Enable configuration cache
#cache_configuration: true
#Articus\PathHandler\RouteInjection\Factory:
# #Enable routing table cache
# router:
# cache:
# directory: ./data/cache/PathHandler
#Enable handler metadata cache
#Articus\PathHandler\MetadataProvider\PhpAttribute:
# cache:
# directory: ./data/cache/PathHandler
#Enable data transfer metadata cache for DTOs
#Articus\DataTransfer\MetadataProvider\PhpAttribute:
# cache:
# directory: ./data/cache/DataTransfer

View File

@ -0,0 +1,22 @@
dependencies:
invokables:
Laminas\HttpHandlerRunner\Emitter\EmitterInterface: Laminas\HttpHandlerRunner\Emitter\SapiStreamEmitter
factories:
Mezzio\Application: App\Factory
Mezzio\MiddlewareContainer: Mezzio\Container\MiddlewareContainerFactory
Mezzio\MiddlewareFactory: Mezzio\Container\MiddlewareFactoryFactory
Mezzio\Router\RouteCollector: Mezzio\Router\RouteCollectorFactory
Psr\Http\Message\ServerRequestInterface: Mezzio\Container\ServerRequestFactoryFactory
Psr\Http\Message\StreamInterface: Mezzio\Container\StreamFactoryFactory
Psr\Http\Message\ResponseInterface: Mezzio\Container\ResponseFactoryFactory
App\Middleware\InternalServerError: Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory
Mezzio\Router\Middleware\RouteMiddleware: Mezzio\Router\Middleware\RouteMiddlewareFactory
Mezzio\Router\Middleware\DispatchMiddleware: Mezzio\Router\Middleware\DispatchMiddlewareFactory
Mezzio\Router\Middleware\MethodNotAllowedMiddleware: Mezzio\Router\Middleware\MethodNotAllowedMiddlewareFactory
Mezzio\Handler\NotFoundHandler: Mezzio\Container\NotFoundHandlerFactory
Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory:
App\Middleware\InternalServerError:
- Psr\Http\Message\ResponseInterface

View File

@ -1,13 +1,13 @@
dependencies:
factories:
Articus\DataTransfer\Service: Articus\DataTransfer\Factory
Articus\DataTransfer\MetadataProvider\Annotation: Articus\DataTransfer\MetadataProvider\Factory\Annotation
Articus\DataTransfer\MetadataProvider\PhpAttribute: Articus\DataTransfer\MetadataProvider\Factory\PhpAttribute
Articus\DataTransfer\Strategy\PluginManager: Articus\DataTransfer\Strategy\Factory\PluginManager
Articus\DataTransfer\Validator\PluginManager: Articus\DataTransfer\Validator\Factory\PluginManager
Laminas\Validator\ValidatorPluginManager: Laminas\Validator\ValidatorPluginManagerFactory
aliases:
Articus\DataTransfer\ClassMetadataProviderInterface: Articus\DataTransfer\MetadataProvider\Annotation
Articus\DataTransfer\FieldMetadataProviderInterface: Articus\DataTransfer\MetadataProvider\Annotation
Articus\DataTransfer\ClassMetadataProviderInterface: Articus\DataTransfer\MetadataProvider\PhpAttribute
Articus\DataTransfer\FieldMetadataProviderInterface: Articus\DataTransfer\MetadataProvider\PhpAttribute
Articus\DataTransfer\Strategy\PluginManager:
invokables:
@ -16,6 +16,10 @@ Articus\DataTransfer\Strategy\PluginManager:
factories:
Date: OpenAPIGenerator\Common\Strategy\Factory\MutableDate
DateTime: OpenAPIGenerator\Common\Strategy\Factory\MutableDateTime
ObjectList: OpenAPIGenerator\Common\Strategy\Factory\NoArgObjectList
ObjectMap: OpenAPIGenerator\Common\Strategy\Factory\NoArgObjectMap
ScalarList: OpenAPIGenerator\Common\Strategy\Factory\ScalarList
ScalarMap: OpenAPIGenerator\Common\Strategy\Factory\ScalarMap
Articus\DataTransfer\Validator\PluginManager:
invokables:
@ -24,3 +28,7 @@ Articus\DataTransfer\Validator\PluginManager:
QueryStringScalarArray: OpenAPIGenerator\Common\Validator\QueryStringScalarArray
abstract_factories:
- Articus\DataTransfer\Validator\Factory\Laminas
validators:
invokables:
Count: Laminas\Validator\IsCountable

View File

@ -1,8 +1,13 @@
dependencies:
factories:
Mezzio\Router\RouterInterface: Articus\PathHandler\RouteInjection\Factory
Mezzio\Router\RouterInterface: Articus\PathHandler\RouteInjectionFactory
Articus\PathHandler\MetadataProviderInterface: Articus\PathHandler\MetadataProvider\Factory\PhpAttribute
Articus\PathHandler\Handler\PluginManager: Articus\PathHandler\Handler\Factory\PluginManager
Articus\PathHandler\Consumer\PluginManager: Articus\PathHandler\Consumer\Factory\PluginManager
Articus\PathHandler\Attribute\PluginManager: Articus\PathHandler\Attribute\Factory\PluginManager
Articus\PathHandler\Producer\PluginManager: Articus\PathHandler\Producer\Factory\PluginManager
Articus\PathHandler\RouteInjection\Factory:
Articus\PathHandler\RouteInjectionFactory:
paths:
'/v2':
- App\Handler\Pet
@ -19,18 +24,22 @@ Articus\PathHandler\RouteInjection\Factory:
- App\Handler\UserLogin
- App\Handler\UserLogout
- App\Handler\UserUsername
handlers:
abstract_factories:
- Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory
# consumers:
# factories:
# invokables:
# attributes:
# factories:
# invokables:
# producers:
# factories:
# invokables:
Articus\PathHandler\Handler\PluginManager:
abstract_factories:
- Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory
#Articus\PathHandler\Consumer\PluginManager:
# factories:
# invokables:
#Articus\PathHandler\Attribute\PluginManager:
# factories:
# invokables:
#Articus\PathHandler\Producer\PluginManager:
# factories:
# invokables:
Laminas\ServiceManager\AbstractFactory\ConfigAbstractFactory:
App\Handler\Pet: []

View File

@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
use Laminas\Config\Factory as ConfigFactory;
//Use Composer autoload that includes code both from ../src and ../vendor
require __DIR__ . '/../vendor/autoload.php';
//Path to file for caching full configuration
const CONFIG_CACHE_PATH = __DIR__ . '/../data/cache/config.php';
//Get full configuration
$config = [];
if (is_readable(CONFIG_CACHE_PATH)) {
$config = include CONFIG_CACHE_PATH;
} else {
//Register extra extension for YAML files
ConfigFactory::registerReader('yml', 'yaml');
//Combine all configuration files in right order
$config = ConfigFactory::fromFiles([
__DIR__ . '/config/data_transfer.yml',
__DIR__ . '/config/path_handler.yml',
__DIR__ . '/config/app.yml',
__DIR__ . '/config.yml',
]);
//Cache full configuration
if ($config['cache_configuration'] ?? false) {
if (!ConfigFactory::toFile(CONFIG_CACHE_PATH, $config)) {
throw new \RuntimeException('Failed to cache configuration');
}
}
}
//Create container
$container = new \Laminas\ServiceManager\ServiceManager($config['dependencies'] ?? []);
//Register full configuration as a service
$container->setService('config', $config);
$container->setAlias('Config', 'config');
return $container;

View File

@ -0,0 +1,26 @@
{
"name": "git_user_id/git_repo_id",
"description": "",
"license": "unlicense",
"version": "1.0.0",
"type": "project",
"require": {
"php": "^8.0",
"ext-yaml": "^2.2",
"mezzio/mezzio": "^3.3",
"laminas/laminas-diactoros": "^2.5",
"articus/path-handler": "^0.7",
"articus/data-transfer": "^0.5",
"articus/openapi-generator-common": "^0.2",
"psr/simple-cache": "^1.0",
"laminas/laminas-config": "^3.4",
"laminas/laminas-stdlib": "^3.3",
"laminas/laminas-validator": "^2.14",
"nikic/fast-route": "^1.3"
},
"autoload": {
"psr-4": {
"": "src/"
}
}
}

View File

@ -0,0 +1,11 @@
<?php
declare(strict_types=1);
chdir(dirname(__DIR__));
/** @var \Laminas\ServiceManager\ServiceManager $container */
$container = require_once __DIR__.'/../application/container.php';
/** @var \Mezzio\Application $app */
$app = $container->get(\Mezzio\Application::class);
$app->run();

View File

@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
/**
* Describes the result of uploading an image resource
*/
class ApiResponse
{
#[DTA\Data(field: "code", nullable: true)]
#[DTA\Validator("Scalar", ["type" => "int"])]
public int|null $code = null;
#[DTA\Data(field: "type", nullable: true)]
#[DTA\Validator("Scalar", ["type" => "string"])]
public string|null $type = null;
#[DTA\Data(field: "message", nullable: true)]
#[DTA\Validator("Scalar", ["type" => "string"])]
public string|null $message = null;
}

View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
/**
* A category for a pet
*/
class Category
{
#[DTA\Data(field: "id", nullable: true)]
#[DTA\Validator("Scalar", ["type" => "int"])]
public int|null $id = null;
#[DTA\Data(field: "name", nullable: true)]
#[DTA\Validator("Scalar", ["type" => "string"])]
#[DTA\Validator("Regex", ["pattern" => "/^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$/"])]
public string|null $name = null;
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ScalarList", ["type" => "string"])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "Scalar", "options" => ["type" => "string"]]
]])]
class Collection extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ObjectList", ["type" => \App\DTO\Tag::class])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "TypeCompliant", "options" => ["type" => \App\DTO\Tag::class]]
]])]
class Collection1 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ScalarList", ["type" => "string"])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "Scalar", "options" => ["type" => "string"]]
]])]
class Collection10 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ObjectList", ["type" => \App\DTO\Tag::class])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "TypeCompliant", "options" => ["type" => \App\DTO\Tag::class]]
]])]
class Collection11 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ScalarList", ["type" => "string"])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "Scalar", "options" => ["type" => "string"]]
]])]
class Collection12 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ObjectList", ["type" => \App\DTO\Tag::class])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "TypeCompliant", "options" => ["type" => \App\DTO\Tag::class]]
]])]
class Collection13 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ScalarList", ["type" => "string"])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "Scalar", "options" => ["type" => "string"]]
]])]
class Collection14 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ObjectList", ["type" => \App\DTO\Tag::class])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "TypeCompliant", "options" => ["type" => \App\DTO\Tag::class]]
]])]
class Collection15 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ScalarList", ["type" => "string"])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "Scalar", "options" => ["type" => "string"]]
]])]
class Collection16 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ScalarList", ["type" => "string"])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "Scalar", "options" => ["type" => "string"]]
]])]
class Collection17 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ObjectList", ["type" => \App\DTO\Tag::class])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "TypeCompliant", "options" => ["type" => \App\DTO\Tag::class]]
]])]
class Collection18 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ObjectList", ["type" => \App\DTO\Pet::class])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "TypeCompliant", "options" => ["type" => \App\DTO\Pet::class]]
]])]
class Collection19 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ScalarList", ["type" => "string"])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "Scalar", "options" => ["type" => "string"]]
]])]
class Collection2 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ScalarList", ["type" => "string"])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "Scalar", "options" => ["type" => "string"]]
]])]
class Collection20 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ObjectList", ["type" => \App\DTO\Tag::class])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "TypeCompliant", "options" => ["type" => \App\DTO\Tag::class]]
]])]
class Collection21 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ObjectList", ["type" => \App\DTO\Pet::class])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "TypeCompliant", "options" => ["type" => \App\DTO\Pet::class]]
]])]
class Collection22 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ScalarList", ["type" => "string"])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "Scalar", "options" => ["type" => "string"]]
]])]
class Collection23 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ScalarList", ["type" => "string"])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "Scalar", "options" => ["type" => "string"]]
]])]
class Collection24 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ObjectList", ["type" => \App\DTO\Tag::class])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "TypeCompliant", "options" => ["type" => \App\DTO\Tag::class]]
]])]
class Collection25 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ObjectList", ["type" => \App\DTO\Pet::class])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "TypeCompliant", "options" => ["type" => \App\DTO\Pet::class]]
]])]
class Collection26 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ScalarList", ["type" => "string"])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "Scalar", "options" => ["type" => "string"]]
]])]
class Collection27 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ObjectList", ["type" => \App\DTO\Tag::class])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "TypeCompliant", "options" => ["type" => \App\DTO\Tag::class]]
]])]
class Collection28 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ObjectList", ["type" => \App\DTO\Pet::class])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "TypeCompliant", "options" => ["type" => \App\DTO\Pet::class]]
]])]
class Collection29 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ObjectList", ["type" => \App\DTO\Tag::class])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "TypeCompliant", "options" => ["type" => \App\DTO\Tag::class]]
]])]
class Collection3 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ScalarList", ["type" => "string"])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "Scalar", "options" => ["type" => "string"]]
]])]
class Collection30 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ObjectList", ["type" => \App\DTO\Tag::class])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "TypeCompliant", "options" => ["type" => \App\DTO\Tag::class]]
]])]
class Collection31 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ScalarList", ["type" => "string"])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "Scalar", "options" => ["type" => "string"]]
]])]
class Collection32 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ObjectList", ["type" => \App\DTO\Tag::class])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "TypeCompliant", "options" => ["type" => \App\DTO\Tag::class]]
]])]
class Collection33 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ScalarMap", ["type" => "int"])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "Scalar", "options" => ["type" => "int"]]
]])]
class Collection34 extends \ArrayObject
{
}

View File

@ -0,0 +1,14 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\PhpAttribute as DTA;
#[DTA\Strategy("ObjectList", ["type" => \App\DTO\User::class])]
#[DTA\Validator("Collection", ["validators" => [
["name" => "TypeCompliant", "options" => ["type" => \App\DTO\User::class]]
]])]
class Collection35 extends \ArrayObject
{
}

Some files were not shown because too many files have changed in this diff Show More