[PHP][php-ze-ph] Support for PHP 7.1+, Zend Expressive 3.2 and PathHander 0.4 (#1902)

* - support for PHP 7.1, Zend Expressive 3.2 and PathHander 0.4 for php-ze-ph generator

* - fixed mess with petstore samples (added new files, removed obsolete files)

* php-ze-ph:
- overwriting "*/*" media type for producers with "n/a" (PathHandler does not support that cause it makes no sense to return response with "Content-Type: */*")
- "array" return type declaration for handler methods with ambiguous "container" return type
- better way to generate attribute annotation stub for request body data with ambiguous "container" type
- fixed missing dependency in composer.json
- minor optimization for container.php
- samples for OAS3 petstore spec

* php-ze-ph:
- note about ext-yaml in stub README
- updated .gitignore

* php-ze-ph:
- logging '*/*' replacement as warning
This commit is contained in:
Arthur Mogliev 2019-01-30 11:36:00 +04:00 committed by William Cheng
parent c871e3bc81
commit 77d2de4e3d
199 changed files with 4098 additions and 587 deletions

View File

@ -22,11 +22,15 @@ executable="./modules/openapi-generator-cli/target/openapi-generator-cli.jar"
if [ ! -f "$executable" ] if [ ! -f "$executable" ]
then then
mvn clean package mvn -B clean package
fi fi
input=modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml
out_folder=samples/server/openapi3/petstore/php-ze-ph
resources=modules/openapi-generator/src/main/resources/ze-ph
# if you've executed sbt assembly previously it will use that instead. # if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="generate -t modules/openapi-generator/src/main/resources/ze-ph -i modules/openapi-generator/src/test/resources/3_0/petstore-with-fake-endpoints-models-for-testing.yaml -g php-ze-ph -o samples/server/petstore/ze-ph $@" ags="generate -t $resources -i $input -g php-ze-ph -o $out_folder $@"
java $JAVA_OPTS -jar $executable $ags java $JAVA_OPTS -jar $executable $ags

View File

@ -25,8 +25,12 @@ then
mvn -B clean package mvn -B clean package
fi fi
input=modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml
out_folder=samples/server/petstore/php-ze-ph
resources=modules/openapi-generator/src/main/resources/ze-ph
# if you've executed sbt assembly previously it will use that instead. # if you've executed sbt assembly previously it will use that instead.
export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties" export JAVA_OPTS="${JAVA_OPTS} -XX:MaxPermSize=256M -Xmx1024M -DloggerPath=conf/log4j.properties"
ags="generate -t modules/openapi-generator/src/main/resources/ze-ph -i modules/openapi-generator/src/test/resources/2_0/petstore-with-fake-endpoints-models-for-testing.yaml -g php-ze-ph -o samples/server/petstore/php-ze-ph $@" ags="generate -t $resources -i $input -g php-ze-ph -o $out_folder $@"
java $JAVA_OPTS -jar $executable $ags java $JAVA_OPTS -jar $executable $ags

View File

@ -26,11 +26,14 @@ import io.swagger.v3.oas.models.parameters.Parameter;
import io.swagger.v3.oas.models.parameters.QueryParameter; import io.swagger.v3.oas.models.parameters.QueryParameter;
import org.openapitools.codegen.*; import org.openapitools.codegen.*;
import org.openapitools.codegen.utils.ModelUtils; import org.openapitools.codegen.utils.ModelUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.util.*; import java.util.*;
public class PhpZendExpressivePathHandlerServerCodegen extends AbstractPhpCodegen { public class PhpZendExpressivePathHandlerServerCodegen extends AbstractPhpCodegen {
private static final Logger LOGGER = LoggerFactory.getLogger(PhpZendExpressivePathHandlerServerCodegen.class);
public static final String VEN_FROM_QUERY = "internal.ze-ph.fromQuery"; 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_COLLECTION_FORMAT = "internal.ze-ph.collectionFormat";
@ -78,7 +81,8 @@ public class PhpZendExpressivePathHandlerServerCodegen extends AbstractPhpCodege
supportingFiles.add(new SupportingFile("app.yml.mustache", "application" + File.separator + "config", "app.yml")); supportingFiles.add(new SupportingFile("app.yml.mustache", "application" + File.separator + "config", "app.yml"));
supportingFiles.add(new SupportingFile("path_handler.yml.mustache", "application" + File.separator + "config", "path_handler.yml")); supportingFiles.add(new SupportingFile("path_handler.yml.mustache", "application" + File.separator + "config", "path_handler.yml"));
supportingFiles.add(new SupportingFile("data_transfer.yml.mustache", "application" + File.separator + "config", "data_transfer.yml")); supportingFiles.add(new SupportingFile("data_transfer.yml.mustache", "application" + File.separator + "config", "data_transfer.yml"));
supportingFiles.add(new SupportingFile("ErrorMiddleware.php.mustache", srcBasePath, "ErrorMiddleware.php")); supportingFiles.add(new SupportingFile("Factory.php.mustache", srcBasePath, "Factory.php"));
supportingFiles.add(new SupportingFile("InternalServerError.php.mustache", srcBasePath + File.separator + "Middleware", "InternalServerError.php"));
supportingFiles.add(new SupportingFile("Date.php.mustache", srcBasePath + File.separator + "Strategy", "Date.php")); supportingFiles.add(new SupportingFile("Date.php.mustache", srcBasePath + File.separator + "Strategy", "Date.php"));
supportingFiles.add(new SupportingFile("DateTime.php.mustache", srcBasePath + File.separator + "Strategy", "DateTime.php")); supportingFiles.add(new SupportingFile("DateTime.php.mustache", srcBasePath + File.separator + "Strategy", "DateTime.php"));
supportingFiles.add(new SupportingFile("QueryParameter.php.mustache", srcBasePath + File.separator + "Strategy", "QueryParameter.php")); supportingFiles.add(new SupportingFile("QueryParameter.php.mustache", srcBasePath + File.separator + "Strategy", "QueryParameter.php"));
@ -291,46 +295,42 @@ public class PhpZendExpressivePathHandlerServerCodegen extends AbstractPhpCodege
objs = super.postProcessOperationsWithModels(objs, allModels); objs = super.postProcessOperationsWithModels(objs, allModels);
Map<String, Object> operations = (Map<String, Object>) objs.get("operations"); Map<String, Object> operations = (Map<String, Object>) objs.get("operations");
List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation"); List<CodegenOperation> operationList = (List<CodegenOperation>) operations.get("operation");
String interfaceToImplement; String httpMethodDeclaration;
StringBuilder interfacesToImplement = new StringBuilder();
String classMethod;
String pathPattern = null; String pathPattern = null;
for (CodegenOperation op : operationList) { for (CodegenOperation op : operationList) {
switch (op.httpMethod) { switch (op.httpMethod) {
case "GET": case "GET":
interfaceToImplement = "Operation\\GetInterface"; httpMethodDeclaration = "Get()";
classMethod = "handleGet";
break; break;
case "POST": case "POST":
interfaceToImplement = "Operation\\PostInterface"; httpMethodDeclaration = "Post()";
classMethod = "handlePost";
break; break;
case "PATCH": case "PATCH":
interfaceToImplement = "Operation\\PatchInterface"; httpMethodDeclaration = "Patch()";
classMethod = "handlePatch";
break; break;
case "PUT": case "PUT":
interfaceToImplement = "Operation\\PutInterface"; httpMethodDeclaration = "Put()";
classMethod = "handlePut";
break; break;
case "DELETE": case "DELETE":
interfaceToImplement = "Operation\\DeleteInterface"; httpMethodDeclaration = "Delete()";
classMethod = "handleDelete";
break; break;
default: default:
throw new RuntimeException("Unknown HTTP Method " + op.httpMethod + " not allowed"); httpMethodDeclaration = "HttpMethod(\"" + op.httpMethod + "\")";
} }
if (interfacesToImplement.length() > 0) { op.httpMethod = httpMethodDeclaration;
interfacesToImplement.append(", "); //Producing content with media type "*/*" is not supported
if (op.produces != null) {
for (Map<String, String> p: op.produces) {
if (p.replace("mediaType", "*/*", "n/a")) {
LOGGER.warn("Media type range '*/*' is not supported, using 'n/a' for code generation instead");
}
}
} }
interfacesToImplement.append(interfaceToImplement);
op.httpMethod = classMethod;
//All operations have same path because of custom operation grouping, so path pattern can be calculated only once //All operations have same path because of custom operation grouping, so path pattern can be calculated only once
if (pathPattern == null) { if (pathPattern == null) {
pathPattern = generatePathPattern(op); pathPattern = generatePathPattern(op);
} }
} }
operations.put("interfacesToImplement", interfacesToImplement.toString());
operations.put("pathPattern", pathPattern); operations.put("pathPattern", pathPattern);
return objs; return objs;

View File

@ -1,26 +1,9 @@
# ref: https://github.com/github/gitignore/blob/master/ZendFramework.gitignore #based on .gitignore generated by https://github.com/zendframework/zend-expressive-skeleton
.idea
# Composer files # Composer files
composer.phar composer.phar
vendor/ vendor/
# Local configs # Default cache folder
config/autoload/*.local.php
# Binary gettext files
*.mo
# Data
data/logs/
data/cache/ data/cache/
data/sessions/
data/tmp/
temp/
#Doctrine 2
data/DoctrineORMModule/Proxy/
data/DoctrineORMModule/cache/
# Legacy ZF1
demos/
extras/documentation

View File

@ -1,4 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace {{invokerPackage}}\Strategy; namespace {{invokerPackage}}\Strategy;
@ -7,8 +8,7 @@ class Date extends DateTime
const DATE_TIME_FORMAT = 'Y-m-d'; const DATE_TIME_FORMAT = 'Y-m-d';
/** /**
* @param $arrayValue * @inheritdoc
* @return \DateTime
*/ */
protected function parseDateString($arrayValue) protected function parseDateString($arrayValue)
{ {

View File

@ -1,4 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace {{invokerPackage}}\Strategy; namespace {{invokerPackage}}\Strategy;
@ -9,7 +10,7 @@ class DateTime implements StrategyInterface
const DATE_TIME_FORMAT = \DateTime::RFC3339; const DATE_TIME_FORMAT = \DateTime::RFC3339;
/** /**
* @inheritDoc * @inheritdoc
*/ */
public function extract($objectValue, $object = null) public function extract($objectValue, $object = null)
{ {
@ -21,7 +22,7 @@ class DateTime implements StrategyInterface
} }
/** /**
* @inheritDoc * @inheritdoc
*/ */
public function hydrate($arrayValue, $objectValue, array $array = null) public function hydrate($arrayValue, $objectValue, array $array = null)
{ {
@ -37,7 +38,7 @@ class DateTime implements StrategyInterface
/** /**
* @param $arrayValue * @param $arrayValue
* @return \DateTime * @return bool|\DateTime
*/ */
protected function parseDateString($arrayValue) protected function parseDateString($arrayValue)
{ {

View File

@ -1,34 +0,0 @@
<?php
namespace {{invokerPackage}};
use Interop\Http\ServerMiddleware\DelegateInterface;
use Interop\Http\ServerMiddleware\MiddlewareInterface;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Zend\Stdlib\ErrorHandler;
class ErrorMiddleware implements MiddlewareInterface
{
public function process(Request $request, DelegateInterface $delegate)
{
$result = null;
try {
ErrorHandler::start();
$result = $delegate->process($request);
ErrorHandler::stop(true);
if (!($result instanceof Response)) {
throw new \RuntimeException(sprintf(
'Invalid response: expecting %s, got %s',
Response::class,
is_object($result)? get_class($result) : gettype($result)
));
}
}
catch (\Exception $error) {
$result = (new \Zend\Diactoros\Response())->withStatus(500, 'Internal server error');
error_log((string)$error);
}
return $result;
}
}

View File

@ -0,0 +1,58 @@
<?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 Zend\Expressive\Application;
use Zend\Expressive\Handler\NotFoundHandler;
use Zend\Expressive\MiddlewareFactory;
use Zend\Expressive\Router\Middleware\DispatchMiddleware;
use Zend\Expressive\Router\Middleware\MethodNotAllowedMiddleware;
use Zend\Expressive\Router\Middleware\RouteMiddleware;
use Zend\Expressive\Router\RouteCollector;
use Zend\HttpHandlerRunner\Emitter\EmitterInterface;
use Zend\HttpHandlerRunner\RequestHandlerRunner;
use Zend\ServiceManager\Factory\FactoryInterface;
use Zend\Stratigility\MiddlewarePipe;
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)
));
}
$pipeline = new MiddlewarePipe();
$runner = new RequestHandlerRunner(
$pipeline,
$container->get(EmitterInterface::class),
$container->get(ServerRequestInterface::class),
function(\Throwable $error) use ($errorMiddleware) : ResponseInterface
{
return $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;
}
}

View File

@ -0,0 +1,54 @@
<?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 Zend\Stdlib\ErrorHandler;
class InternalServerError implements MiddlewareInterface
{
/**
* @var callable
*/
protected $responseGenerator;
/**
* @param callable $responseGenerator
*/
public function __construct(callable $responseGenerator)
{
$this->responseGenerator = $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

@ -1,4 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace {{invokerPackage}}\Strategy; namespace {{invokerPackage}}\Strategy;
@ -31,7 +32,7 @@ class QueryParameter implements StrategyInterface
if (empty($options['type'])) { if (empty($options['type'])) {
throw new \InvalidArgumentException('Option "type" is required.'); throw new \InvalidArgumentException('Option "type" is required.');
} elseif (!isset(self::TYPE_MAP[$options['type']])) { } elseif (!isset(self::TYPE_MAP[$options['type']])) {
throw new \InvalidArgumentException(sprintf('Unknown type "%s".', $options['type'])); throw new \InvalidArgumentException(\sprintf('Unknown type "%s".', $options['type']));
} }
$this->type = $options['type']; $this->type = $options['type'];
} }

View File

@ -1,4 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace {{invokerPackage}}\Strategy; namespace {{invokerPackage}}\Strategy;
@ -28,8 +29,8 @@ class QueryParameterArray extends QueryParameter
parent::__construct($options); parent::__construct($options);
if (empty($options['format'])) { if (empty($options['format'])) {
throw new \InvalidArgumentException('Option "format" is required.'); throw new \InvalidArgumentException('Option "format" is required.');
} elseif (!array_key_exists($options['format'], self::DELIMITER_MAP)) { } elseif (!\array_key_exists($options['format'], self::DELIMITER_MAP)) {
throw new \InvalidArgumentException(sprintf('Unknown format "%s".', $options['format'])); throw new \InvalidArgumentException(\sprintf('Unknown format "%s".', $options['format']));
} }
$this->delimiter = self::DELIMITER_MAP[$options['format']]; $this->delimiter = self::DELIMITER_MAP[$options['format']];
} }
@ -40,11 +41,11 @@ class QueryParameterArray extends QueryParameter
public function extract($objectValue, $object = null) public function extract($objectValue, $object = null)
{ {
$result = null; $result = null;
if (is_array($objectValue)) { if (\is_array($objectValue)) {
if ($this->delimiter === null) { if ($this->delimiter === null) {
$result = $objectValue; $result = $objectValue;
} else { } else {
$result = implode($this->delimiter, $objectValue); $result = \implode($this->delimiter, $objectValue);
} }
} }
return $result; return $result;
@ -59,9 +60,9 @@ class QueryParameterArray extends QueryParameter
if ($arrayValue !== null) { if ($arrayValue !== null) {
$list = null; $list = null;
if ($this->delimiter === null) { if ($this->delimiter === null) {
$list = (is_array($arrayValue))? $arrayValue : [$arrayValue]; $list = (\is_array($arrayValue))? $arrayValue : [$arrayValue];
} else { } else {
$list = explode($this->delimiter, $arrayValue); $list = \explode($this->delimiter, $arrayValue);
} }
$result = []; $result = [];
foreach ($list as $item) { foreach ($list as $item) {

View File

@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace {{invokerPackage}}\Validator; namespace {{invokerPackage}}\Validator;
use App\Strategy\QueryParameterArray; use App\Strategy\QueryParameterArray;
@ -6,14 +8,14 @@ use App\Strategy\QueryParameterArray;
class QueryParameterArrayType extends QueryParameterType class QueryParameterArrayType extends QueryParameterType
{ {
/** /**
* @var string * @var null|string
*/ */
protected $format; protected $format;
/** /**
* @return string * @return string
*/ */
public function getFormat() public function getFormat(): ?string
{ {
return $this->format; return $this->format;
} }
@ -22,21 +24,21 @@ class QueryParameterArrayType extends QueryParameterType
* @param string $format * @param string $format
* @return self * @return self
*/ */
public function setFormat($format) public function setFormat(string $format): self
{ {
$this->format = $format; $this->format = $format;
return $this; return $this;
} }
protected function checkType($value) protected function checkType($value): bool
{ {
$result = true; $result = true;
if (!array_key_exists($this->format, QueryParameterArray::DELIMITER_MAP)) { if (!\array_key_exists($this->format, QueryParameterArray::DELIMITER_MAP)) {
throw new \InvalidArgumentException(sprintf('Can not check for format %s.', $this->format)); throw new \InvalidArgumentException(\sprintf('Can not check for format %s.', $this->format));
} }
$delimiter = QueryParameterArray::DELIMITER_MAP[$this->format]; $delimiter = QueryParameterArray::DELIMITER_MAP[$this->format];
if ($delimiter === null) { if ($delimiter === null) {
if (is_array($value)) { if (\is_array($value)) {
foreach ($value as $item) { foreach ($value as $item) {
$result = $result && parent::checkType($item); $result = $result && parent::checkType($item);
} }
@ -46,27 +48,27 @@ class QueryParameterArrayType extends QueryParameterType
} else { } else {
switch ($this->type) { switch ($this->type) {
case QueryParameterArray::TYPE_INT: case QueryParameterArray::TYPE_INT:
$result = is_string($value) && preg_match(self::prepareRepeatingTypeRegExp(self::RE_INT, $delimiter), $value); $result = \is_string($value) && \preg_match(self::prepareRepeatingTypeRegExp(self::RE_INT, $delimiter), $value);
break; break;
case QueryParameterArray::TYPE_BOOL: case QueryParameterArray::TYPE_BOOL:
$result = is_string($value) && preg_match(self::prepareRepeatingTypeRegExp(self::RE_BOOL, $delimiter), $value); $result = \is_string($value) && \preg_match(self::prepareRepeatingTypeRegExp(self::RE_BOOL, $delimiter), $value);
break; break;
case QueryParameterArray::TYPE_FLOAT: case QueryParameterArray::TYPE_FLOAT:
$result = is_string($value) && preg_match(self::prepareRepeatingTypeRegExp(self::RE_FLOAT, $delimiter), $value); $result = \is_string($value) && \preg_match(self::prepareRepeatingTypeRegExp(self::RE_FLOAT, $delimiter), $value);
break; break;
case QueryParameterArray::TYPE_STRING: case QueryParameterArray::TYPE_STRING:
$result = is_string($value); $result = \is_string($value);
break; break;
default: default:
throw new \InvalidArgumentException(sprintf('Can not check for type %s.', $this->type)); throw new \InvalidArgumentException(\sprintf('Can not check for type %s.', $this->type));
} }
} }
return $result; return $result;
} }
protected static function prepareRepeatingTypeRegExp($typeRegExp, $delimiter) protected static function prepareRepeatingTypeRegExp(string $typeRegExp, string $delimiter): string
{ {
$escapedDelimiter = preg_quote($delimiter, '/'); $escapedDelimiter = \preg_quote($delimiter, '/');
return '/^(' . $typeRegExp . ')(' . $escapedDelimiter . '('. $typeRegExp . '))*$/'; return '/^(' . $typeRegExp . ')(' . $escapedDelimiter . '('. $typeRegExp . '))*$/';
} }
} }

View File

@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace {{invokerPackage}}\Validator; namespace {{invokerPackage}}\Validator;
use App\Strategy\QueryParameter; use App\Strategy\QueryParameter;
@ -9,19 +11,19 @@ class QueryParameterType extends Type
const RE_BOOL = 'true|false'; const RE_BOOL = 'true|false';
const RE_FLOAT = '0(\.\d+)?|-?[1-9]\d*(\.\d+)?|-0\.\d+'; const RE_FLOAT = '0(\.\d+)?|-?[1-9]\d*(\.\d+)?|-0\.\d+';
protected function checkType($value) protected function checkType($value): bool
{ {
switch ($this->type) { switch ($this->type) {
case QueryParameter::TYPE_INT: case QueryParameter::TYPE_INT:
return is_string($value) && preg_match('/^(' . self::RE_INT . ')$/', $value); return \is_string($value) && \preg_match('/^(' . self::RE_INT . ')$/', $value);
case QueryParameter::TYPE_BOOL: case QueryParameter::TYPE_BOOL:
return is_string($value) && preg_match('/^(' . self::RE_BOOL . ')$/', $value); return \is_string($value) && \preg_match('/^(' . self::RE_BOOL . ')$/', $value);
case QueryParameter::TYPE_FLOAT: case QueryParameter::TYPE_FLOAT:
return is_string($value) && preg_match('/^(' . self::RE_FLOAT . ')$/', $value); return \is_string($value) && \preg_match('/^(' . self::RE_FLOAT . ')$/', $value);
case QueryParameter::TYPE_STRING: case QueryParameter::TYPE_STRING:
return is_string($value); return \is_string($value);
default: default:
throw new \InvalidArgumentException(sprintf('Can not check for type %s.', $this->type)); throw new \InvalidArgumentException(\sprintf('Can not check for type %s.', $this->type));
} }
} }
} }

View File

@ -5,14 +5,14 @@ Generated by the [OpenAPI Generator](https://openapi-generator.tech) project.
## Overview ## Overview
This server stub aims to provide light, yet comprehensive structure for your API project using: This server stub aims to provide light, yet comprehensive structure for your API project using:
- PHP: 5.6 or 7.* - PHP: >=7.1
- [Zend Expressive](https://zendframework.github.io/zend-expressive): 2.1 - [Zend Expressive](https://zendframework.github.io/zend-expressive): >=3.2
- [Path Handler](https://github.com/Articus/PathHandler): 0.3 - [Path Handler](https://github.com/Articus/PathHandler): >=0.4
## How to use ## How to use
All you have to do to start development is: All you have to do to start development is:
- install dependencies via [Composer](https://getcomposer.org/) - 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/ZendCache` (you will need it later for configuration and metadata caches - check comments in `./application/config.yml`) - create cache folder: `mkdir -p ./data/cache/ZendCache` (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`) - 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`)
@ -24,11 +24,11 @@ After that you should be able to call all methods from your API spec. Most of th
- `400 Malformed JSON` for unparsable JSON body - `400 Malformed JSON` for unparsable JSON body
- `422 Unprocessable entity` for parsable JSON body that fails validation - `422 Unprocessable entity` for parsable JSON body that fails validation
But for obvious reason you will not get any `200 OK`, only `500 Not implemented`. So your next steps are: 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 - 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 API security mechanism (either special attribute or separate middleware) - generator does not do anything about it yet
- implement your handlers - the most tricky part :) - implement your handlers - the most tricky part :)
## Enjoy! ## Enjoy!
Hopefully this stub will reduce the amount of boilerplate code you have to write manually. If you have any suggestions or questions about `ze-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). Hopefully this stub will reduce the amount of boilerplate code you have to write manually. If you have any suggestions or questions about `php-ze-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

@ -1,4 +1,6 @@
<?php <?php
declare(strict_types=1);
namespace {{invokerPackage}}\Validator; namespace {{invokerPackage}}\Validator;
use Zend\Validator\AbstractValidator; use Zend\Validator\AbstractValidator;
@ -18,14 +20,14 @@ class Type extends AbstractValidator
]; ];
/** /**
* @var string * @var null|string
*/ */
protected $type; protected $type;
/** /**
* @return mixed * @return string
*/ */
public function getType() public function getType(): ?string
{ {
return $this->type; return $this->type;
} }
@ -34,14 +36,14 @@ class Type extends AbstractValidator
* @param string $type * @param string $type
* @return self * @return self
*/ */
public function setType($type) public function setType(string $type): self
{ {
$this->type = $type; $this->type = $type;
return $this; return $this;
} }
/** /**
* @inheritDoc * @inheritdoc
*/ */
public function isValid($value) public function isValid($value)
{ {
@ -53,19 +55,19 @@ class Type extends AbstractValidator
return $result; return $result;
} }
protected function checkType($value) protected function checkType($value): bool
{ {
switch ($this->type) { switch ($this->type) {
case 'int': case 'int':
return is_int($value); return \is_int($value);
case 'bool': case 'bool':
return is_bool($value); return \is_bool($value);
case 'float': case 'float':
return is_float($value) || is_int($value); return \is_float($value) || \is_int($value);
case 'string': case 'string':
return is_string($value); return \is_string($value);
default: default:
throw new \InvalidArgumentException(sprintf('Can not check for type %s.', $this->type)); throw new \InvalidArgumentException(\sprintf('Can not check for type %s.', $this->type));
} }
} }
} }

View File

@ -1,8 +1,8 @@
<?php <?php
declare(strict_types=1);
namespace {{package}}; namespace {{package}};
use Articus\PathHandler\Operation;
use Articus\PathHandler\Annotation as PHA; use Articus\PathHandler\Annotation as PHA;
use Articus\PathHandler\Consumer as PHConsumer; use Articus\PathHandler\Consumer as PHConsumer;
use Articus\PathHandler\Producer as PHProducer; use Articus\PathHandler\Producer as PHProducer;
@ -17,7 +17,7 @@ use Psr\Http\Message\ServerRequestInterface;
{{/description}} {{/description}}
* @PHA\Route(pattern="{{pathPattern}}") * @PHA\Route(pattern="{{pathPattern}}")
*/ */
class {{classname}} implements {{interfacesToImplement}} class {{classname}}
{ {
{{#operation}} {{#operation}}
/** /**
@ -27,6 +27,7 @@ class {{classname}} implements {{interfacesToImplement}}
{{#description}} {{#description}}
* {{description}} * {{description}}
{{/description}} {{/description}}
* @PHA\{{httpMethod}}
{{#vendorExtensions}} {{#vendorExtensions}}
{{#internal.ze-ph.hasQueryData}} {{#internal.ze-ph.hasQueryData}}
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={ * @PHA\Attribute(name=PHAttribute\Transfer::class, options={
@ -44,8 +45,11 @@ class {{classname}} implements {{interfacesToImplement}}
{{^isPrimitiveType}} {{^isPrimitiveType}}
{{#isContainer}} {{#isContainer}}
* TODO check if attribute is valid and can handle your container type * 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}}
{{^isContainer}}
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={"type":{{dataType}}::class,"objectAttr":"bodyData"}) * @PHA\Attribute(name=PHAttribute\Transfer::class, options={"type":{{dataType}}::class,"objectAttr":"bodyData"})
{{/isContainer}}
{{/isPrimitiveType}} {{/isPrimitiveType}}
{{/bodyParam}} {{/bodyParam}}
{{#produces}} {{#produces}}
@ -54,13 +58,16 @@ class {{classname}} implements {{interfacesToImplement}}
{{/produces}} {{/produces}}
* @param ServerRequestInterface $request * @param ServerRequestInterface $request
* *
* @throws PHException\HttpCode 500 if the method is not implemented * @throws PHException\HttpCode 501 if the method is not implemented
{{#returnType}} {{#returnType}}
* *
{{#returnContainer}}
* TODO check if generated return container type is valid
{{/returnContainer}}
* @return {{returnType}} * @return {{returnType}}
{{/returnType}} {{/returnType}}
*/ */
public function {{httpMethod}}(ServerRequestInterface $request) public function {{operationId}}(ServerRequestInterface $request){{#returnType}}: {{#returnContainer}}array{{/returnContainer}}{{^returnContainer}}{{returnType}}{{/returnContainer}}{{/returnType}}
{ {
//TODO implement method //TODO implement method
{{#vendorExtensions}} {{#vendorExtensions}}
@ -75,7 +82,7 @@ class {{classname}} implements {{interfacesToImplement}}
$bodyData = $request->getAttribute("bodyData"); $bodyData = $request->getAttribute("bodyData");
{{/isPrimitiveType}} {{/isPrimitiveType}}
{{/bodyParam}} {{/bodyParam}}
throw new PHException\HttpCode(500, "Not implemented"); throw new PHException\HttpCode(501, "Not implemented");
} }
{{/operation}} {{/operation}}
} }

View File

@ -1,14 +1,23 @@
dependencies: dependencies:
invokables: invokables:
Zend\Diactoros\Response\EmitterInterface: Zend\Diactoros\Response\SapiStreamEmitter Zend\HttpHandlerRunner\Emitter\EmitterInterface: Zend\HttpHandlerRunner\Emitter\SapiStreamEmitter
App\ErrorMiddleware: App\ErrorMiddleware
factories: factories:
Zend\Expressive\Application: Zend\Expressive\Container\ApplicationFactory Zend\Expressive\Application: App\Factory
Articus\PathHandler\Middleware: Articus\PathHandler\MiddlewareFactory Zend\Expressive\MiddlewareContainer: Zend\Expressive\Container\MiddlewareContainerFactory
Zend\Expressive\MiddlewareFactory: Zend\Expressive\Container\MiddlewareFactoryFactory
Zend\Expressive\Router\RouteCollector: Zend\Expressive\Router\RouteCollectorFactory
Zend\Expressive\Router\RouterInterface: Articus\PathHandler\RouteInjection\Factory
middleware_pipeline: Psr\Http\Message\ServerRequestInterface: Zend\Expressive\Container\ServerRequestFactoryFactory
error: Psr\Http\Message\StreamInterface: Zend\Expressive\Container\StreamFactoryFactory
middleware: App\ErrorMiddleware Psr\Http\Message\ResponseInterface: Zend\Expressive\Container\ResponseFactoryFactory
api:
middleware: Articus\PathHandler\Middleware Zend\Expressive\Router\Middleware\RouteMiddleware: Zend\Expressive\Router\Middleware\RouteMiddlewareFactory
path: {{basePathWithoutHost}} Zend\Expressive\Router\Middleware\DispatchMiddleware: Zend\Expressive\Router\Middleware\DispatchMiddlewareFactory
Zend\Expressive\Router\Middleware\MethodNotAllowedMiddleware: Zend\Expressive\Router\Middleware\MethodNotAllowedMiddlewareFactory
Zend\Expressive\Handler\NotFoundHandler: Zend\Expressive\Container\NotFoundHandlerFactory
App\Middleware\InternalServerError: Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory
Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory:
App\Middleware\InternalServerError:
- Psr\Http\Message\ResponseInterface

View File

@ -5,15 +5,17 @@
"version": "{{artifactVersion}}", "version": "{{artifactVersion}}",
"type": "project", "type": "project",
"require": { "require": {
"php": "^5.6 || ^7.0", "php": "^7.1",
"ext-yaml" : "^1.2 || ^2.0", "ext-yaml": "^2.0",
"zendframework/zend-expressive": "^2.1", "zendframework/zend-expressive": "^3.2",
"articus/path-handler": "^0.3", "zendframework/zend-diactoros": "^2.1",
"articus/data-transfer": "^0.1", "articus/path-handler": "^0.4",
"zendframework/zend-serializer": "^2.8", "articus/data-transfer": "^0.2",
"zendframework/zend-config": "^3.1", "doctrine/annotations": "^1.6",
"nikic/fast-route": "^1.2", "zendframework/zend-cache": "^2.8",
"http-interop/http-middleware": "^0.4.1" "zendframework/zend-serializer": "^2.9",
"zendframework/zend-config": "^3.2",
"nikic/fast-route": "^1.3"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {

View File

@ -4,38 +4,36 @@
#Enable configuration cache #Enable configuration cache
#cache_configuration: true #cache_configuration: true
#Enable routing cache for handlers #Articus\PathHandler\RouteInjection\Factory:
#Articus\PathHandler\Router\FastRouteAnnotation: # #Enable routing table cache
# metadata_cache: # router:
# adapter: # cache:
# name: filesystem # adapter: filesystem
# options: # options:
# cache_dir: data/cache/ZendCache # cache_dir: data/cache/ZendCache
# namespace: fast-route # namespace: ph-router
# plugins: # plugins:
# serializer: # serializer:
# serializer: phpserialize # serializer: phpserialize
# #Enable handler metadata cache
#Enable consumer, attribute and producer cache for handlers # metadata:
#Articus\PathHandler\Middleware: # cache:
# metadata_cache: # adapter: filesystem
# adapter:
# name: filesystem
# options: # options:
# cache_dir: data/cache/ZendCache # cache_dir: data/cache/ZendCache
# namespace: path-handler # namespace: ph-metadata
# plugins: # plugins:
# serializer: # serializer:
# serializer: phpserialize # serializer: phpserialize
#Enable data transfer metadata cache for DTOs #Enable data transfer metadata cache for DTOs
#data_transfer: #Articus\DataTransfer\Service:
# metadata_cache: # metadata_cache:
# adapter: # adapter:
# name: filesystem # name: filesystem
# options: # options:
# cache_dir: data/cache/ZendCache # cache_dir: data/cache/ZendCache
# namespace: data-transfer # namespace: dt
# plugins: # plugins:
# serializer: # serializer:
# serializer: phpserialize # serializer: phpserialize

View File

@ -1,9 +1,14 @@
<?php <?php
declare(strict_types=1);
use Zend\Config\Factory as ConfigFactory; use Zend\Config\Factory as ConfigFactory;
//Use Composer autoload that includes code both from ../src and ../vendor //Use Composer autoload that includes code both from ../src and ../vendor
require __DIR__ . '/../vendor/autoload.php'; require __DIR__ . '/../vendor/autoload.php';
//Register Doctrine annotation autoload
\Doctrine\Common\Annotations\AnnotationRegistry::registerLoader('class_exists');
//Path to file for caching full configuration //Path to file for caching full configuration
const CONFIG_CACHE_PATH = __DIR__ . '/../data/cache/config.php'; const CONFIG_CACHE_PATH = __DIR__ . '/../data/cache/config.php';
@ -24,20 +29,15 @@ if (is_readable(CONFIG_CACHE_PATH)) {
]); ]);
//Cache full configuration //Cache full configuration
if (isset($config['cache_configuration']) && $config['cache_configuration']) { if ($config['cache_configuration'] ?? false) {
if (!ConfigFactory::toFile(CONFIG_CACHE_PATH, $config)) { if (!ConfigFactory::toFile(CONFIG_CACHE_PATH, $config)) {
throw new \RuntimeException('Failed to cache configuration'); throw new \RuntimeException('Failed to cache configuration');
} }
} }
} }
//Get configuration for container
$dependencies = [];
if (isset($config['dependencies'])) {
$dependencies = $config['dependencies'];
}
//Create container //Create container
$container = new \Zend\ServiceManager\ServiceManager($dependencies); $container = new \Zend\ServiceManager\ServiceManager($config['dependencies'] ?? []);
//Register full configuration as a service //Register full configuration as a service
$container->setService('config', $config); $container->setService('config', $config);

View File

@ -2,7 +2,7 @@ dependencies:
factories: factories:
Articus\DataTransfer\Service: Articus\DataTransfer\ServiceFactory Articus\DataTransfer\Service: Articus\DataTransfer\ServiceFactory
data_transfer: Articus\DataTransfer\Service:
metadata_cache: metadata_cache:
adapter: adapter:
name: blackhole name: blackhole
@ -12,7 +12,6 @@ data_transfer:
{{invokerPackage}}\Strategy\DateTime: {{invokerPackage}}\Strategy\DateTime {{invokerPackage}}\Strategy\DateTime: {{invokerPackage}}\Strategy\DateTime
{{invokerPackage}}\Strategy\QueryParameter: {{invokerPackage}}\Strategy\QueryParameter {{invokerPackage}}\Strategy\QueryParameter: {{invokerPackage}}\Strategy\QueryParameter
{{invokerPackage}}\Strategy\QueryParameterArray: {{invokerPackage}}\Strategy\QueryParameterArray {{invokerPackage}}\Strategy\QueryParameterArray: {{invokerPackage}}\Strategy\QueryParameterArray
# factories:
aliases: aliases:
Date: {{invokerPackage}}\Strategy\Date Date: {{invokerPackage}}\Strategy\Date
DateTime: {{invokerPackage}}\Strategy\DateTime DateTime: {{invokerPackage}}\Strategy\DateTime

View File

@ -1,4 +1,5 @@
<?php <?php
declare(strict_types=1);
chdir(dirname(__DIR__)); chdir(dirname(__DIR__));

View File

@ -1,4 +1,5 @@
<?php <?php
declare(strict_types=1);
{{#models}}{{#model}} {{#models}}{{#model}}
namespace {{package}}; namespace {{package}};

View File

@ -1,14 +1,16 @@
dependencies: Articus\PathHandler\RouteInjection\Factory:
factories: paths:
Zend\Expressive\Router\RouterInterface: Articus\PathHandler\Router\Factory\FastRouteAnnotation '{{basePathWithoutHost}}':
{{#apiInfo}}
Articus\PathHandler\Middleware: {{#apis}}
metadata_cache: {{#operations}}
adapter: - {{package}}\{{classname}}
name: blackhole {{/operations}}
{{/apis}}
{{/apiInfo}}
handlers: handlers:
abstract_factories: abstract_factories:
- Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory - Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory
# consumers: # consumers:
# factories: # factories:
# invokables: # invokables:
@ -19,19 +21,6 @@ Articus\PathHandler\Middleware:
# factories: # factories:
# invokables: # invokables:
Articus\PathHandler\Router\FastRouteAnnotation:
metadata_cache:
adapter:
name: blackhole
handlers:
{{#apiInfo}}
{{#apis}}
{{#operations}}
- {{package}}\{{classname}}
{{/operations}}
{{/apis}}
{{/apiInfo}}
Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory: Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory:
{{#apiInfo}} {{#apiInfo}}
{{#apis}} {{#apis}}

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,23 @@
# OpenAPI Generator Ignore
# Generated by openapi-generator https://github.com/openapitools/openapi-generator
# Use this file to prevent files from being overwritten by the generator.
# The patterns follow closely to .gitignore or .dockerignore.
# As an example, the C# client generator defines ApiClient.cs.
# You can make changes and tell OpenAPI Generator to ignore just this file by uncommenting the following line:
#ApiClient.cs
# You can match any string of characters against a directory, file or extension with a single asterisk (*):
#foo/*/qux
# The above matches foo/bar/qux and foo/baz/qux, but not foo/bar/baz/qux
# You can recursively match patterns against a directory, file or extension with a double asterisk (**):
#foo/**/qux
# This matches foo/bar/qux, foo/baz/qux, and foo/bar/baz/qux
# You can also negate patterns with an exclamation (!).
# For example, you can ignore all files in a docs folder with the file extension .md:
#docs/*.md
# Then explicitly reverse the ignore rule for a single file:
#!docs/README.md

View File

@ -0,0 +1 @@
4.0.0-SNAPSHOT

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: >=7.1
- [Zend Expressive](https://zendframework.github.io/zend-expressive): >=3.2
- [Path Handler](https://github.com/Articus/PathHandler): >=0.4
## 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/ZendCache` (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-ze-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,39 @@
#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:
# adapter: filesystem
# options:
# cache_dir: data/cache/ZendCache
# namespace: ph-router
# plugins:
# serializer:
# serializer: phpserialize
# #Enable handler metadata cache
# metadata:
# cache:
# adapter: filesystem
# options:
# cache_dir: data/cache/ZendCache
# namespace: ph-metadata
# plugins:
# serializer:
# serializer: phpserialize
#Enable data transfer metadata cache for DTOs
#Articus\DataTransfer\Service:
# metadata_cache:
# adapter:
# name: filesystem
# options:
# cache_dir: data/cache/ZendCache
# namespace: dt
# plugins:
# serializer:
# serializer: phpserialize

View File

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

View File

@ -0,0 +1,33 @@
dependencies:
factories:
Articus\DataTransfer\Service: Articus\DataTransfer\ServiceFactory
Articus\DataTransfer\Service:
metadata_cache:
adapter:
name: blackhole
strategies:
invokables:
App\Strategy\Date: App\Strategy\Date
App\Strategy\DateTime: App\Strategy\DateTime
App\Strategy\QueryParameter: App\Strategy\QueryParameter
App\Strategy\QueryParameterArray: App\Strategy\QueryParameterArray
aliases:
Date: App\Strategy\Date
DateTime: App\Strategy\DateTime
QueryParameter: App\Strategy\QueryParameter
QueryParameterArray: App\Strategy\QueryParameterArray
validators:
invokables:
App\Validator\Type: App\Validator\Type
App\Validator\QueryParameterType: App\Validator\QueryParameterType
App\Validator\QueryParameterArrayType: App\Validator\QueryParameterArrayType
factories:
Articus\DataTransfer\Validator\Dictionary: Articus\DataTransfer\Validator\Factory
Articus\DataTransfer\Validator\Collection: Articus\DataTransfer\Validator\Factory
aliases:
Dictionary: Articus\DataTransfer\Validator\Dictionary
Collection: Articus\DataTransfer\Validator\Collection
Type: App\Validator\Type
QueryParameterType: App\Validator\QueryParameterType
QueryParameterArrayType: App\Validator\QueryParameterArrayType

View File

@ -0,0 +1,71 @@
Articus\PathHandler\RouteInjection\Factory:
paths:
'/v2':
- App\Handler\AnotherFakeDummy
- App\Handler\Fake
- App\Handler\FakeBodyWithFileSchema
- App\Handler\FakeBodyWithQueryParams
- App\Handler\FakeInlineAdditionalProperties
- App\Handler\FakeJsonFormData
- App\Handler\FakeOuterBoolean
- App\Handler\FakeOuterComposite
- App\Handler\FakeOuterNumber
- App\Handler\FakeOuterString
- App\Handler\FakePetIdUploadImageWithRequiredFile
- App\Handler\FakeClassnameTest
- App\Handler\Foo
- App\Handler\Pet
- App\Handler\PetFindByStatus
- App\Handler\PetFindByTags
- App\Handler\PetPetId
- App\Handler\PetPetIdUploadImage
- App\Handler\StoreInventory
- App\Handler\StoreOrder
- App\Handler\StoreOrderOrderId
- App\Handler\User
- App\Handler\UserCreateWithArray
- App\Handler\UserCreateWithList
- App\Handler\UserLogin
- App\Handler\UserLogout
- App\Handler\UserUsername
handlers:
abstract_factories:
- Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory
# consumers:
# factories:
# invokables:
# attributes:
# factories:
# invokables:
# producers:
# factories:
# invokables:
Zend\ServiceManager\AbstractFactory\ConfigAbstractFactory:
App\Handler\AnotherFakeDummy: []
App\Handler\Fake: []
App\Handler\FakeBodyWithFileSchema: []
App\Handler\FakeBodyWithQueryParams: []
App\Handler\FakeInlineAdditionalProperties: []
App\Handler\FakeJsonFormData: []
App\Handler\FakeOuterBoolean: []
App\Handler\FakeOuterComposite: []
App\Handler\FakeOuterNumber: []
App\Handler\FakeOuterString: []
App\Handler\FakePetIdUploadImageWithRequiredFile: []
App\Handler\FakeClassnameTest: []
App\Handler\Foo: []
App\Handler\Pet: []
App\Handler\PetFindByStatus: []
App\Handler\PetFindByTags: []
App\Handler\PetPetId: []
App\Handler\PetPetIdUploadImage: []
App\Handler\StoreInventory: []
App\Handler\StoreOrder: []
App\Handler\StoreOrderOrderId: []
App\Handler\User: []
App\Handler\UserCreateWithArray: []
App\Handler\UserCreateWithList: []
App\Handler\UserLogin: []
App\Handler\UserLogout: []
App\Handler\UserUsername: []

View File

@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
use Zend\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';
//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 \Zend\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,25 @@
{
"name": "GIT_USER_ID/GIT_REPO_ID",
"description": "",
"license": "proprietary",
"version": "1.0.0",
"type": "project",
"require": {
"php": "^7.1",
"ext-yaml": "^2.0",
"zendframework/zend-expressive": "^3.2",
"zendframework/zend-diactoros": "^2.1",
"articus/path-handler": "^0.4",
"articus/data-transfer": "^0.2",
"doctrine/annotations": "^1.6",
"zendframework/zend-cache": "^2.8",
"zendframework/zend-serializer": "^2.9",
"zendframework/zend-config": "^3.2",
"nikic/fast-route": "^1.3"
},
"autoload": {
"psr-4": {
"": "src/"
}
}
}

View File

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

View File

@ -0,0 +1,31 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class AdditionalPropertiesClass
{
/**
* @DTA\Data(field="map_property", nullable=true)
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Validator(name="Collection", options={"validators":{
* {"name":"Type", "options":{"type":"string"}}
* }})
* @var map[string,string]
*/
public $map_property;
/**
* @DTA\Data(field="map_of_map_property", nullable=true)
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Strategy(name="ObjectArray", options={"type":map[string,string]::class})
* @DTA\Validator(name="Collection", options={"validators":{
* {"name":"Dictionary", "options":{"type":map[string,string]::class}}
* }})
* @var map[string,map[string,string]]
*/
public $map_of_map_property;
}

View File

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class Animal
{
/**
* @DTA\Data(field="className")
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $class_name;
/**
* @DTA\Data(field="color", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $color;
}

View File

@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class ApiResponse
{
/**
* @DTA\Data(field="code", nullable=true)
* @DTA\Validator(name="Type", options={"type":"int"})
* @var int
*/
public $code;
/**
* @DTA\Data(field="type", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $type;
/**
* @DTA\Data(field="message", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $message;
}

View File

@ -0,0 +1,22 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class ArrayOfArrayOfNumberOnly
{
/**
* @DTA\Data(field="ArrayArrayNumber", nullable=true)
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Strategy(name="ObjectArray", options={"type":float[]::class})
* @DTA\Validator(name="Collection", options={"validators":{
* {"name":"Dictionary", "options":{"type":float[]::class}}
* }})
* @var float[][]
*/
public $array_array_number;
}

View File

@ -0,0 +1,21 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class ArrayOfNumberOnly
{
/**
* @DTA\Data(field="ArrayNumber", nullable=true)
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Validator(name="Collection", options={"validators":{
* {"name":"Type", "options":{"type":"float"}}
* }})
* @var float[]
*/
public $array_number;
}

View File

@ -0,0 +1,41 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class ArrayTest
{
/**
* @DTA\Data(field="array_of_string", nullable=true)
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Validator(name="Collection", options={"validators":{
* {"name":"Type", "options":{"type":"string"}}
* }})
* @var string[]
*/
public $array_of_string;
/**
* @DTA\Data(field="array_array_of_integer", nullable=true)
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Strategy(name="ObjectArray", options={"type":int[]::class})
* @DTA\Validator(name="Collection", options={"validators":{
* {"name":"Dictionary", "options":{"type":int[]::class}}
* }})
* @var int[][]
*/
public $array_array_of_integer;
/**
* @DTA\Data(field="array_array_of_model", nullable=true)
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Strategy(name="ObjectArray", options={"type":\App\DTO\ReadOnlyFirst[]::class})
* @DTA\Validator(name="Collection", options={"validators":{
* {"name":"Dictionary", "options":{"type":\App\DTO\ReadOnlyFirst[]::class}}
* }})
* @var \App\DTO\ReadOnlyFirst[][]
*/
public $array_array_of_model;
}

View File

@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class Capitalization
{
/**
* @DTA\Data(field="smallCamel", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $small_camel;
/**
* @DTA\Data(field="CapitalCamel", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $capital_camel;
/**
* @DTA\Data(field="small_Snake", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $small_snake;
/**
* @DTA\Data(field="Capital_Snake", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $capital_snake;
/**
* @DTA\Data(field="SCA_ETH_Flow_Points", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $sca_eth_flow_points;
/**
* Name of the pet
* @DTA\Data(field="ATT_NAME", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $att_name;
}

View File

@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class Cat
{
/**
* @DTA\Data(field="className")
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $class_name;
/**
* @DTA\Data(field="color", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $color;
/**
* @DTA\Data(field="declawed", nullable=true)
* @DTA\Validator(name="Type", options={"type":"bool"})
* @var bool
*/
public $declawed;
}

View File

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class Category
{
/**
* @DTA\Data(field="id", nullable=true)
* @DTA\Validator(name="Type", options={"type":"int"})
* @var int
*/
public $id;
/**
* @DTA\Data(field="name")
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $name;
}

View File

@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
* Model for testing model with \&quot;_class\&quot; property
*/
class ClassModel
{
/**
* @DTA\Data(field="_class", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $_class;
}

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class Client
{
/**
* @DTA\Data(field="client", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $client;
}

View File

@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class Dog
{
/**
* @DTA\Data(field="className")
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $class_name;
/**
* @DTA\Data(field="color", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $color;
/**
* @DTA\Data(field="breed", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $breed;
}

View File

@ -0,0 +1,27 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class EnumArrays
{
/**
* @DTA\Data(field="just_symbol", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $just_symbol;
/**
* @DTA\Data(field="array_enum", nullable=true)
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Validator(name="Collection", options={"validators":{
* {"name":"Type", "options":{"type":"string"}}
* }})
* @var string[]
*/
public $array_enum;
}

View File

@ -1,4 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace App\DTO; namespace App\DTO;
@ -6,6 +7,6 @@ use Articus\DataTransfer\Annotation as DTA;
/** /**
*/ */
class OuterNumber class EnumClass
{ {
} }

View File

@ -0,0 +1,43 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class EnumTest
{
/**
* @DTA\Data(field="enum_string", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $enum_string;
/**
* @DTA\Data(field="enum_string_required")
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $enum_string_required;
/**
* @DTA\Data(field="enum_integer", nullable=true)
* @DTA\Validator(name="Type", options={"type":"int"})
* @var int
*/
public $enum_integer;
/**
* @DTA\Data(field="enum_number", nullable=true)
* @DTA\Validator(name="Type", options={"type":"float"})
* @var float
*/
public $enum_number;
/**
* @DTA\Data(field="outerEnum", nullable=true)
* @DTA\Strategy(name="Object", options={"type":\App\DTO\OuterEnum::class})
* @DTA\Validator(name="Dictionary", options={"type":\App\DTO\OuterEnum::class})
* @var \App\DTO\OuterEnum
*/
public $outer_enum;
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class FileSchemaTestClass
{
/**
* @DTA\Data(field="file", nullable=true)
* @DTA\Strategy(name="Object", options={"type":\App\DTO\File::class})
* @DTA\Validator(name="Dictionary", options={"type":\App\DTO\File::class})
* @var \App\DTO\File
*/
public $file;
/**
* @DTA\Data(field="files", nullable=true)
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Strategy(name="ObjectArray", options={"type":\App\DTO\File::class})
* @DTA\Validator(name="Collection", options={"validators":{
* {"name":"Dictionary", "options":{"type":\App\DTO\File::class}}
* }})
* @var \App\DTO\File[]
*/
public $files;
}

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class Foo
{
/**
* @DTA\Data(field="bar", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $bar;
}

View File

@ -0,0 +1,121 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class FormatTest
{
/**
* @DTA\Data(field="integer", nullable=true)
* @DTA\Validator(name="Type", options={"type":"int"})
* @DTA\Validator(name="GreaterThan", options={"min":10, "inclusive":true})
* @DTA\Validator(name="LessThan", options={"max":100, "inclusive":true})
* @var int
*/
public $integer;
/**
* @DTA\Data(field="int32", nullable=true)
* @DTA\Validator(name="Type", options={"type":"int"})
* @DTA\Validator(name="GreaterThan", options={"min":20, "inclusive":true})
* @DTA\Validator(name="LessThan", options={"max":200, "inclusive":true})
* @var int
*/
public $int32;
/**
* @DTA\Data(field="int64", nullable=true)
* @DTA\Validator(name="Type", options={"type":"int"})
* @var int
*/
public $int64;
/**
* @DTA\Data(field="number")
* @DTA\Validator(name="Type", options={"type":"float"})
* @DTA\Validator(name="GreaterThan", options={"min":32.1, "inclusive":true})
* @DTA\Validator(name="LessThan", options={"max":543.2, "inclusive":true})
* @var float
*/
public $number;
/**
* @DTA\Data(field="float", nullable=true)
* @DTA\Validator(name="Type", options={"type":"float"})
* @DTA\Validator(name="GreaterThan", options={"min":54.3, "inclusive":true})
* @DTA\Validator(name="LessThan", options={"max":987.6, "inclusive":true})
* @var float
*/
public $float;
/**
* @DTA\Data(field="double", nullable=true)
* @DTA\Validator(name="Type", options={"type":"float"})
* @DTA\Validator(name="GreaterThan", options={"min":67.8, "inclusive":true})
* @DTA\Validator(name="LessThan", options={"max":123.4, "inclusive":true})
* @var float
*/
public $double;
/**
* @DTA\Data(field="string", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @DTA\Validator(name="Regex", options={"pattern":"/[a-z]/i"})
* @var string
*/
public $string;
/**
* @DTA\Data(field="byte")
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $byte;
/**
* @DTA\Data(field="binary", nullable=true)
* @DTA\Strategy(name="Object", options={"type":\SplFileObject::class})
* @DTA\Validator(name="Dictionary", options={"type":\SplFileObject::class})
* @var \SplFileObject
*/
public $binary;
/**
* @DTA\Data(field="date")
* @DTA\Strategy(name="Date")
* @DTA\Validator(name="Date")
* @var \DateTime
*/
public $date;
/**
* @DTA\Data(field="dateTime", nullable=true)
* @DTA\Strategy(name="DateTime")
* @DTA\Validator(name="Date", options={"format": \DateTime::RFC3339})
* @var \DateTime
*/
public $date_time;
/**
* @DTA\Data(field="uuid", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $uuid;
/**
* @DTA\Data(field="password")
* @DTA\Validator(name="Type", options={"type":"string"})
* @DTA\Validator(name="StringLength", options={"min":10, "max":64})
* @var string
*/
public $password;
/**
* A string that is a 10 digit number. Can have leading zeros.
* @DTA\Data(field="pattern_with_digits", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @DTA\Validator(name="Regex", options={"pattern":"/^\\d{10}$/"})
* @var string
*/
public $pattern_with_digits;
/**
* A string starting with &#39;image_&#39; (case insensitive) and one to three digits following i.e. Image_01.
* @DTA\Data(field="pattern_with_digits_and_delimiter", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @DTA\Validator(name="Regex", options={"pattern":"/^image_\\d{1,3}$/i"})
* @var string
*/
public $pattern_with_digits_and_delimiter;
}

View File

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class HasOnlyReadOnly
{
/**
* @DTA\Data(field="bar", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $bar;
/**
* @DTA\Data(field="foo", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $foo;
}

View File

@ -0,0 +1,26 @@
<?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="Type", options={"type":"string"})
* @var string
*/
public $name;
/**
* Updated status of the pet
* @DTA\Data(field="status", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $status;
}

View File

@ -0,0 +1,27 @@
<?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="Type", options={"type":"string"})
* @var string
*/
public $additional_metadata;
/**
* file to upload
* @DTA\Data(field="file", nullable=true)
* @DTA\Strategy(name="Object", options={"type":\SplFileObject::class})
* @DTA\Validator(name="Dictionary", options={"type":\SplFileObject::class})
* @var \SplFileObject
*/
public $file;
}

View File

@ -0,0 +1,29 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class InlineObject2
{
/**
* Form parameter enum test (string array)
* @DTA\Data(field="enum_form_string_array", nullable=true)
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Validator(name="Collection", options={"validators":{
* {"name":"Type", "options":{"type":"string"}}
* }})
* @var string[]
*/
public $enum_form_string_array;
/**
* Form parameter enum test (string)
* @DTA\Data(field="enum_form_string", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $enum_form_string;
}

View File

@ -0,0 +1,125 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class InlineObject3
{
/**
* None
* @DTA\Data(field="integer", nullable=true)
* @DTA\Validator(name="Type", options={"type":"int"})
* @DTA\Validator(name="GreaterThan", options={"min":10, "inclusive":true})
* @DTA\Validator(name="LessThan", options={"max":100, "inclusive":true})
* @var int
*/
public $integer;
/**
* None
* @DTA\Data(field="int32", nullable=true)
* @DTA\Validator(name="Type", options={"type":"int"})
* @DTA\Validator(name="GreaterThan", options={"min":20, "inclusive":true})
* @DTA\Validator(name="LessThan", options={"max":200, "inclusive":true})
* @var int
*/
public $int32;
/**
* None
* @DTA\Data(field="int64", nullable=true)
* @DTA\Validator(name="Type", options={"type":"int"})
* @var int
*/
public $int64;
/**
* None
* @DTA\Data(field="number")
* @DTA\Validator(name="Type", options={"type":"float"})
* @DTA\Validator(name="GreaterThan", options={"min":32.1, "inclusive":true})
* @DTA\Validator(name="LessThan", options={"max":543.2, "inclusive":true})
* @var float
*/
public $number;
/**
* None
* @DTA\Data(field="float", nullable=true)
* @DTA\Validator(name="Type", options={"type":"float"})
* @DTA\Validator(name="LessThan", options={"max":987.6, "inclusive":true})
* @var float
*/
public $float;
/**
* None
* @DTA\Data(field="double")
* @DTA\Validator(name="Type", options={"type":"float"})
* @DTA\Validator(name="GreaterThan", options={"min":67.8, "inclusive":true})
* @DTA\Validator(name="LessThan", options={"max":123.4, "inclusive":true})
* @var float
*/
public $double;
/**
* None
* @DTA\Data(field="string", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @DTA\Validator(name="Regex", options={"pattern":"/[a-z]/i"})
* @var string
*/
public $string;
/**
* None
* @DTA\Data(field="pattern_without_delimiter")
* @DTA\Validator(name="Type", options={"type":"string"})
* @DTA\Validator(name="Regex", options={"pattern":"/^[A-Z].*/"})
* @var string
*/
public $pattern_without_delimiter;
/**
* None
* @DTA\Data(field="byte")
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $byte;
/**
* None
* @DTA\Data(field="binary", nullable=true)
* @DTA\Strategy(name="Object", options={"type":\SplFileObject::class})
* @DTA\Validator(name="Dictionary", options={"type":\SplFileObject::class})
* @var \SplFileObject
*/
public $binary;
/**
* None
* @DTA\Data(field="date", nullable=true)
* @DTA\Strategy(name="Date")
* @DTA\Validator(name="Date")
* @var \DateTime
*/
public $date;
/**
* None
* @DTA\Data(field="dateTime", nullable=true)
* @DTA\Strategy(name="DateTime")
* @DTA\Validator(name="Date", options={"format": \DateTime::RFC3339})
* @var \DateTime
*/
public $date_time;
/**
* None
* @DTA\Data(field="password", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @DTA\Validator(name="StringLength", options={"min":10, "max":64})
* @var string
*/
public $password;
/**
* None
* @DTA\Data(field="callback", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $callback;
}

View File

@ -0,0 +1,26 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class InlineObject4
{
/**
* field1
* @DTA\Data(field="param")
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $param;
/**
* field2
* @DTA\Data(field="param2")
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $param2;
}

View File

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

View File

@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class InlineResponseDefault
{
/**
* @DTA\Data(field="string", nullable=true)
* @DTA\Strategy(name="Object", options={"type":\App\DTO\Foo::class})
* @DTA\Validator(name="Dictionary", options={"type":\App\DTO\Foo::class})
* @var \App\DTO\Foo
*/
public $string;
}

View File

@ -1,4 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace App\DTO; namespace App\DTO;

View File

@ -0,0 +1,49 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class MapTest
{
/**
* @DTA\Data(field="map_map_of_string", nullable=true)
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Strategy(name="ObjectArray", options={"type":map[string,string]::class})
* @DTA\Validator(name="Collection", options={"validators":{
* {"name":"Dictionary", "options":{"type":map[string,string]::class}}
* }})
* @var map[string,map[string,string]]
*/
public $map_map_of_string;
/**
* @DTA\Data(field="map_of_enum_string", nullable=true)
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Validator(name="Collection", options={"validators":{
* {"name":"Type", "options":{"type":"string"}}
* }})
* @var map[string,string]
*/
public $map_of_enum_string;
/**
* @DTA\Data(field="direct_map", nullable=true)
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Validator(name="Collection", options={"validators":{
* {"name":"Type", "options":{"type":"bool"}}
* }})
* @var map[string,bool]
*/
public $direct_map;
/**
* @DTA\Data(field="indirect_map", nullable=true)
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Validator(name="Collection", options={"validators":{
* {"name":"Type", "options":{"type":"bool"}}
* }})
* @var map[string,bool]
*/
public $indirect_map;
}

View File

@ -0,0 +1,35 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class MixedPropertiesAndAdditionalPropertiesClass
{
/**
* @DTA\Data(field="uuid", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $uuid;
/**
* @DTA\Data(field="dateTime", nullable=true)
* @DTA\Strategy(name="DateTime")
* @DTA\Validator(name="Date", options={"format": \DateTime::RFC3339})
* @var \DateTime
*/
public $date_time;
/**
* @DTA\Data(field="map", nullable=true)
* TODO check validator and strategy are correct and can handle container item type
* @DTA\Strategy(name="ObjectArray", options={"type":\App\DTO\Animal::class})
* @DTA\Validator(name="Collection", options={"validators":{
* {"name":"Dictionary", "options":{"type":\App\DTO\Animal::class}}
* }})
* @var map[string,\App\DTO\Animal]
*/
public $map;
}

View File

@ -0,0 +1,25 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
* Model for testing model name starting with number
*/
class Model200Response
{
/**
* @DTA\Data(field="name", nullable=true)
* @DTA\Validator(name="Type", options={"type":"int"})
* @var int
*/
public $name;
/**
* @DTA\Data(field="class", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $class;
}

View File

@ -0,0 +1,19 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
* Model for testing reserved words
*/
class ModelReturn
{
/**
* @DTA\Data(field="return", nullable=true)
* @DTA\Validator(name="Type", options={"type":"int"})
* @var int
*/
public $return;
}

View File

@ -0,0 +1,37 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
* Model for testing model name same as property name
*/
class Name
{
/**
* @DTA\Data(field="name")
* @DTA\Validator(name="Type", options={"type":"int"})
* @var int
*/
public $name;
/**
* @DTA\Data(field="snake_case", nullable=true)
* @DTA\Validator(name="Type", options={"type":"int"})
* @var int
*/
public $snake_case;
/**
* @DTA\Data(field="property", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $property;
/**
* @DTA\Data(field="123Number", nullable=true)
* @DTA\Validator(name="Type", options={"type":"int"})
* @var int
*/
public $_123_number;
}

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class NumberOnly
{
/**
* @DTA\Data(field="JustNumber", nullable=true)
* @DTA\Validator(name="Type", options={"type":"float"})
* @var float
*/
public $just_number;
}

View File

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

View File

@ -0,0 +1,30 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class OuterComposite
{
/**
* @DTA\Data(field="my_number", nullable=true)
* @DTA\Validator(name="Type", options={"type":"float"})
* @var float
*/
public $my_number;
/**
* @DTA\Data(field="my_string", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $my_string;
/**
* @DTA\Data(field="my_boolean", nullable=true)
* @DTA\Validator(name="Type", options={"type":"bool"})
* @var bool
*/
public $my_boolean;
}

View File

@ -1,4 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace App\DTO; namespace App\DTO;
@ -6,6 +7,6 @@ use Articus\DataTransfer\Annotation as DTA;
/** /**
*/ */
class OuterString class OuterEnum
{ {
} }

View File

@ -0,0 +1,57 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class Pet
{
/**
* @DTA\Data(field="id", nullable=true)
* @DTA\Validator(name="Type", options={"type":"int"})
* @var int
*/
public $id;
/**
* @DTA\Data(field="category", nullable=true)
* @DTA\Strategy(name="Object", options={"type":\App\DTO\Category::class})
* @DTA\Validator(name="Dictionary", options={"type":\App\DTO\Category::class})
* @var \App\DTO\Category
*/
public $category;
/**
* @DTA\Data(field="name")
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
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":"Type", "options":{"type":"string"}}
* }})
* @var string[]
*/
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":"Dictionary", "options":{"type":\App\DTO\Tag::class}}
* }})
* @var \App\DTO\Tag[]
*/
public $tags;
/**
* pet status in the store
* @DTA\Data(field="status", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $status;
}

View File

@ -0,0 +1,24 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class ReadOnlyFirst
{
/**
* @DTA\Data(field="bar", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $bar;
/**
* @DTA\Data(field="baz", nullable=true)
* @DTA\Validator(name="Type", options={"type":"string"})
* @var string
*/
public $baz;
}

View File

@ -0,0 +1,18 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
*/
class SpecialModelName
{
/**
* @DTA\Data(field="$special[property.name]", nullable=true)
* @DTA\Validator(name="Type", options={"type":"int"})
* @var int
*/
public $special_property_name;
}

View File

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

View File

@ -0,0 +1,20 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
* Query parameters for testBodyWithQueryParams
*/
class TestBodyWithQueryParamsQueryData
{
/**
* @DTA\Data(field="query")
* @DTA\Strategy(name="QueryParameter", options={"type":"string"})
* @DTA\Validator(name="QueryParameterType", options={"type":"string"})
* @var string
*/
public $query;
}

View File

@ -1,4 +1,5 @@
<?php <?php
declare(strict_types=1);
namespace App\DTO; namespace App\DTO;
@ -9,6 +10,14 @@ use Articus\DataTransfer\Annotation as DTA;
*/ */
class TestEnumParametersQueryData class TestEnumParametersQueryData
{ {
/**
* Query parameter enum test (double)
* @DTA\Data(field="enum_query_double", nullable=true)
* @DTA\Strategy(name="QueryParameter", options={"type":"float"})
* @DTA\Validator(name="QueryParameterType", options={"type":"float"})
* @var float
*/
public $enum_query_double;
/** /**
* Query parameter enum test (string) * Query parameter enum test (string)
* @DTA\Data(field="enum_query_string", nullable=true) * @DTA\Data(field="enum_query_string", nullable=true)
@ -29,8 +38,8 @@ class TestEnumParametersQueryData
* Query parameter enum test (string array) * Query parameter enum test (string array)
* @DTA\Data(field="enum_query_string_array", nullable=true) * @DTA\Data(field="enum_query_string_array", nullable=true)
* TODO check validator and strategy are correct and can handle container item type * TODO check validator and strategy are correct and can handle container item type
* @DTA\Strategy(name="QueryParameterArray", options={"type":"string", "format":"csv"}) * @DTA\Strategy(name="QueryParameterArray", options={"type":"string", "format":"multi"})
* @DTA\Validator(name="QueryParameterArrayType", options={"type":"string", "format":"csv"}) * @DTA\Validator(name="QueryParameterArrayType", options={"type":"string", "format":"multi"})
* @var string[] * @var string[]
*/ */
public $enum_query_string_array; public $enum_query_string_array;

View File

@ -0,0 +1,45 @@
<?php
declare(strict_types=1);
namespace App\DTO;
use Articus\DataTransfer\Annotation as DTA;
/**
* Query parameters for testGroupParameters
*/
class TestGroupParametersQueryData
{
/**
* Required String in group parameters
* @DTA\Data(field="required_string_group")
* @DTA\Strategy(name="QueryParameter", options={"type":"int"})
* @DTA\Validator(name="QueryParameterType", options={"type":"int"})
* @var int
*/
public $required_string_group;
/**
* Integer in group parameters
* @DTA\Data(field="int64_group", nullable=true)
* @DTA\Strategy(name="QueryParameter", options={"type":"int"})
* @DTA\Validator(name="QueryParameterType", options={"type":"int"})
* @var int
*/
public $int64_group;
/**
* String in group parameters
* @DTA\Data(field="string_group", nullable=true)
* @DTA\Strategy(name="QueryParameter", options={"type":"int"})
* @DTA\Validator(name="QueryParameterType", options={"type":"int"})
* @var int
*/
public $string_group;
/**
* Required Integer in group parameters
* @DTA\Data(field="required_int64_group")
* @DTA\Strategy(name="QueryParameter", options={"type":"int"})
* @DTA\Validator(name="QueryParameterType", options={"type":"int"})
* @var int
*/
public $required_int64_group;
}

View File

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

View File

@ -0,0 +1,58 @@
<?php
declare(strict_types=1);
namespace App;
use App\Middleware;
use Interop\Container\ContainerInterface;
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Zend\Expressive\Application;
use Zend\Expressive\Handler\NotFoundHandler;
use Zend\Expressive\MiddlewareFactory;
use Zend\Expressive\Router\Middleware\DispatchMiddleware;
use Zend\Expressive\Router\Middleware\MethodNotAllowedMiddleware;
use Zend\Expressive\Router\Middleware\RouteMiddleware;
use Zend\Expressive\Router\RouteCollector;
use Zend\HttpHandlerRunner\Emitter\EmitterInterface;
use Zend\HttpHandlerRunner\RequestHandlerRunner;
use Zend\ServiceManager\Factory\FactoryInterface;
use Zend\Stratigility\MiddlewarePipe;
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)
));
}
$pipeline = new MiddlewarePipe();
$runner = new RequestHandlerRunner(
$pipeline,
$container->get(EmitterInterface::class),
$container->get(ServerRequestInterface::class),
function(\Throwable $error) use ($errorMiddleware) : ResponseInterface
{
return $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;
}
}

View File

@ -0,0 +1,39 @@
<?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="/another-fake/dummy")
*/
class AnotherFakeDummy
{
/**
* To test special tags
* @PHA\Patch()
* 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, mediaType="application/json")
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={"type":\App\DTO\Client::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/json")
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*
* @return \App\DTO\Client
*/
public function call123TestSpecialTags(ServerRequestInterface $request): \App\DTO\Client
{
//TODO implement method
/** @var \App\DTO\Client $bodyData */
$bodyData = $request->getAttribute("bodyData");
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -0,0 +1,89 @@
<?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="/fake")
*/
class Fake
{
/**
* To test \&quot;client\&quot; model
* @PHA\Patch()
* 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, mediaType="application/json")
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={"type":\App\DTO\Client::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/json")
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*
* @return \App\DTO\Client
*/
public function testClientModel(ServerRequestInterface $request): \App\DTO\Client
{
//TODO implement method
/** @var \App\DTO\Client $bodyData */
$bodyData = $request->getAttribute("bodyData");
throw new PHException\HttpCode(501, "Not implemented");
}
/**
* Fake endpoint for testing various parameters 假端點 偽のエンドポイント 가짜 엔드 포인트
* @PHA\Post()
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*/
public function testEndpointParameters(ServerRequestInterface $request)
{
//TODO implement method
throw new PHException\HttpCode(501, "Not implemented");
}
/**
* To test enum parameters
* @PHA\Get()
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={
* "type":\App\DTO\TestEnumParametersQueryData::class,
* "objectAttr":"queryData",
* "source": PHAttribute\Transfer::SOURCE_GET
* })
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*/
public function testEnumParameters(ServerRequestInterface $request)
{
//TODO implement method
/** @var \App\DTO\TestEnumParametersQueryData $queryData */
$queryData = $request->getAttribute("queryData");
throw new PHException\HttpCode(501, "Not implemented");
}
/**
* Fake endpoint to test group parameters (optional)
* @PHA\Delete()
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={
* "type":\App\DTO\TestGroupParametersQueryData::class,
* "objectAttr":"queryData",
* "source": PHAttribute\Transfer::SOURCE_GET
* })
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*/
public function testGroupParameters(ServerRequestInterface $request)
{
//TODO implement method
/** @var \App\DTO\TestGroupParametersQueryData $queryData */
$queryData = $request->getAttribute("queryData");
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -0,0 +1,34 @@
<?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="/fake/body-with-file-schema")
*/
class FakeBodyWithFileSchema
{
/**
* @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, mediaType="application/json")
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={"type":\App\DTO\FileSchemaTestClass::class,"objectAttr":"bodyData"})
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*/
public function testBodyWithFileSchema(ServerRequestInterface $request)
{
//TODO implement method
/** @var \App\DTO\FileSchemaTestClass $bodyData */
$bodyData = $request->getAttribute("bodyData");
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -0,0 +1,41 @@
<?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="/fake/body-with-query-params")
*/
class FakeBodyWithQueryParams
{
/**
* @PHA\Put()
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={
* "type":\App\DTO\TestBodyWithQueryParamsQueryData::class,
* "objectAttr":"queryData",
* "source": PHAttribute\Transfer::SOURCE_GET
* })
* 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, mediaType="application/json")
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={"type":\App\DTO\User::class,"objectAttr":"bodyData"})
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*/
public function testBodyWithQueryParams(ServerRequestInterface $request)
{
//TODO implement method
/** @var \App\DTO\TestBodyWithQueryParamsQueryData $queryData */
$queryData = $request->getAttribute("queryData");
/** @var \App\DTO\User $bodyData */
$bodyData = $request->getAttribute("bodyData");
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -0,0 +1,39 @@
<?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="/fake_classname_test")
*/
class FakeClassnameTest
{
/**
* To test class name in snake case
* @PHA\Patch()
* 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, mediaType="application/json")
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={"type":\App\DTO\Client::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/json")
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*
* @return \App\DTO\Client
*/
public function testClassname(ServerRequestInterface $request): \App\DTO\Client
{
//TODO implement method
/** @var \App\DTO\Client $bodyData */
$bodyData = $request->getAttribute("bodyData");
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -0,0 +1,36 @@
<?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="/fake/inline-additionalProperties")
*/
class FakeInlineAdditionalProperties
{
/**
* test inline additionalProperties
* @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, mediaType="application/json")
* TODO check if attribute is valid and can handle your container type
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={"type":"map[string,string]","objectAttr":"bodyData"})
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*/
public function testInlineAdditionalProperties(ServerRequestInterface $request)
{
//TODO implement method
/** @var map[string,string] $bodyData */
$bodyData = $request->getAttribute("bodyData");
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -0,0 +1,30 @@
<?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="/fake/jsonFormData")
*/
class FakeJsonFormData
{
/**
* test json serialization of form data
* @PHA\Get()
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*/
public function testJsonFormData(ServerRequestInterface $request)
{
//TODO implement method
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -0,0 +1,35 @@
<?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="/fake/outer/boolean")
*/
class FakeOuterBoolean
{
/**
* @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, mediaType="application/json")
* 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="n/a")
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*
* @return bool
*/
public function fakeOuterBooleanSerialize(ServerRequestInterface $request): bool
{
//TODO implement method
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -0,0 +1,38 @@
<?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="/fake/outer/composite")
*/
class FakeOuterComposite
{
/**
* @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, mediaType="application/json")
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={"type":\App\DTO\OuterComposite::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="n/a")
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*
* @return \App\DTO\OuterComposite
*/
public function fakeOuterCompositeSerialize(ServerRequestInterface $request): \App\DTO\OuterComposite
{
//TODO implement method
/** @var \App\DTO\OuterComposite $bodyData */
$bodyData = $request->getAttribute("bodyData");
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -0,0 +1,35 @@
<?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="/fake/outer/number")
*/
class FakeOuterNumber
{
/**
* @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, mediaType="application/json")
* 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="n/a")
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*
* @return float
*/
public function fakeOuterNumberSerialize(ServerRequestInterface $request): float
{
//TODO implement method
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -0,0 +1,35 @@
<?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="/fake/outer/string")
*/
class FakeOuterString
{
/**
* @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, mediaType="application/json")
* 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="n/a")
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*
* @return string
*/
public function fakeOuterStringSerialize(ServerRequestInterface $request): string
{
//TODO implement method
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -0,0 +1,34 @@
<?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="/fake/{petId}/uploadImageWithRequiredFile")
*/
class FakePetIdUploadImageWithRequiredFile
{
/**
* uploads an image (required)
* @PHA\Post()
* 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\ApiResponse
*/
public function uploadFileWithRequiredFile(ServerRequestInterface $request): \App\DTO\ApiResponse
{
//TODO implement method
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -0,0 +1,33 @@
<?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="/foo")
*/
class Foo
{
/**
* @PHA\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/json")
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*
* @return \App\DTO\InlineResponseDefault
*/
public function fooGet(ServerRequestInterface $request): \App\DTO\InlineResponseDefault
{
//TODO implement method
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -0,0 +1,56 @@
<?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, mediaType="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, mediaType="application/xml")
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={"type":\App\DTO\Pet::class,"objectAttr":"bodyData"})
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*/
public function addPet(ServerRequestInterface $request)
{
//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, mediaType="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, mediaType="application/xml")
* @PHA\Attribute(name=PHAttribute\Transfer::class, options={"type":\App\DTO\Pet::class,"objectAttr":"bodyData"})
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*/
public function updatePet(ServerRequestInterface $request)
{
//TODO implement method
/** @var \App\DTO\Pet $bodyData */
$bodyData = $request->getAttribute("bodyData");
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -0,0 +1,44 @@
<?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

@ -0,0 +1,44 @@
<?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

@ -0,0 +1,60 @@
<?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/{petId}")
*/
class PetPetId
{
/**
* Deletes a pet
* @PHA\Delete()
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*/
public function deletePet(ServerRequestInterface $request)
{
//TODO implement method
throw new PHException\HttpCode(501, "Not implemented");
}
/**
* Find pet by ID
* @PHA\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 \App\DTO\Pet
*/
public function getPetById(ServerRequestInterface $request): \App\DTO\Pet
{
//TODO implement method
throw new PHException\HttpCode(501, "Not implemented");
}
/**
* Updates a pet in the store with form data
* @PHA\Post()
* @param ServerRequestInterface $request
*
* @throws PHException\HttpCode 501 if the method is not implemented
*/
public function updatePetWithForm(ServerRequestInterface $request)
{
//TODO implement method
throw new PHException\HttpCode(501, "Not implemented");
}
}

View File

@ -1,8 +1,8 @@
<?php <?php
declare(strict_types=1);
namespace App\Handler; namespace App\Handler;
use Articus\PathHandler\Operation;
use Articus\PathHandler\Annotation as PHA; use Articus\PathHandler\Annotation as PHA;
use Articus\PathHandler\Consumer as PHConsumer; use Articus\PathHandler\Consumer as PHConsumer;
use Articus\PathHandler\Producer as PHProducer; use Articus\PathHandler\Producer as PHProducer;
@ -11,23 +11,24 @@ use Articus\PathHandler\Exception as PHException;
use Psr\Http\Message\ServerRequestInterface; use Psr\Http\Message\ServerRequestInterface;
/** /**
* @PHA\Route(pattern="/pet/{petId}/uploadImageWithRequiredFile") * @PHA\Route(pattern="/pet/{petId}/uploadImage")
*/ */
class PetPetIdUploadImageWithRequiredFile implements Operation\PostInterface class PetPetIdUploadImage
{ {
/** /**
* uploads an image * uploads an image
* @PHA\Post()
* TODO check if producer is valid, if it has correct priority and if it can be moved to class annotation * 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") * @PHA\Producer(name=PHProducer\Transfer::class, mediaType="application/json")
* @param ServerRequestInterface $request * @param ServerRequestInterface $request
* *
* @throws PHException\HttpCode 500 if the method is not implemented * @throws PHException\HttpCode 501 if the method is not implemented
* *
* @return \App\DTO\ApiResponse * @return \App\DTO\ApiResponse
*/ */
public function handlePost(ServerRequestInterface $request) public function uploadFile(ServerRequestInterface $request): \App\DTO\ApiResponse
{ {
//TODO implement method //TODO implement method
throw new PHException\HttpCode(500, "Not implemented"); throw new PHException\HttpCode(501, "Not implemented");
} }
} }

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