forked from loafle/openapi-generator-original
[php-slim4] Add dependency injection container 2 (#11159)
* Change packages order alphabetically * Add PHP-DI package to Composer template * Remove ContainerInterface from APIs User shouldn't access container directly, it's an anti-pattern. Ref: https://php-di.org/doc/best-practices.html#rules-for-using-a-container-and-dependency-injection * Change app templates to use PHP-DI Application looks more like a default Slim skeleton now. Ref: https://github.com/slimphp/Slim-Skeleton * Rename SlimRouter to RegisterRoutes Since it's callable class new name fits better. * Add short documentation * Refresh samples
This commit is contained in:
parent
ac55ac9d55
commit
aa61220db2
@ -50,6 +50,8 @@ public class PhpSlim4ServerCodegen extends AbstractPhpCodegen {
|
||||
protected String artifactId = "openapi-server";
|
||||
protected String authDirName = "Auth";
|
||||
protected String authPackage = "";
|
||||
protected String appDirName = "App";
|
||||
protected String appPackage = "";
|
||||
protected String psr7Implementation = "slim-psr7";
|
||||
protected String interfacesDirName = "Interfaces";
|
||||
protected String interfacesPackage = "";
|
||||
@ -92,6 +94,7 @@ public class PhpSlim4ServerCodegen extends AbstractPhpCodegen {
|
||||
modelPackage = invokerPackage + "\\" + modelDirName;
|
||||
authPackage = invokerPackage + "\\" + authDirName;
|
||||
interfacesPackage = invokerPackage + "\\" + interfacesDirName;
|
||||
appPackage = invokerPackage + "\\" + appDirName;
|
||||
outputFolder = "generated-code" + File.separator + "slim4";
|
||||
|
||||
modelTestTemplateFiles.put("model_test.mustache", ".php");
|
||||
@ -167,6 +170,8 @@ public class PhpSlim4ServerCodegen extends AbstractPhpCodegen {
|
||||
authPackage = invokerPackage + "\\" + authDirName;
|
||||
// Update interfacesPackage
|
||||
interfacesPackage = invokerPackage + "\\" + interfacesDirName;
|
||||
// update appPackage
|
||||
appPackage = invokerPackage + "\\" + appDirName;
|
||||
}
|
||||
|
||||
// make auth src path available in mustache template
|
||||
@ -178,6 +183,10 @@ public class PhpSlim4ServerCodegen extends AbstractPhpCodegen {
|
||||
additionalProperties.put("interfacesSrcPath", "./" + toSrcPath(interfacesPackage, srcBasePath));
|
||||
additionalProperties.put("interfacesTestPath", "./" + toSrcPath(interfacesPackage, testBasePath));
|
||||
|
||||
// same for app classes
|
||||
additionalProperties.put("appPackage", appPackage);
|
||||
additionalProperties.put("appSrcPath", "./" + toSrcPath(appPackage, srcBasePath));
|
||||
|
||||
if (additionalProperties.containsKey(PSR7_IMPLEMENTATION)) {
|
||||
this.setPsr7Implementation((String) additionalProperties.get(PSR7_IMPLEMENTATION));
|
||||
}
|
||||
@ -213,7 +222,9 @@ public class PhpSlim4ServerCodegen extends AbstractPhpCodegen {
|
||||
supportingFiles.add(new SupportingFile("composer.mustache", "", "composer.json"));
|
||||
supportingFiles.add(new SupportingFile("index.mustache", "public", "index.php"));
|
||||
supportingFiles.add(new SupportingFile(".htaccess", "public", ".htaccess"));
|
||||
supportingFiles.add(new SupportingFile("SlimRouter.mustache", toSrcPath(invokerPackage, srcBasePath), "SlimRouter.php"));
|
||||
supportingFiles.add(new SupportingFile("register_dependencies.mustache", toSrcPath(appPackage, srcBasePath), "RegisterDependencies.php"));
|
||||
supportingFiles.add(new SupportingFile("register_middlewares.mustache", toSrcPath(appPackage, srcBasePath), "RegisterMiddlewares.php"));
|
||||
supportingFiles.add(new SupportingFile("register_routes.mustache", toSrcPath(appPackage, srcBasePath), "RegisterRoutes.php"));
|
||||
|
||||
// don't generate phpunit config when tests generation disabled
|
||||
if (Boolean.TRUE.equals(generateApiTests) || Boolean.TRUE.equals(generateModelTests)) {
|
||||
@ -224,8 +235,8 @@ public class PhpSlim4ServerCodegen extends AbstractPhpCodegen {
|
||||
supportingFiles.add(new SupportingFile("phpcs.xml.mustache", "", "phpcs.xml.dist"));
|
||||
|
||||
supportingFiles.add(new SupportingFile("htaccess_deny_all", "config", ".htaccess"));
|
||||
supportingFiles.add(new SupportingFile("config_example.mustache", "config" + File.separator + "dev", "example.inc.php"));
|
||||
supportingFiles.add(new SupportingFile("config_example.mustache", "config" + File.separator + "prod", "example.inc.php"));
|
||||
supportingFiles.add(new SupportingFile("config_dev_default.mustache", "config" + File.separator + "dev", "default.inc.php"));
|
||||
supportingFiles.add(new SupportingFile("config_prod_default.mustache", "config" + File.separator + "prod", "default.inc.php"));
|
||||
|
||||
if (Boolean.TRUE.equals(generateModels)) {
|
||||
supportingFiles.add(new SupportingFile("base_model.mustache", toSrcPath(invokerPackage, srcBasePath), "BaseModel.php"));
|
||||
|
@ -1,3 +1,7 @@
|
||||
<IfModule mod_env.c>
|
||||
SetEnv APP_ENV 'production'
|
||||
</IfModule>
|
||||
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
|
@ -15,6 +15,7 @@ This server has been generated with [Guzzle PSR-7](https://github.com/guzzle/psr
|
||||
{{#isZendDiactoros}}
|
||||
This server has been generated with [Laminas (Zend) PSR-7 implementation](https://github.com/laminas/laminas-diactoros).
|
||||
{{/isZendDiactoros}}
|
||||
[PHP-DI](https://php-di.org/doc/frameworks/slim.html) package used as dependency container.
|
||||
|
||||
## Requirements
|
||||
|
||||
@ -34,7 +35,10 @@ $ composer install
|
||||
|
||||
## Add configs
|
||||
|
||||
Application requires at least one config file(`config/dev/config.inc.php` or `config/prod/config.inc.php`). You can use [config/dev/example.inc.php](config/dev/example.inc.php) as starting point.
|
||||
[PHP-DI package](https://php-di.org/doc/getting-started.html) helps to decouple configuration from implementation. App loads configuration files in straight order(`$env` can be `prod` or `dev`):
|
||||
1. `config/$env/default.inc.php` (contains safe values, can be committed to vcs)
|
||||
2. `config/$env/config.inc.php` (user config, excluded from vcs, can contain sensitive values, passwords etc.)
|
||||
3. `lib/App/RegisterDependencies.php`
|
||||
|
||||
## Start devserver
|
||||
|
||||
@ -103,25 +107,14 @@ $ composer phplint
|
||||
|
||||
## Show errors
|
||||
|
||||
Switch on option in your application config file like:
|
||||
```diff
|
||||
return [
|
||||
'slimSettings' => [
|
||||
- 'displayErrorDetails' => false,
|
||||
+ 'displayErrorDetails' => true,
|
||||
'logErrors' => true,
|
||||
'logErrorDetails' => true,
|
||||
],
|
||||
Switch your app environment to development in `public/.htaccess` file:
|
||||
```ini
|
||||
## .htaccess
|
||||
<IfModule mod_env.c>
|
||||
SetEnv APP_ENV 'development'
|
||||
</IfModule>
|
||||
```
|
||||
|
||||
## Mock Server
|
||||
For a quick start uncomment [mocker middleware options](config/dev/example.inc.php#L67-L94) in your application config file.
|
||||
|
||||
Used packages:
|
||||
* [Openapi Data Mocker](https://github.com/ybelenko/openapi-data-mocker) - first implementation of OAS3 fake data generator.
|
||||
* [Openapi Data Mocker Server Middleware](https://github.com/ybelenko/openapi-data-mocker-server-middleware) - PSR-15 HTTP server middleware.
|
||||
* [Openapi Data Mocker Interfaces](https://github.com/ybelenko/openapi-data-mocker-interfaces) - package with mocking interfaces.
|
||||
|
||||
{{#generateApiDocs}}
|
||||
## API Endpoints
|
||||
|
||||
@ -135,17 +128,22 @@ All URIs are relative to *{{{basePath}}}*
|
||||
namespace {{apiPackage}};
|
||||
|
||||
use {{apiPackage}}\AbstractPetApi;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
class PetApi extends AbstractPetApi
|
||||
{
|
||||
|
||||
public function addPet($request, $response, $args)
|
||||
{
|
||||
public function addPet(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response
|
||||
): ResponseInterface {
|
||||
// your implementation of addPet method here
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When you need to inject dependencies into API controller check [PHP-DI - Controllers as services](https://github.com/PHP-DI/Slim-Bridge#controllers-as-services) guide.
|
||||
|
||||
Place all your implementation classes in `./src` folder accordingly.
|
||||
For instance, when abstract class located at `./lib/Api/AbstractPetApi.php` you need to create implementation class at `./src/Api/PetApi.php`.
|
||||
|
||||
|
@ -1,331 +0,0 @@
|
||||
<?php
|
||||
|
||||
{{>licenseInfo}}
|
||||
|
||||
/**
|
||||
* NOTE: This class is auto generated by the openapi generator program.
|
||||
* https://github.com/openapitools/openapi-generator
|
||||
* Do not edit the class manually.
|
||||
*/{{#apiInfo}}
|
||||
namespace {{invokerPackage}};
|
||||
|
||||
use Slim\Factory\AppFactory;
|
||||
use Slim\Interfaces\RouteInterface;
|
||||
use Slim\Exception\HttpNotImplementedException;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use InvalidArgumentException;
|
||||
use Dyorg\TokenAuthentication;
|
||||
use Dyorg\TokenAuthentication\TokenSearch;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use OpenAPIServer\Mock\OpenApiDataMocker;
|
||||
use OpenAPIServer\Mock\OpenApiDataMockerRouteMiddleware;
|
||||
{{#isSlimPsr7}}
|
||||
use Slim\Psr7\Factory\ResponseFactory;
|
||||
{{/isSlimPsr7}}
|
||||
{{#isNyholmPsr7}}
|
||||
use Nyholm\Psr7\Factory\Psr17Factory
|
||||
{{/isNyholmPsr7}}
|
||||
{{#isGuzzlePsr7}}
|
||||
use GuzzleHttp\Psr7\HttpFactory;
|
||||
{{/isGuzzlePsr7}}
|
||||
{{#isZendDiactoros}}
|
||||
use Zend\Diactoros\ResponseFactory;
|
||||
{{/isZendDiactoros}}
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* SlimRouter Class Doc Comment
|
||||
*
|
||||
* @package {{invokerPackage}}
|
||||
* @author OpenAPI Generator team
|
||||
* @link https://github.com/openapitools/openapi-generator
|
||||
*/
|
||||
class SlimRouter
|
||||
{
|
||||
|
||||
/** @var App instance */
|
||||
private $slimApp;
|
||||
|
||||
/** @var array[] list of all api operations */
|
||||
private $operations = [
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
[
|
||||
'httpMethod' => '{{httpMethod}}',
|
||||
'basePathWithoutHost' => '{{{basePathWithoutHost}}}',
|
||||
'path' => '{{{path}}}',
|
||||
'apiPackage' => '{{apiPackage}}',
|
||||
'classname' => '{{classname}}',
|
||||
'userClassname' => '{{userClassname}}',
|
||||
'operationId' => '{{operationId}}',
|
||||
'responses' => [
|
||||
{{#responses}}
|
||||
'{{#isDefault}}default{{/isDefault}}{{^isDefault}}{{code}}{{/isDefault}}' => [
|
||||
'jsonSchema' => '{{{jsonSchema}}}',
|
||||
],
|
||||
{{/responses}}
|
||||
],
|
||||
'authMethods' => [
|
||||
{{#hasAuthMethods}}
|
||||
{{#authMethods}}
|
||||
// {{type}} security schema named '{{name}}'
|
||||
{{#isBasicBasic}}
|
||||
[
|
||||
'type' => '{{type}}',
|
||||
'isBasic' => true,
|
||||
'isBearer' => false,
|
||||
'isApiKey' => false,
|
||||
'isOAuth' => false,
|
||||
],
|
||||
{{/isBasicBasic}}
|
||||
{{#isBasicBearer}}
|
||||
[
|
||||
'type' => '{{type}}',
|
||||
'isBasic' => true,
|
||||
'isBearer' => true,
|
||||
'isApiKey' => false,
|
||||
'isOAuth' => false,
|
||||
],
|
||||
{{/isBasicBearer}}
|
||||
{{#isApiKey}}
|
||||
[
|
||||
'type' => '{{type}}',
|
||||
'isBasic' => false,
|
||||
'isBearer' => false,
|
||||
'isApiKey' => true,
|
||||
'isOAuth' => false,
|
||||
'keyParamName' => '{{keyParamName}}',
|
||||
'isKeyInHeader' => {{#isKeyInHeader}}true{{/isKeyInHeader}}{{^isKeyInHeader}}false{{/isKeyInHeader}},
|
||||
'isKeyInQuery' => {{#isKeyInQuery}}true{{/isKeyInQuery}}{{^isKeyInQuery}}false{{/isKeyInQuery}},
|
||||
'isKeyInCookie' => {{#isKeyInCookie}}true{{/isKeyInCookie}}{{^isKeyInCookie}}false{{/isKeyInCookie}},
|
||||
],
|
||||
{{/isApiKey}}
|
||||
{{#isOAuth}}
|
||||
[
|
||||
'type' => '{{type}}',
|
||||
'isBasic' => false,
|
||||
'isBearer' => false,
|
||||
'isApiKey' => false,
|
||||
'isOAuth' => true,
|
||||
'scopes' => [
|
||||
{{#scopes}}
|
||||
'{{scope}}',{{#description}} // {{.}}{{/description}}
|
||||
{{/scopes}}
|
||||
],
|
||||
],
|
||||
{{/isOAuth}}
|
||||
{{/authMethods}}
|
||||
{{/hasAuthMethods}}
|
||||
],
|
||||
],
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
];
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
*
|
||||
* @param ContainerInterface|array $settings Either a ContainerInterface or an associative array of app settings
|
||||
*
|
||||
* @throws HttpNotImplementedException When implementation class doesn't exists
|
||||
* @throws Exception when not supported authorization schema type provided
|
||||
*/
|
||||
public function __construct($settings = [])
|
||||
{
|
||||
if ($settings instanceof ContainerInterface) {
|
||||
// Set container to create App with on AppFactory
|
||||
AppFactory::setContainer($settings);
|
||||
}
|
||||
$this->slimApp = AppFactory::create();
|
||||
|
||||
// middlewares requires Psr\Container\ContainerInterface
|
||||
$container = $this->slimApp->getContainer();
|
||||
|
||||
{{#hasAuthMethods}}
|
||||
$authPackage = '{{authPackage}}';
|
||||
$basicAuthenticator = function (ServerRequestInterface &$request, TokenSearch $tokenSearch) use ($authPackage) {
|
||||
$message = "How about extending {{abstractNamePrefix}}Authenticator{{abstractNameSuffix}} class by {$authPackage}\BasicAuthenticator?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
};
|
||||
$apiKeyAuthenticator = function (ServerRequestInterface &$request, TokenSearch $tokenSearch) use ($authPackage) {
|
||||
$message = "How about extending {{abstractNamePrefix}}Authenticator{{abstractNameSuffix}} class by {$authPackage}\ApiKeyAuthenticator?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
};
|
||||
$oAuthAuthenticator = function (ServerRequestInterface &$request, TokenSearch $tokenSearch) use ($authPackage) {
|
||||
$message = "How about extending {{abstractNamePrefix}}Authenticator{{abstractNameSuffix}} class by {$authPackage}\OAuthAuthenticator?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
};
|
||||
{{/hasAuthMethods}}
|
||||
|
||||
$userOptions = $this->getSetting($settings, 'tokenAuthenticationOptions', null);
|
||||
|
||||
// mocker options
|
||||
$mockerOptions = $this->getSetting($settings, 'mockerOptions', null);
|
||||
$dataMocker = $mockerOptions['dataMocker'] ?? new OpenApiDataMocker();
|
||||
{{#isSlimPsr7}}
|
||||
$responseFactory = new ResponseFactory();
|
||||
{{/isSlimPsr7}}
|
||||
{{#isNyholmPsr7}}
|
||||
$responseFactory = new Psr17Factory();
|
||||
{{/isNyholmPsr7}}
|
||||
{{#isGuzzlePsr7}}
|
||||
$responseFactory = new HttpFactory();
|
||||
{{/isGuzzlePsr7}}
|
||||
{{#isZendDiactoros}}
|
||||
$responseFactory = new ResponseFactory();
|
||||
{{/isZendDiactoros}}
|
||||
$getMockStatusCodeCallback = $mockerOptions['getMockStatusCodeCallback'] ?? null;
|
||||
$mockAfterCallback = $mockerOptions['afterCallback'] ?? null;
|
||||
|
||||
foreach ($this->operations as $operation) {
|
||||
$callback = function ($request, $response, $arguments) use ($operation) {
|
||||
$message = "How about extending {$operation['classname']} by {$operation['apiPackage']}\\{$operation['userClassname']} class implementing {$operation['operationId']} as a {$operation['httpMethod']} method?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
};
|
||||
$middlewares = [];
|
||||
|
||||
if (class_exists("\\{$operation['apiPackage']}\\{$operation['userClassname']}")) {
|
||||
$callback = "\\{$operation['apiPackage']}\\{$operation['userClassname']}:{$operation['operationId']}";
|
||||
}
|
||||
|
||||
{{#hasAuthMethods}}
|
||||
foreach ($operation['authMethods'] as $authMethod) {
|
||||
switch ($authMethod['type']) {
|
||||
case 'http':
|
||||
$authenticatorClassname = "\\{$authPackage}\\BasicAuthenticator";
|
||||
if (class_exists($authenticatorClassname)) {
|
||||
$basicAuthenticator = new $authenticatorClassname($container);
|
||||
}
|
||||
|
||||
$middlewares[] = new TokenAuthentication($this->getTokenAuthenticationOptions([
|
||||
'authenticator' => $basicAuthenticator,
|
||||
'regex' => $authMethod['isBearer'] ? '/Bearer\s+(.*)$/i' : '/Basic\s+(.*)$/i',
|
||||
'header' => 'Authorization',
|
||||
'parameter' => null,
|
||||
'cookie' => null,
|
||||
'argument' => null,
|
||||
], $userOptions));
|
||||
break;
|
||||
case 'apiKey':
|
||||
$authenticatorClassname = "\\{$authPackage}\\ApiKeyAuthenticator";
|
||||
if (class_exists($authenticatorClassname)) {
|
||||
$apiKeyAuthenticator = new $authenticatorClassname($container);
|
||||
}
|
||||
|
||||
$middlewares[] = new TokenAuthentication($this->getTokenAuthenticationOptions([
|
||||
'authenticator' => $apiKeyAuthenticator,
|
||||
'regex' => '/^(.*)$/i',
|
||||
'header' => $authMethod['isKeyInHeader'] ? $authMethod['keyParamName'] : null,
|
||||
'parameter' => $authMethod['isKeyInQuery'] ? $authMethod['keyParamName'] : null,
|
||||
'cookie' => $authMethod['isKeyInCookie'] ? $authMethod['keyParamName'] : null,
|
||||
'argument' => null,
|
||||
], $userOptions));
|
||||
break;
|
||||
case 'oauth2':
|
||||
$authenticatorClassname = "\\{$authPackage}\\OAuthAuthenticator";
|
||||
if (class_exists($authenticatorClassname)) {
|
||||
$oAuthAuthenticator = new $authenticatorClassname($container, $authMethod['scopes']);
|
||||
}
|
||||
|
||||
$middlewares[] = new TokenAuthentication($this->getTokenAuthenticationOptions([
|
||||
'authenticator' => $oAuthAuthenticator,
|
||||
'regex' => '/Bearer\s+(.*)$/i',
|
||||
'header' => 'Authorization',
|
||||
'parameter' => null,
|
||||
'cookie' => null,
|
||||
'argument' => null,
|
||||
], $userOptions));
|
||||
break;
|
||||
default:
|
||||
throw new Exception('Unknown authorization schema type');
|
||||
}
|
||||
}
|
||||
{{/hasAuthMethods}}
|
||||
|
||||
if (is_callable($getMockStatusCodeCallback)) {
|
||||
$mockSchemaResponses = array_map(function ($item) {
|
||||
return json_decode($item['jsonSchema'], true);
|
||||
}, $operation['responses']);
|
||||
$middlewares[] = new OpenApiDataMockerRouteMiddleware($dataMocker, $mockSchemaResponses, $responseFactory, $getMockStatusCodeCallback, $mockAfterCallback);
|
||||
}
|
||||
|
||||
$this->addRoute(
|
||||
[$operation['httpMethod']],
|
||||
"{$operation['basePathWithoutHost']}{$operation['path']}",
|
||||
$callback,
|
||||
$middlewares
|
||||
)->setName($operation['operationId']);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges user defined options with dynamic params
|
||||
*
|
||||
* @param array $staticOptions Required static options
|
||||
* @param array $userOptions User options
|
||||
*
|
||||
* @return array Merged array
|
||||
*/
|
||||
private function getTokenAuthenticationOptions(array $staticOptions, array $userOptions = null)
|
||||
{
|
||||
if (is_array($userOptions) === false) {
|
||||
return $staticOptions;
|
||||
}
|
||||
|
||||
return array_merge($userOptions, $staticOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns app setting by name.
|
||||
*
|
||||
* @param ContainerInterface|array $settings Either a ContainerInterface or an associative array of app settings
|
||||
* @param string $settingName Setting name
|
||||
* @param mixed $default Default setting value.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private function getSetting($settings, $settingName, $default = null)
|
||||
{
|
||||
if ($settings instanceof ContainerInterface && $settings->has($settingName)) {
|
||||
return $settings->get($settingName);
|
||||
} elseif (is_array($settings) && array_key_exists($settingName, $settings)) {
|
||||
return $settings[$settingName];
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add route with multiple methods
|
||||
*
|
||||
* @param string[] $methods Numeric array of HTTP method names
|
||||
* @param string $pattern The route URI pattern
|
||||
* @param callable|string $callable The route callback routine
|
||||
* @param array|null $middlewares List of middlewares
|
||||
*
|
||||
* @return RouteInterface
|
||||
*
|
||||
* @throws InvalidArgumentException If the route pattern isn't a string
|
||||
*/
|
||||
public function addRoute(array $methods, string $pattern, $callable, $middlewares = [])
|
||||
{
|
||||
$route = $this->slimApp->map($methods, $pattern, $callable);
|
||||
foreach ($middlewares as $middleware) {
|
||||
$route->add($middleware);
|
||||
}
|
||||
return $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Slim Framework instance
|
||||
*
|
||||
* @return App
|
||||
*/
|
||||
public function getSlimApp()
|
||||
{
|
||||
return $this->slimApp;
|
||||
}
|
||||
}
|
||||
{{/apiInfo}}
|
@ -9,7 +9,6 @@
|
||||
*/{{#apiInfo}}
|
||||
namespace {{authPackage}};
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Dyorg\TokenAuthentication;
|
||||
use Dyorg\TokenAuthentication\TokenSearch;
|
||||
@ -24,12 +23,6 @@ use Dyorg\TokenAuthentication\Exceptions\UnauthorizedExceptionInterface;
|
||||
*/
|
||||
abstract class {{abstractNamePrefix}}Authenticator{{abstractNameSuffix}}
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ContainerInterface|null Slim app container instance
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* @var string[]|null List of required scopes
|
||||
*/
|
||||
@ -49,12 +42,10 @@ abstract class {{abstractNamePrefix}}Authenticator{{abstractNameSuffix}}
|
||||
/**
|
||||
* Authenticator constructor
|
||||
*
|
||||
* @param ContainerInterface|null $container Slim app container instance
|
||||
* @param string[]|null $requiredScope List of required scopes
|
||||
* @param string[]|null $requiredScope List of required scopes
|
||||
*/
|
||||
public function __construct(ContainerInterface $container = null, $requiredScope = null)
|
||||
public function __construct($requiredScope = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->requiredScope = $requiredScope;
|
||||
}
|
||||
|
||||
|
@ -6,10 +6,11 @@
|
||||
* NOTE: This class is auto generated by the openapi generator program.
|
||||
* https://github.com/openapitools/openapi-generator
|
||||
* Do not edit the class manually.
|
||||
* Extend this class with your controller. You can inject dependencies via class constructor,
|
||||
* @see https://github.com/PHP-DI/Slim-Bridge basic example.
|
||||
*/
|
||||
namespace {{apiPackage}};
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Slim\Exception\HttpNotImplementedException;
|
||||
@ -23,25 +24,8 @@ use Slim\Exception\HttpNotImplementedException;
|
||||
*/
|
||||
abstract class {{classname}}
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ContainerInterface|null Slim app container instance
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Route Controller constructor receives container
|
||||
*
|
||||
* @param ContainerInterface|null $container Slim app container instance
|
||||
*/
|
||||
public function __construct(ContainerInterface $container = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
|
||||
/**
|
||||
* {{httpMethod}} {{operationId}}
|
||||
{{#summary}}
|
||||
@ -56,7 +40,11 @@ abstract class {{classname}}
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
{{#hasPathParams}}
|
||||
{{#pathParams}}
|
||||
* @param {{{dataType}}} ${{paramName}}{{#description}} {{.}}{{/description}}{{^description}} {{paramName}}{{/description}}
|
||||
{{/pathParams}}
|
||||
{{/hasPathParams}}
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
@ -64,19 +52,21 @@ abstract class {{classname}}
|
||||
* @deprecated
|
||||
{{/isDeprecated}}
|
||||
*/
|
||||
public function {{operationId}}(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
public function {{operationId}}(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response{{#hasPathParams}},{{/hasPathParams}}
|
||||
{{#hasPathParams}}
|
||||
{{#pathParams}}
|
||||
{{{dataType}}} ${{paramName}}{{^-last}},{{/-last}}
|
||||
{{/pathParams}}
|
||||
{{/hasPathParams}}
|
||||
): ResponseInterface {
|
||||
{{#hasHeaderParams}}
|
||||
$headers = $request->getHeaders();
|
||||
{{#headerParams}}
|
||||
${{paramName}} = $request->hasHeader('{{baseName}}') ? $headers['{{baseName}}'] : null;
|
||||
{{/headerParams}}
|
||||
{{/hasHeaderParams}}
|
||||
{{#hasPathParams}}
|
||||
{{#pathParams}}
|
||||
${{paramName}} = $args['{{baseName}}'];
|
||||
{{/pathParams}}
|
||||
{{/hasPathParams}}
|
||||
{{#hasQueryParams}}
|
||||
$queryParams = $request->getQueryParams();
|
||||
{{#queryParams}}
|
||||
@ -105,6 +95,9 @@ abstract class {{classname}}
|
||||
$message = "How about implementing {{nickname}} as a {{httpMethod}} method in {{apiPackage}}\{{userClassname}} class?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
}
|
||||
{{^-last}}
|
||||
|
||||
{{/-last}}
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
}
|
||||
|
@ -9,30 +9,30 @@
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"slim/slim": "^4.5.0",
|
||||
"dyorg/slim-token-authentication": "dev-slim4",
|
||||
"ybelenko/openapi-data-mocker": "^1.0",
|
||||
"ybelenko/openapi-data-mocker-server-middleware": "^1.0",
|
||||
{{#isSlimPsr7}}
|
||||
"slim/psr7": "^1.1.0"
|
||||
{{/isSlimPsr7}}
|
||||
{{#isNyholmPsr7}}
|
||||
"nyholm/psr7": "^1.3.0",
|
||||
"nyholm/psr7-server": "^0.4.1"
|
||||
{{/isNyholmPsr7}}
|
||||
{{#isGuzzlePsr7}}
|
||||
"guzzlehttp/psr7": "^1.6.1",
|
||||
"http-interop/http-factory-guzzle": "^1.0.0"
|
||||
"http-interop/http-factory-guzzle": "^1.0.0",
|
||||
{{/isGuzzlePsr7}}
|
||||
{{#isZendDiactoros}}
|
||||
"laminas/laminas-diactoros": "^2.3.0"
|
||||
"laminas/laminas-diactoros": "^2.3.0",
|
||||
{{/isZendDiactoros}}
|
||||
{{#isNyholmPsr7}}
|
||||
"nyholm/psr7": "^1.3.0",
|
||||
"nyholm/psr7-server": "^0.4.1",
|
||||
{{/isNyholmPsr7}}
|
||||
"php-di/slim-bridge": "^3.2",
|
||||
{{#isSlimPsr7}}
|
||||
"slim/psr7": "^1.1.0",
|
||||
{{/isSlimPsr7}}
|
||||
"ybelenko/openapi-data-mocker": "^1.0",
|
||||
"ybelenko/openapi-data-mocker-server-middleware": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"overtrue/phplint": "^2.0.2",
|
||||
{{#generateTests}}
|
||||
"phpunit/phpunit": "^8.0 || ^9.0",
|
||||
{{/generateTests}}
|
||||
"overtrue/phplint": "^2.0.2",
|
||||
"squizlabs/php_codesniffer": "^3.5"
|
||||
},
|
||||
"autoload": {
|
||||
@ -58,5 +58,8 @@
|
||||
{{/generateTests}}
|
||||
"phpcs": "phpcs",
|
||||
"phplint": "phplint ./ --exclude=vendor"
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
}
|
||||
}
|
||||
|
35
modules/openapi-generator/src/main/resources/php-slim4-server/config_dev_default.mustache
vendored
Normal file
35
modules/openapi-generator/src/main/resources/php-slim4-server/config_dev_default.mustache
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* App configuration defaults for development.
|
||||
* This file used when 'APP_ENV' variable set to 'dev' or 'development'. Check public/.htaccess file
|
||||
*/
|
||||
|
||||
// Enable error reporting
|
||||
error_reporting(E_ALL);
|
||||
ini_set("display_errors", 1);
|
||||
|
||||
/**
|
||||
* Each environment(dev, prod) should contain two files default.inc.php and config.inc.php.
|
||||
* This is the first file with development defaults. It contains all data which can be safely committed
|
||||
* to VCS(version control system). For sensitive values(passwords, api keys, emails) use config.inc.php
|
||||
* and make sure it's excluded from VCS by .gitignore.
|
||||
* do not add dependencies here, use {{appPackage}}\RegisterDependencies class
|
||||
* @see https://php-di.org/doc/php-definitions.html#values
|
||||
*/
|
||||
return [
|
||||
'mode' => 'development',
|
||||
|
||||
// slim framework settings
|
||||
'slim.displayErrorDetails' => true,
|
||||
'slim.logErrors' => false,
|
||||
'slim.logErrorDetails' => false,
|
||||
|
||||
// PDO
|
||||
'pdo.dsn' => 'mysql:host=localhost;charset=utf8mb4',
|
||||
'pdo.username' => 'root',
|
||||
'pdo.password' => 'root',
|
||||
'pdo.options' => [
|
||||
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
|
||||
],
|
||||
];
|
@ -1,83 +0,0 @@
|
||||
<?php
|
||||
|
||||
{{>licenseInfo}}
|
||||
|
||||
/**
|
||||
* App configuration file example.
|
||||
*
|
||||
* Copy file to config/dev/config.inc.php and config/prod/config.inc.php
|
||||
* App loads dev config only when prod doesn't exist
|
||||
* in other words if both configs presented - prod config applies
|
||||
*/
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use OpenAPIServer\Mock\OpenApiDataMocker;
|
||||
|
||||
$mocker = new OpenApiDataMocker();
|
||||
$mocker->setModelsNamespace('{{modelPackage}}\\');
|
||||
|
||||
return [
|
||||
'slimSettings' => [
|
||||
'displayErrorDetails' => false,
|
||||
'logErrors' => true,
|
||||
'logErrorDetails' => true,
|
||||
],
|
||||
|
||||
'tokenAuthenticationOptions' => [
|
||||
/**
|
||||
* Tokens are essentially passwords. You should treat them as such and you should always
|
||||
* use HTTPS. If the middleware detects insecure usage over HTTP it will return unauthorized
|
||||
* with a message Required HTTPS for token authentication. This rule is relaxed for requests
|
||||
* on localhost. To allow insecure usage you must enable it manually by setting secure to
|
||||
* false.
|
||||
* Default: true
|
||||
*/
|
||||
// 'secure' => true,
|
||||
|
||||
/**
|
||||
* Alternatively you can list your development host to have relaxed security.
|
||||
* Default: ['localhost', '127.0.0.1']
|
||||
*/
|
||||
// 'relaxed' => ['localhost', '127.0.0.1'],
|
||||
|
||||
/**
|
||||
* By default on occurred a fail on authentication, is sent a response on json format with a
|
||||
* message (`Invalid Token` or `Not found Token`) and with the token (if found), with status
|
||||
* `401 Unauthorized`. You can customize it by setting a callable function on error option.
|
||||
* Default: null
|
||||
*/
|
||||
// 'error' => null,
|
||||
],
|
||||
|
||||
'mockerOptions' => [
|
||||
// 'dataMocker' => $mocker,
|
||||
|
||||
// 'getMockStatusCodeCallback' => function (ServerRequestInterface $request, array $responses) {
|
||||
// // check if client clearly asks for mocked response
|
||||
// $pingHeader = 'X-{{invokerPackage}}-Mock';
|
||||
// $pingHeaderCode = 'X-{{invokerPackage}}-Mock-Code';
|
||||
// if (
|
||||
// $request->hasHeader($pingHeader)
|
||||
// && $request->getHeader($pingHeader)[0] === 'ping'
|
||||
// ) {
|
||||
// $responses = (array) $responses;
|
||||
// $requestedResponseCode = ($request->hasHeader($pingHeaderCode)) ? $request->getHeader($pingHeaderCode)[0] : 'default';
|
||||
// if (array_key_exists($requestedResponseCode, $responses)) {
|
||||
// return $requestedResponseCode;
|
||||
// }
|
||||
|
||||
// // return first response key
|
||||
// reset($responses);
|
||||
// return key($responses);
|
||||
// }
|
||||
|
||||
// return false;
|
||||
// },
|
||||
|
||||
// 'afterCallback' => function (ServerRequestInterface $request, ResponseInterface $response) {
|
||||
// // mark mocked response to distinguish real and fake responses
|
||||
// return $response->withHeader('X-{{invokerPackage}}-Mock', 'pong');
|
||||
// },
|
||||
],
|
||||
];
|
35
modules/openapi-generator/src/main/resources/php-slim4-server/config_prod_default.mustache
vendored
Normal file
35
modules/openapi-generator/src/main/resources/php-slim4-server/config_prod_default.mustache
vendored
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* App configuration defaults for production.
|
||||
* This file used when 'APP_ENV' variable set to 'prod' or 'production'. Check public/.htaccess file
|
||||
*/
|
||||
|
||||
// Disable error reporting
|
||||
error_reporting(0);
|
||||
ini_set('display_errors', '0');
|
||||
|
||||
/**
|
||||
* Each environment(dev, prod) should contain two files default.inc.php and config.inc.php.
|
||||
* This is the first file with production defaults. It contains all data which can be safely committed
|
||||
* to VCS(version control system). For sensitive values(passwords, api keys, emails) use config.inc.php
|
||||
* and make sure it's excluded from VCS by .gitignore.
|
||||
* do not add dependencies here, use {{appPackage}}\RegisterDependencies class
|
||||
* @see https://php-di.org/doc/php-definitions.html#values
|
||||
*/
|
||||
return [
|
||||
'mode' => 'production',
|
||||
|
||||
// slim framework settings
|
||||
'slim.displayErrorDetails' => false,
|
||||
'slim.logErrors' => true,
|
||||
'slim.logErrorDetails' => true,
|
||||
|
||||
// PDO
|
||||
'pdo.dsn' => 'mysql:host=localhost;charset=utf8mb4',
|
||||
'pdo.username' => 'root',
|
||||
'pdo.password' => 'root',
|
||||
'pdo.options' => [
|
||||
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
|
||||
],
|
||||
];
|
@ -20,5 +20,5 @@ composer.phar
|
||||
# Application config may contain sensitive data
|
||||
/config/**/*.*
|
||||
!/config/.htaccess
|
||||
!/config/dev/example.inc.php
|
||||
!/config/prod/example.inc.php
|
||||
!/config/dev/default.inc.php
|
||||
!/config/prod/default.inc.php
|
||||
|
@ -9,49 +9,64 @@
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use {{invokerPackage}}\SlimRouter;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use OpenAPIServer\Mock\OpenApiDataMocker;
|
||||
use DI\Bridge\Slim\Bridge;
|
||||
use DI\ContainerBuilder;
|
||||
use {{appPackage}}\RegisterDependencies;
|
||||
use {{appPackage}}\RegisterRoutes;
|
||||
use {{appPackage}}\RegisterMiddlewares;
|
||||
use Slim\Factory\ServerRequestCreatorFactory;
|
||||
use Slim\ResponseEmitter;
|
||||
{{/apiInfo}}
|
||||
|
||||
// load config file
|
||||
$config = [];
|
||||
if (is_array($prodConfig = @include(__DIR__ . '/../config/prod/config.inc.php'))) {
|
||||
$config = $prodConfig;
|
||||
} elseif (is_array($devConfig = @include(__DIR__ . '/../config/dev/config.inc.php'))) {
|
||||
$config = $devConfig;
|
||||
} else {
|
||||
throw new InvalidArgumentException('Config file missed or broken.');
|
||||
// Instantiate PHP-DI ContainerBuilder
|
||||
$builder = new ContainerBuilder();
|
||||
|
||||
// consider prod by default
|
||||
$env;
|
||||
switch (strtolower($_SERVER['APP_ENV'] ?? 'prod')) {
|
||||
case 'development':
|
||||
case 'dev':
|
||||
$env = 'dev';
|
||||
break;
|
||||
case 'production':
|
||||
case 'prod':
|
||||
default:
|
||||
$env = 'prod';
|
||||
}
|
||||
|
||||
$router = new SlimRouter($config);
|
||||
$app = $router->getSlimApp();
|
||||
// Main configuration
|
||||
$builder->addDefinitions(__DIR__ . "/../config/{$env}/default.inc.php");
|
||||
|
||||
// Parse json, form data and xml
|
||||
$app->addBodyParsingMiddleware();
|
||||
// Config file for the environment if exists
|
||||
$userConfig = __DIR__ . "/../config/{$env}/config.inc.php";
|
||||
if (file_exists($userConfig)) {
|
||||
$builder->addDefinitions($userConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* The routing middleware should be added before the ErrorMiddleware
|
||||
* Otherwise exceptions thrown from it will not be handled
|
||||
*/
|
||||
$app->addRoutingMiddleware();
|
||||
// Set up dependencies
|
||||
$dependencies = new RegisterDependencies();
|
||||
$dependencies($builder);
|
||||
|
||||
/**
|
||||
* Add Error Handling Middleware
|
||||
*
|
||||
* @param bool $displayErrorDetails -> Should be set to false in production
|
||||
* @param bool $logErrors -> Parameter is passed to the default ErrorHandler
|
||||
* @param bool $logErrorDetails -> Display error details in error log
|
||||
* which can be replaced by a callable of your choice.
|
||||
// Build PHP-DI Container instance
|
||||
$container = $builder->build();
|
||||
|
||||
* Note: This middleware should be added last. It will not handle any exceptions/errors
|
||||
* for middleware added after it.
|
||||
*/
|
||||
$app->addErrorMiddleware(
|
||||
$config['slimSettings']['displayErrorDetails'] ?? false,
|
||||
$config['slimSettings']['logErrors'] ?? true,
|
||||
$config['slimSettings']['logErrorDetails'] ?? true
|
||||
);
|
||||
// Instantiate the app
|
||||
$app = Bridge::create($container);
|
||||
|
||||
$app->run();
|
||||
// Register middleware
|
||||
$middleware = new RegisterMiddlewares();
|
||||
$middleware($app);
|
||||
|
||||
// Register routes
|
||||
// yes, it's anti-pattern you shouldn't get deps from container directly
|
||||
$routes = $container->get(RegisterRoutes::class);
|
||||
$routes($app);
|
||||
|
||||
// Create Request object from globals
|
||||
$serverRequestCreator = ServerRequestCreatorFactory::create();
|
||||
$request = $serverRequestCreator->createServerRequestFromGlobals();
|
||||
|
||||
// Run App & Emit Response
|
||||
$response = $app->handle($request);
|
||||
$responseEmitter = new ResponseEmitter();
|
||||
$responseEmitter->emit($response);
|
||||
|
58
modules/openapi-generator/src/main/resources/php-slim4-server/register_dependencies.mustache
vendored
Normal file
58
modules/openapi-generator/src/main/resources/php-slim4-server/register_dependencies.mustache
vendored
Normal file
@ -0,0 +1,58 @@
|
||||
<?php
|
||||
|
||||
{{>licenseInfo}}
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* NOTE: This class is auto generated by the openapi generator program.
|
||||
* https://github.com/openapitools/openapi-generator
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
namespace {{appPackage}};
|
||||
|
||||
/**
|
||||
* RegisterDependencies
|
||||
*
|
||||
* Recommendations from template creator:
|
||||
*
|
||||
* I don't use imports(eg. use Slim\Middleware\ErrorMiddleware) here because each package unlikely
|
||||
* be used in code twice. It helps to keep that file short and make Git history cleaner.
|
||||
*
|
||||
* This class declared as final because two classes with dependency injections can cause confusion. Edit
|
||||
* template of this class or use your own implementation instead(overwrite index.php to import your
|
||||
* custom class).
|
||||
*/
|
||||
final class RegisterDependencies
|
||||
{
|
||||
/**
|
||||
* Adds dependency definitions.
|
||||
*
|
||||
* @param \DI\ContainerBuilder $containerBuilder Container builder.
|
||||
*
|
||||
* @see https://php-di.org/doc/php-definitions.html
|
||||
*/
|
||||
public function __invoke(\DI\ContainerBuilder $containerBuilder): void
|
||||
{
|
||||
$containerBuilder->addDefinitions([
|
||||
// Response factory required as typed argument in next ErrorMiddleware injection
|
||||
\Psr\Http\Message\ResponseFactoryInterface::class => \DI\factory([\Slim\Factory\AppFactory::class, 'determineResponseFactory']),
|
||||
|
||||
// Slim error middleware
|
||||
// @see https://www.slimframework.com/docs/v4/middleware/error-handling.html
|
||||
\Slim\Middleware\ErrorMiddleware::class => \DI\autowire()
|
||||
->constructorParameter('displayErrorDetails', \DI\get('slim.displayErrorDetails', false))
|
||||
->constructorParameter('logErrors', \DI\get('slim.logErrors', true))
|
||||
->constructorParameter('logErrorDetails', \DI\get('slim.logErrorDetails', true)),
|
||||
|
||||
// PDO class for database managing
|
||||
\PDO::class => \DI\create()
|
||||
->constructor(
|
||||
\DI\get('pdo.dsn'),
|
||||
\DI\get('pdo.username'),
|
||||
\DI\get('pdo.password'),
|
||||
\DI\get('pdo.options', null)
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
51
modules/openapi-generator/src/main/resources/php-slim4-server/register_middlewares.mustache
vendored
Normal file
51
modules/openapi-generator/src/main/resources/php-slim4-server/register_middlewares.mustache
vendored
Normal file
@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
{{>licenseInfo}}
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* NOTE: This class is auto generated by the openapi generator program.
|
||||
* https://github.com/openapitools/openapi-generator
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
namespace {{appPackage}};
|
||||
|
||||
/**
|
||||
* RegisterMiddlewares
|
||||
*
|
||||
* Recommendations from template creator:
|
||||
*
|
||||
* There is no way to add route related middlewares here, add global ones. Route related middlewares
|
||||
* can be applied in \{{appPackage}}\RegisterRoutes class.
|
||||
*
|
||||
* I add middlewares by full class names(\Slim\Middleware\ErrorMiddleware::class) because that way
|
||||
* Slim initiates them with options from Container. They already configured, don't need to pass any
|
||||
* options manually.
|
||||
*
|
||||
* I don't use imports(eg. use Slim\Middleware\ErrorMiddleware) here because each package unlikely
|
||||
* be used in code twice. It helps to keep that file short and make Git history cleaner.
|
||||
*
|
||||
* This class declared as final because two classes with middlewares can cause confusion. Edit
|
||||
* template of this class or use your own implementation instead(overwrite index.php to import your
|
||||
* custom class).
|
||||
*/
|
||||
final class RegisterMiddlewares
|
||||
{
|
||||
/**
|
||||
* Adds middlewares to Slim app instance.
|
||||
*
|
||||
* @param \Slim\App $app App instance.
|
||||
*/
|
||||
public function __invoke(\Slim\App $app): void
|
||||
{
|
||||
// Parse json, form data and xml
|
||||
$app->addBodyParsingMiddleware();
|
||||
|
||||
// Add Routing Middleware
|
||||
$app->addRoutingMiddleware();
|
||||
|
||||
// Add Error Middleware
|
||||
$app->add(\Slim\Middleware\ErrorMiddleware::class);
|
||||
}
|
||||
}
|
137
modules/openapi-generator/src/main/resources/php-slim4-server/register_routes.mustache
vendored
Normal file
137
modules/openapi-generator/src/main/resources/php-slim4-server/register_routes.mustache
vendored
Normal file
@ -0,0 +1,137 @@
|
||||
<?php
|
||||
|
||||
{{>licenseInfo}}
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* NOTE: This class is auto generated by the openapi generator program.
|
||||
* https://github.com/openapitools/openapi-generator
|
||||
* Do not edit the class manually.
|
||||
*/{{#apiInfo}}
|
||||
namespace {{appPackage}};
|
||||
|
||||
use Slim\Exception\HttpNotImplementedException;
|
||||
|
||||
/**
|
||||
* RegisterRoutes Class Doc Comment
|
||||
*
|
||||
* @package {{invokerPackage}}
|
||||
* @author OpenAPI Generator team
|
||||
* @link https://github.com/openapitools/openapi-generator
|
||||
*/
|
||||
class RegisterRoutes
|
||||
{
|
||||
/** @var array[] list of all api operations */
|
||||
private $operations = [
|
||||
{{#apis}}
|
||||
{{#operations}}
|
||||
{{#operation}}
|
||||
[
|
||||
'httpMethod' => '{{httpMethod}}',
|
||||
'basePathWithoutHost' => '{{{basePathWithoutHost}}}',
|
||||
'path' => '{{{path}}}',
|
||||
'apiPackage' => '{{apiPackage}}',
|
||||
'classname' => '{{classname}}',
|
||||
'userClassname' => '{{userClassname}}',
|
||||
'operationId' => '{{operationId}}',
|
||||
'responses' => [
|
||||
{{#responses}}
|
||||
'{{#isDefault}}default{{/isDefault}}{{^isDefault}}{{code}}{{/isDefault}}' => [
|
||||
'jsonSchema' => '{{{jsonSchema}}}',
|
||||
],
|
||||
{{/responses}}
|
||||
],
|
||||
'authMethods' => [
|
||||
{{#hasAuthMethods}}
|
||||
{{#authMethods}}
|
||||
// {{type}} security schema named '{{name}}'
|
||||
{{#isBasicBasic}}
|
||||
[
|
||||
'type' => '{{type}}',
|
||||
'isBasic' => true,
|
||||
'isBearer' => false,
|
||||
'isApiKey' => false,
|
||||
'isOAuth' => false,
|
||||
],
|
||||
{{/isBasicBasic}}
|
||||
{{#isBasicBearer}}
|
||||
[
|
||||
'type' => '{{type}}',
|
||||
'isBasic' => true,
|
||||
'isBearer' => true,
|
||||
'isApiKey' => false,
|
||||
'isOAuth' => false,
|
||||
],
|
||||
{{/isBasicBearer}}
|
||||
{{#isApiKey}}
|
||||
[
|
||||
'type' => '{{type}}',
|
||||
'isBasic' => false,
|
||||
'isBearer' => false,
|
||||
'isApiKey' => true,
|
||||
'isOAuth' => false,
|
||||
'keyParamName' => '{{keyParamName}}',
|
||||
'isKeyInHeader' => {{#isKeyInHeader}}true{{/isKeyInHeader}}{{^isKeyInHeader}}false{{/isKeyInHeader}},
|
||||
'isKeyInQuery' => {{#isKeyInQuery}}true{{/isKeyInQuery}}{{^isKeyInQuery}}false{{/isKeyInQuery}},
|
||||
'isKeyInCookie' => {{#isKeyInCookie}}true{{/isKeyInCookie}}{{^isKeyInCookie}}false{{/isKeyInCookie}},
|
||||
],
|
||||
{{/isApiKey}}
|
||||
{{#isOAuth}}
|
||||
[
|
||||
'type' => '{{type}}',
|
||||
'isBasic' => false,
|
||||
'isBearer' => false,
|
||||
'isApiKey' => false,
|
||||
'isOAuth' => true,
|
||||
'scopes' => [
|
||||
{{#scopes}}
|
||||
'{{scope}}',{{#description}} // {{.}}{{/description}}
|
||||
{{/scopes}}
|
||||
],
|
||||
],
|
||||
{{/isOAuth}}
|
||||
{{/authMethods}}
|
||||
{{/hasAuthMethods}}
|
||||
],
|
||||
],
|
||||
{{/operation}}
|
||||
{{/operations}}
|
||||
{{/apis}}
|
||||
];
|
||||
|
||||
/**
|
||||
* Add routes to Slim app.
|
||||
*
|
||||
* @param \Slim\App $app Pre-configured Slim application instance
|
||||
*
|
||||
* @throws HttpNotImplementedException When implementation class doesn't exists
|
||||
*/
|
||||
public function __invoke(\Slim\App $app): void
|
||||
{
|
||||
foreach ($this->operations as $operation) {
|
||||
$callback = function ($request) use ($operation) {
|
||||
$message = "How about extending {$operation['classname']} by {$operation['apiPackage']}\\{$operation['userClassname']} class implementing {$operation['operationId']} as a {$operation['httpMethod']} method?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
};
|
||||
$middlewares = [];
|
||||
|
||||
if (class_exists("\\{$operation['apiPackage']}\\{$operation['userClassname']}")) {
|
||||
// Notice how we register the controller using the class name?
|
||||
// PHP-DI will instantiate the class for us only when it's actually necessary
|
||||
$callback = ["\\{$operation['apiPackage']}\\{$operation['userClassname']}", $operation['operationId']];
|
||||
}
|
||||
|
||||
$route = $app->map(
|
||||
[$operation['httpMethod']],
|
||||
"{$operation['basePathWithoutHost']}{$operation['path']}",
|
||||
$callback
|
||||
)->setName($operation['operationId']);
|
||||
|
||||
foreach ($middlewares as $middleware) {
|
||||
$route->add($middleware);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
{{/apiInfo}}
|
4
samples/server/petstore/php-slim4/.gitignore
vendored
4
samples/server/petstore/php-slim4/.gitignore
vendored
@ -20,5 +20,5 @@ composer.phar
|
||||
# Application config may contain sensitive data
|
||||
/config/**/*.*
|
||||
!/config/.htaccess
|
||||
!/config/dev/example.inc.php
|
||||
!/config/prod/example.inc.php
|
||||
!/config/dev/default.inc.php
|
||||
!/config/prod/default.inc.php
|
||||
|
@ -2,11 +2,14 @@
|
||||
README.md
|
||||
composer.json
|
||||
config/.htaccess
|
||||
config/dev/example.inc.php
|
||||
config/prod/example.inc.php
|
||||
config/dev/default.inc.php
|
||||
config/prod/default.inc.php
|
||||
lib/Api/AbstractPetApi.php
|
||||
lib/Api/AbstractStoreApi.php
|
||||
lib/Api/AbstractUserApi.php
|
||||
lib/App/RegisterDependencies.php
|
||||
lib/App/RegisterMiddlewares.php
|
||||
lib/App/RegisterRoutes.php
|
||||
lib/Auth/AbstractAuthenticator.php
|
||||
lib/BaseModel.php
|
||||
lib/Model/ApiResponse.php
|
||||
@ -15,7 +18,6 @@ lib/Model/Order.php
|
||||
lib/Model/Pet.php
|
||||
lib/Model/Tag.php
|
||||
lib/Model/User.php
|
||||
lib/SlimRouter.php
|
||||
phpcs.xml.dist
|
||||
phpunit.xml.dist
|
||||
public/.htaccess
|
||||
|
@ -4,6 +4,7 @@
|
||||
* [Slim 4 Documentation](https://www.slimframework.com/docs/v4/)
|
||||
|
||||
This server has been generated with [Slim PSR-7](https://github.com/slimphp/Slim-Psr7) implementation.
|
||||
[PHP-DI](https://php-di.org/doc/frameworks/slim.html) package used as dependency container.
|
||||
|
||||
## Requirements
|
||||
|
||||
@ -23,7 +24,10 @@ $ composer install
|
||||
|
||||
## Add configs
|
||||
|
||||
Application requires at least one config file(`config/dev/config.inc.php` or `config/prod/config.inc.php`). You can use [config/dev/example.inc.php](config/dev/example.inc.php) as starting point.
|
||||
[PHP-DI package](https://php-di.org/doc/getting-started.html) helps to decouple configuration from implementation. App loads configuration files in straight order(`$env` can be `prod` or `dev`):
|
||||
1. `config/$env/default.inc.php` (contains safe values, can be committed to vcs)
|
||||
2. `config/$env/config.inc.php` (user config, excluded from vcs, can contain sensitive values, passwords etc.)
|
||||
3. `lib/App/RegisterDependencies.php`
|
||||
|
||||
## Start devserver
|
||||
|
||||
@ -86,25 +90,14 @@ $ composer phplint
|
||||
|
||||
## Show errors
|
||||
|
||||
Switch on option in your application config file like:
|
||||
```diff
|
||||
return [
|
||||
'slimSettings' => [
|
||||
- 'displayErrorDetails' => false,
|
||||
+ 'displayErrorDetails' => true,
|
||||
'logErrors' => true,
|
||||
'logErrorDetails' => true,
|
||||
],
|
||||
Switch your app environment to development in `public/.htaccess` file:
|
||||
```ini
|
||||
## .htaccess
|
||||
<IfModule mod_env.c>
|
||||
SetEnv APP_ENV 'development'
|
||||
</IfModule>
|
||||
```
|
||||
|
||||
## Mock Server
|
||||
For a quick start uncomment [mocker middleware options](config/dev/example.inc.php#L67-L94) in your application config file.
|
||||
|
||||
Used packages:
|
||||
* [Openapi Data Mocker](https://github.com/ybelenko/openapi-data-mocker) - first implementation of OAS3 fake data generator.
|
||||
* [Openapi Data Mocker Server Middleware](https://github.com/ybelenko/openapi-data-mocker-server-middleware) - PSR-15 HTTP server middleware.
|
||||
* [Openapi Data Mocker Interfaces](https://github.com/ybelenko/openapi-data-mocker-interfaces) - package with mocking interfaces.
|
||||
|
||||
## API Endpoints
|
||||
|
||||
All URIs are relative to *http://petstore.swagger.io/v2*
|
||||
@ -117,17 +110,22 @@ All URIs are relative to *http://petstore.swagger.io/v2*
|
||||
namespace OpenAPIServer\Api;
|
||||
|
||||
use OpenAPIServer\Api\AbstractPetApi;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
|
||||
class PetApi extends AbstractPetApi
|
||||
{
|
||||
|
||||
public function addPet($request, $response, $args)
|
||||
{
|
||||
public function addPet(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response
|
||||
): ResponseInterface {
|
||||
// your implementation of addPet method here
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
When you need to inject dependencies into API controller check [PHP-DI - Controllers as services](https://github.com/PHP-DI/Slim-Bridge#controllers-as-services) guide.
|
||||
|
||||
Place all your implementation classes in `./src` folder accordingly.
|
||||
For instance, when abstract class located at `./lib/Api/AbstractPetApi.php` you need to create implementation class at `./src/Api/PetApi.php`.
|
||||
|
||||
|
@ -9,15 +9,15 @@
|
||||
],
|
||||
"require": {
|
||||
"php": "^7.4 || ^8.0",
|
||||
"slim/slim": "^4.5.0",
|
||||
"dyorg/slim-token-authentication": "dev-slim4",
|
||||
"php-di/slim-bridge": "^3.2",
|
||||
"slim/psr7": "^1.1.0",
|
||||
"ybelenko/openapi-data-mocker": "^1.0",
|
||||
"ybelenko/openapi-data-mocker-server-middleware": "^1.0",
|
||||
"slim/psr7": "^1.1.0"
|
||||
"ybelenko/openapi-data-mocker-server-middleware": "^1.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^8.0 || ^9.0",
|
||||
"overtrue/phplint": "^2.0.2",
|
||||
"phpunit/phpunit": "^8.0 || ^9.0",
|
||||
"squizlabs/php_codesniffer": "^3.5"
|
||||
},
|
||||
"autoload": {
|
||||
@ -37,5 +37,8 @@
|
||||
"test-models": "phpunit --testsuite Models",
|
||||
"phpcs": "phpcs",
|
||||
"phplint": "phplint ./ --exclude=vendor"
|
||||
},
|
||||
"config": {
|
||||
"sort-packages": true
|
||||
}
|
||||
}
|
||||
|
35
samples/server/petstore/php-slim4/config/dev/default.inc.php
Normal file
35
samples/server/petstore/php-slim4/config/dev/default.inc.php
Normal file
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* App configuration defaults for development.
|
||||
* This file used when 'APP_ENV' variable set to 'dev' or 'development'. Check public/.htaccess file
|
||||
*/
|
||||
|
||||
// Enable error reporting
|
||||
error_reporting(E_ALL);
|
||||
ini_set("display_errors", 1);
|
||||
|
||||
/**
|
||||
* Each environment(dev, prod) should contain two files default.inc.php and config.inc.php.
|
||||
* This is the first file with development defaults. It contains all data which can be safely committed
|
||||
* to VCS(version control system). For sensitive values(passwords, api keys, emails) use config.inc.php
|
||||
* and make sure it's excluded from VCS by .gitignore.
|
||||
* do not add dependencies here, use OpenAPIServer\App\RegisterDependencies class
|
||||
* @see https://php-di.org/doc/php-definitions.html#values
|
||||
*/
|
||||
return [
|
||||
'mode' => 'development',
|
||||
|
||||
// slim framework settings
|
||||
'slim.displayErrorDetails' => true,
|
||||
'slim.logErrors' => false,
|
||||
'slim.logErrorDetails' => false,
|
||||
|
||||
// PDO
|
||||
'pdo.dsn' => 'mysql:host=localhost;charset=utf8mb4',
|
||||
'pdo.username' => 'root',
|
||||
'pdo.password' => 'root',
|
||||
'pdo.options' => [
|
||||
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
|
||||
],
|
||||
];
|
@ -1,96 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* PHP version 7.4
|
||||
*
|
||||
* @package OpenAPIServer
|
||||
* @author OpenAPI Generator team
|
||||
* @link https://github.com/openapitools/openapi-generator
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
* Generated by: https://github.com/openapitools/openapi-generator.git
|
||||
*/
|
||||
|
||||
/**
|
||||
* App configuration file example.
|
||||
*
|
||||
* Copy file to config/dev/config.inc.php and config/prod/config.inc.php
|
||||
* App loads dev config only when prod doesn't exist
|
||||
* in other words if both configs presented - prod config applies
|
||||
*/
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use OpenAPIServer\Mock\OpenApiDataMocker;
|
||||
|
||||
$mocker = new OpenApiDataMocker();
|
||||
$mocker->setModelsNamespace('OpenAPIServer\Model\\');
|
||||
|
||||
return [
|
||||
'slimSettings' => [
|
||||
'displayErrorDetails' => false,
|
||||
'logErrors' => true,
|
||||
'logErrorDetails' => true,
|
||||
],
|
||||
|
||||
'tokenAuthenticationOptions' => [
|
||||
/**
|
||||
* Tokens are essentially passwords. You should treat them as such and you should always
|
||||
* use HTTPS. If the middleware detects insecure usage over HTTP it will return unauthorized
|
||||
* with a message Required HTTPS for token authentication. This rule is relaxed for requests
|
||||
* on localhost. To allow insecure usage you must enable it manually by setting secure to
|
||||
* false.
|
||||
* Default: true
|
||||
*/
|
||||
// 'secure' => true,
|
||||
|
||||
/**
|
||||
* Alternatively you can list your development host to have relaxed security.
|
||||
* Default: ['localhost', '127.0.0.1']
|
||||
*/
|
||||
// 'relaxed' => ['localhost', '127.0.0.1'],
|
||||
|
||||
/**
|
||||
* By default on occurred a fail on authentication, is sent a response on json format with a
|
||||
* message (`Invalid Token` or `Not found Token`) and with the token (if found), with status
|
||||
* `401 Unauthorized`. You can customize it by setting a callable function on error option.
|
||||
* Default: null
|
||||
*/
|
||||
// 'error' => null,
|
||||
],
|
||||
|
||||
'mockerOptions' => [
|
||||
// 'dataMocker' => $mocker,
|
||||
|
||||
// 'getMockStatusCodeCallback' => function (ServerRequestInterface $request, array $responses) {
|
||||
// // check if client clearly asks for mocked response
|
||||
// $pingHeader = 'X-OpenAPIServer-Mock';
|
||||
// $pingHeaderCode = 'X-OpenAPIServer-Mock-Code';
|
||||
// if (
|
||||
// $request->hasHeader($pingHeader)
|
||||
// && $request->getHeader($pingHeader)[0] === 'ping'
|
||||
// ) {
|
||||
// $responses = (array) $responses;
|
||||
// $requestedResponseCode = ($request->hasHeader($pingHeaderCode)) ? $request->getHeader($pingHeaderCode)[0] : 'default';
|
||||
// if (array_key_exists($requestedResponseCode, $responses)) {
|
||||
// return $requestedResponseCode;
|
||||
// }
|
||||
|
||||
// // return first response key
|
||||
// reset($responses);
|
||||
// return key($responses);
|
||||
// }
|
||||
|
||||
// return false;
|
||||
// },
|
||||
|
||||
// 'afterCallback' => function (ServerRequestInterface $request, ResponseInterface $response) {
|
||||
// // mark mocked response to distinguish real and fake responses
|
||||
// return $response->withHeader('X-OpenAPIServer-Mock', 'pong');
|
||||
// },
|
||||
],
|
||||
];
|
@ -0,0 +1,35 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* App configuration defaults for production.
|
||||
* This file used when 'APP_ENV' variable set to 'prod' or 'production'. Check public/.htaccess file
|
||||
*/
|
||||
|
||||
// Disable error reporting
|
||||
error_reporting(0);
|
||||
ini_set('display_errors', '0');
|
||||
|
||||
/**
|
||||
* Each environment(dev, prod) should contain two files default.inc.php and config.inc.php.
|
||||
* This is the first file with production defaults. It contains all data which can be safely committed
|
||||
* to VCS(version control system). For sensitive values(passwords, api keys, emails) use config.inc.php
|
||||
* and make sure it's excluded from VCS by .gitignore.
|
||||
* do not add dependencies here, use OpenAPIServer\App\RegisterDependencies class
|
||||
* @see https://php-di.org/doc/php-definitions.html#values
|
||||
*/
|
||||
return [
|
||||
'mode' => 'production',
|
||||
|
||||
// slim framework settings
|
||||
'slim.displayErrorDetails' => false,
|
||||
'slim.logErrors' => true,
|
||||
'slim.logErrorDetails' => true,
|
||||
|
||||
// PDO
|
||||
'pdo.dsn' => 'mysql:host=localhost;charset=utf8mb4',
|
||||
'pdo.username' => 'root',
|
||||
'pdo.password' => 'root',
|
||||
'pdo.options' => [
|
||||
\PDO::ATTR_ERRMODE => \PDO::ERRMODE_EXCEPTION,
|
||||
],
|
||||
];
|
@ -1,96 +0,0 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* PHP version 7.4
|
||||
*
|
||||
* @package OpenAPIServer
|
||||
* @author OpenAPI Generator team
|
||||
* @link https://github.com/openapitools/openapi-generator
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
* Generated by: https://github.com/openapitools/openapi-generator.git
|
||||
*/
|
||||
|
||||
/**
|
||||
* App configuration file example.
|
||||
*
|
||||
* Copy file to config/dev/config.inc.php and config/prod/config.inc.php
|
||||
* App loads dev config only when prod doesn't exist
|
||||
* in other words if both configs presented - prod config applies
|
||||
*/
|
||||
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use OpenAPIServer\Mock\OpenApiDataMocker;
|
||||
|
||||
$mocker = new OpenApiDataMocker();
|
||||
$mocker->setModelsNamespace('OpenAPIServer\Model\\');
|
||||
|
||||
return [
|
||||
'slimSettings' => [
|
||||
'displayErrorDetails' => false,
|
||||
'logErrors' => true,
|
||||
'logErrorDetails' => true,
|
||||
],
|
||||
|
||||
'tokenAuthenticationOptions' => [
|
||||
/**
|
||||
* Tokens are essentially passwords. You should treat them as such and you should always
|
||||
* use HTTPS. If the middleware detects insecure usage over HTTP it will return unauthorized
|
||||
* with a message Required HTTPS for token authentication. This rule is relaxed for requests
|
||||
* on localhost. To allow insecure usage you must enable it manually by setting secure to
|
||||
* false.
|
||||
* Default: true
|
||||
*/
|
||||
// 'secure' => true,
|
||||
|
||||
/**
|
||||
* Alternatively you can list your development host to have relaxed security.
|
||||
* Default: ['localhost', '127.0.0.1']
|
||||
*/
|
||||
// 'relaxed' => ['localhost', '127.0.0.1'],
|
||||
|
||||
/**
|
||||
* By default on occurred a fail on authentication, is sent a response on json format with a
|
||||
* message (`Invalid Token` or `Not found Token`) and with the token (if found), with status
|
||||
* `401 Unauthorized`. You can customize it by setting a callable function on error option.
|
||||
* Default: null
|
||||
*/
|
||||
// 'error' => null,
|
||||
],
|
||||
|
||||
'mockerOptions' => [
|
||||
// 'dataMocker' => $mocker,
|
||||
|
||||
// 'getMockStatusCodeCallback' => function (ServerRequestInterface $request, array $responses) {
|
||||
// // check if client clearly asks for mocked response
|
||||
// $pingHeader = 'X-OpenAPIServer-Mock';
|
||||
// $pingHeaderCode = 'X-OpenAPIServer-Mock-Code';
|
||||
// if (
|
||||
// $request->hasHeader($pingHeader)
|
||||
// && $request->getHeader($pingHeader)[0] === 'ping'
|
||||
// ) {
|
||||
// $responses = (array) $responses;
|
||||
// $requestedResponseCode = ($request->hasHeader($pingHeaderCode)) ? $request->getHeader($pingHeaderCode)[0] : 'default';
|
||||
// if (array_key_exists($requestedResponseCode, $responses)) {
|
||||
// return $requestedResponseCode;
|
||||
// }
|
||||
|
||||
// // return first response key
|
||||
// reset($responses);
|
||||
// return key($responses);
|
||||
// }
|
||||
|
||||
// return false;
|
||||
// },
|
||||
|
||||
// 'afterCallback' => function (ServerRequestInterface $request, ResponseInterface $response) {
|
||||
// // mark mocked response to distinguish real and fake responses
|
||||
// return $response->withHeader('X-OpenAPIServer-Mock', 'pong');
|
||||
// },
|
||||
],
|
||||
];
|
@ -19,10 +19,11 @@
|
||||
* NOTE: This class is auto generated by the openapi generator program.
|
||||
* https://github.com/openapitools/openapi-generator
|
||||
* Do not edit the class manually.
|
||||
* Extend this class with your controller. You can inject dependencies via class constructor,
|
||||
* @see https://github.com/PHP-DI/Slim-Bridge basic example.
|
||||
*/
|
||||
namespace OpenAPIServer\Api;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Slim\Exception\HttpNotImplementedException;
|
||||
@ -36,23 +37,6 @@ use Slim\Exception\HttpNotImplementedException;
|
||||
*/
|
||||
abstract class AbstractPetApi
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ContainerInterface|null Slim app container instance
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Route Controller constructor receives container
|
||||
*
|
||||
* @param ContainerInterface|null $container Slim app container instance
|
||||
*/
|
||||
public function __construct(ContainerInterface $container = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* POST addPet
|
||||
* Summary: Add a new pet to the store
|
||||
@ -60,13 +44,14 @@ abstract class AbstractPetApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
*/
|
||||
public function addPet(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
public function addPet(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response
|
||||
): ResponseInterface {
|
||||
$body = $request->getParsedBody();
|
||||
$message = "How about implementing addPet as a POST method in OpenAPIServer\Api\PetApi class?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
@ -78,16 +63,18 @@ abstract class AbstractPetApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
* @param int $petId Pet id to delete
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
*/
|
||||
public function deletePet(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
public function deletePet(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response,
|
||||
int $petId
|
||||
): ResponseInterface {
|
||||
$headers = $request->getHeaders();
|
||||
$apiKey = $request->hasHeader('api_key') ? $headers['api_key'] : null;
|
||||
$petId = $args['petId'];
|
||||
$message = "How about implementing deletePet as a DELETE method in OpenAPIServer\Api\PetApi class?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
}
|
||||
@ -100,13 +87,14 @@ abstract class AbstractPetApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
*/
|
||||
public function findPetsByStatus(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
public function findPetsByStatus(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response
|
||||
): ResponseInterface {
|
||||
$queryParams = $request->getQueryParams();
|
||||
$status = (key_exists('status', $queryParams)) ? $queryParams['status'] : null;
|
||||
$message = "How about implementing findPetsByStatus as a GET method in OpenAPIServer\Api\PetApi class?";
|
||||
@ -121,14 +109,15 @@ abstract class AbstractPetApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
* @deprecated
|
||||
*/
|
||||
public function findPetsByTags(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
public function findPetsByTags(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response
|
||||
): ResponseInterface {
|
||||
$queryParams = $request->getQueryParams();
|
||||
$tags = (key_exists('tags', $queryParams)) ? $queryParams['tags'] : null;
|
||||
$message = "How about implementing findPetsByTags as a GET method in OpenAPIServer\Api\PetApi class?";
|
||||
@ -143,14 +132,16 @@ abstract class AbstractPetApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
* @param int $petId ID of pet to return
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
*/
|
||||
public function getPetById(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
$petId = $args['petId'];
|
||||
public function getPetById(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response,
|
||||
int $petId
|
||||
): ResponseInterface {
|
||||
$message = "How about implementing getPetById as a GET method in OpenAPIServer\Api\PetApi class?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
}
|
||||
@ -162,13 +153,14 @@ abstract class AbstractPetApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
*/
|
||||
public function updatePet(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
public function updatePet(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response
|
||||
): ResponseInterface {
|
||||
$body = $request->getParsedBody();
|
||||
$message = "How about implementing updatePet as a PUT method in OpenAPIServer\Api\PetApi class?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
@ -180,14 +172,16 @@ abstract class AbstractPetApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
* @param int $petId ID of pet that needs to be updated
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
*/
|
||||
public function updatePetWithForm(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
$petId = $args['petId'];
|
||||
public function updatePetWithForm(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response,
|
||||
int $petId
|
||||
): ResponseInterface {
|
||||
$body = $request->getParsedBody();
|
||||
$name = (isset($body['name'])) ? $body['name'] : null;
|
||||
$status = (isset($body['status'])) ? $body['status'] : null;
|
||||
@ -202,14 +196,16 @@ abstract class AbstractPetApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
* @param int $petId ID of pet to update
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
*/
|
||||
public function uploadFile(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
$petId = $args['petId'];
|
||||
public function uploadFile(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response,
|
||||
int $petId
|
||||
): ResponseInterface {
|
||||
$body = $request->getParsedBody();
|
||||
$additionalMetadata = (isset($body['additionalMetadata'])) ? $body['additionalMetadata'] : null;
|
||||
$file = (key_exists('file', $request->getUploadedFiles())) ? $request->getUploadedFiles()['file'] : null;
|
||||
|
@ -19,10 +19,11 @@
|
||||
* NOTE: This class is auto generated by the openapi generator program.
|
||||
* https://github.com/openapitools/openapi-generator
|
||||
* Do not edit the class manually.
|
||||
* Extend this class with your controller. You can inject dependencies via class constructor,
|
||||
* @see https://github.com/PHP-DI/Slim-Bridge basic example.
|
||||
*/
|
||||
namespace OpenAPIServer\Api;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Slim\Exception\HttpNotImplementedException;
|
||||
@ -36,23 +37,6 @@ use Slim\Exception\HttpNotImplementedException;
|
||||
*/
|
||||
abstract class AbstractStoreApi
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ContainerInterface|null Slim app container instance
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Route Controller constructor receives container
|
||||
*
|
||||
* @param ContainerInterface|null $container Slim app container instance
|
||||
*/
|
||||
public function __construct(ContainerInterface $container = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* DELETE deleteOrder
|
||||
* Summary: Delete purchase order by ID
|
||||
@ -60,14 +44,16 @@ abstract class AbstractStoreApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
* @param string $orderId ID of the order that needs to be deleted
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
*/
|
||||
public function deleteOrder(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
$orderId = $args['orderId'];
|
||||
public function deleteOrder(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response,
|
||||
string $orderId
|
||||
): ResponseInterface {
|
||||
$message = "How about implementing deleteOrder as a DELETE method in OpenAPIServer\Api\StoreApi class?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
}
|
||||
@ -80,13 +66,14 @@ abstract class AbstractStoreApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
*/
|
||||
public function getInventory(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
public function getInventory(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response
|
||||
): ResponseInterface {
|
||||
$message = "How about implementing getInventory as a GET method in OpenAPIServer\Api\StoreApi class?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
}
|
||||
@ -99,14 +86,16 @@ abstract class AbstractStoreApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
* @param int $orderId ID of pet that needs to be fetched
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
*/
|
||||
public function getOrderById(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
$orderId = $args['orderId'];
|
||||
public function getOrderById(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response,
|
||||
int $orderId
|
||||
): ResponseInterface {
|
||||
$message = "How about implementing getOrderById as a GET method in OpenAPIServer\Api\StoreApi class?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
}
|
||||
@ -118,13 +107,14 @@ abstract class AbstractStoreApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
*/
|
||||
public function placeOrder(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
public function placeOrder(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response
|
||||
): ResponseInterface {
|
||||
$body = $request->getParsedBody();
|
||||
$message = "How about implementing placeOrder as a POST method in OpenAPIServer\Api\StoreApi class?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
|
@ -19,10 +19,11 @@
|
||||
* NOTE: This class is auto generated by the openapi generator program.
|
||||
* https://github.com/openapitools/openapi-generator
|
||||
* Do not edit the class manually.
|
||||
* Extend this class with your controller. You can inject dependencies via class constructor,
|
||||
* @see https://github.com/PHP-DI/Slim-Bridge basic example.
|
||||
*/
|
||||
namespace OpenAPIServer\Api;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use Slim\Exception\HttpNotImplementedException;
|
||||
@ -36,23 +37,6 @@ use Slim\Exception\HttpNotImplementedException;
|
||||
*/
|
||||
abstract class AbstractUserApi
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ContainerInterface|null Slim app container instance
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* Route Controller constructor receives container
|
||||
*
|
||||
* @param ContainerInterface|null $container Slim app container instance
|
||||
*/
|
||||
public function __construct(ContainerInterface $container = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* POST createUser
|
||||
* Summary: Create user
|
||||
@ -60,13 +44,14 @@ abstract class AbstractUserApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
*/
|
||||
public function createUser(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
public function createUser(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response
|
||||
): ResponseInterface {
|
||||
$body = $request->getParsedBody();
|
||||
$message = "How about implementing createUser as a POST method in OpenAPIServer\Api\UserApi class?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
@ -78,13 +63,14 @@ abstract class AbstractUserApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
*/
|
||||
public function createUsersWithArrayInput(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
public function createUsersWithArrayInput(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response
|
||||
): ResponseInterface {
|
||||
$body = $request->getParsedBody();
|
||||
$message = "How about implementing createUsersWithArrayInput as a POST method in OpenAPIServer\Api\UserApi class?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
@ -96,13 +82,14 @@ abstract class AbstractUserApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
*/
|
||||
public function createUsersWithListInput(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
public function createUsersWithListInput(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response
|
||||
): ResponseInterface {
|
||||
$body = $request->getParsedBody();
|
||||
$message = "How about implementing createUsersWithListInput as a POST method in OpenAPIServer\Api\UserApi class?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
@ -115,14 +102,16 @@ abstract class AbstractUserApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
* @param string $username The name that needs to be deleted
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
*/
|
||||
public function deleteUser(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
$username = $args['username'];
|
||||
public function deleteUser(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response,
|
||||
string $username
|
||||
): ResponseInterface {
|
||||
$message = "How about implementing deleteUser as a DELETE method in OpenAPIServer\Api\UserApi class?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
}
|
||||
@ -134,14 +123,16 @@ abstract class AbstractUserApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
* @param string $username The name that needs to be fetched. Use user1 for testing.
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
*/
|
||||
public function getUserByName(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
$username = $args['username'];
|
||||
public function getUserByName(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response,
|
||||
string $username
|
||||
): ResponseInterface {
|
||||
$message = "How about implementing getUserByName as a GET method in OpenAPIServer\Api\UserApi class?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
}
|
||||
@ -153,13 +144,14 @@ abstract class AbstractUserApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
*/
|
||||
public function loginUser(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
public function loginUser(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response
|
||||
): ResponseInterface {
|
||||
$queryParams = $request->getQueryParams();
|
||||
$username = (key_exists('username', $queryParams)) ? $queryParams['username'] : null;
|
||||
$password = (key_exists('password', $queryParams)) ? $queryParams['password'] : null;
|
||||
@ -173,13 +165,14 @@ abstract class AbstractUserApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
*/
|
||||
public function logoutUser(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
public function logoutUser(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response
|
||||
): ResponseInterface {
|
||||
$message = "How about implementing logoutUser as a GET method in OpenAPIServer\Api\UserApi class?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
}
|
||||
@ -191,14 +184,16 @@ abstract class AbstractUserApi
|
||||
*
|
||||
* @param ServerRequestInterface $request Request
|
||||
* @param ResponseInterface $response Response
|
||||
* @param array|null $args Path arguments
|
||||
* @param string $username name that need to be deleted
|
||||
*
|
||||
* @return ResponseInterface
|
||||
* @throws HttpNotImplementedException to force implementation class to override this method
|
||||
*/
|
||||
public function updateUser(ServerRequestInterface $request, ResponseInterface $response, array $args)
|
||||
{
|
||||
$username = $args['username'];
|
||||
public function updateUser(
|
||||
ServerRequestInterface $request,
|
||||
ResponseInterface $response,
|
||||
string $username
|
||||
): ResponseInterface {
|
||||
$body = $request->getParsedBody();
|
||||
$message = "How about implementing updateUser as a PUT method in OpenAPIServer\Api\UserApi class?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
|
@ -0,0 +1,71 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* PHP version 7.4
|
||||
*
|
||||
* @package OpenAPIServer
|
||||
* @author OpenAPI Generator team
|
||||
* @link https://github.com/openapitools/openapi-generator
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
* Generated by: https://github.com/openapitools/openapi-generator.git
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* NOTE: This class is auto generated by the openapi generator program.
|
||||
* https://github.com/openapitools/openapi-generator
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
namespace OpenAPIServer\App;
|
||||
|
||||
/**
|
||||
* RegisterDependencies
|
||||
*
|
||||
* Recommendations from template creator:
|
||||
*
|
||||
* I don't use imports(eg. use Slim\Middleware\ErrorMiddleware) here because each package unlikely
|
||||
* be used in code twice. It helps to keep that file short and make Git history cleaner.
|
||||
*
|
||||
* This class declared as final because two classes with dependency injections can cause confusion. Edit
|
||||
* template of this class or use your own implementation instead(overwrite index.php to import your
|
||||
* custom class).
|
||||
*/
|
||||
final class RegisterDependencies
|
||||
{
|
||||
/**
|
||||
* Adds dependency definitions.
|
||||
*
|
||||
* @param \DI\ContainerBuilder $containerBuilder Container builder.
|
||||
*
|
||||
* @see https://php-di.org/doc/php-definitions.html
|
||||
*/
|
||||
public function __invoke(\DI\ContainerBuilder $containerBuilder): void
|
||||
{
|
||||
$containerBuilder->addDefinitions([
|
||||
// Response factory required as typed argument in next ErrorMiddleware injection
|
||||
\Psr\Http\Message\ResponseFactoryInterface::class => \DI\factory([\Slim\Factory\AppFactory::class, 'determineResponseFactory']),
|
||||
|
||||
// Slim error middleware
|
||||
// @see https://www.slimframework.com/docs/v4/middleware/error-handling.html
|
||||
\Slim\Middleware\ErrorMiddleware::class => \DI\autowire()
|
||||
->constructorParameter('displayErrorDetails', \DI\get('slim.displayErrorDetails', false))
|
||||
->constructorParameter('logErrors', \DI\get('slim.logErrors', true))
|
||||
->constructorParameter('logErrorDetails', \DI\get('slim.logErrorDetails', true)),
|
||||
|
||||
// PDO class for database managing
|
||||
\PDO::class => \DI\create()
|
||||
->constructor(
|
||||
\DI\get('pdo.dsn'),
|
||||
\DI\get('pdo.username'),
|
||||
\DI\get('pdo.password'),
|
||||
\DI\get('pdo.options', null)
|
||||
),
|
||||
]);
|
||||
}
|
||||
}
|
@ -0,0 +1,64 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* OpenAPI Petstore
|
||||
* PHP version 7.4
|
||||
*
|
||||
* @package OpenAPIServer
|
||||
* @author OpenAPI Generator team
|
||||
* @link https://github.com/openapitools/openapi-generator
|
||||
*/
|
||||
|
||||
/**
|
||||
* This is a sample server Petstore server. For this sample, you can use the api key `special-key` to test the authorization filters.
|
||||
* The version of the OpenAPI document: 1.0.0
|
||||
* Generated by: https://github.com/openapitools/openapi-generator.git
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* NOTE: This class is auto generated by the openapi generator program.
|
||||
* https://github.com/openapitools/openapi-generator
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
namespace OpenAPIServer\App;
|
||||
|
||||
/**
|
||||
* RegisterMiddlewares
|
||||
*
|
||||
* Recommendations from template creator:
|
||||
*
|
||||
* There is no way to add route related middlewares here, add global ones. Route related middlewares
|
||||
* can be applied in \OpenAPIServer\App\RegisterRoutes class.
|
||||
*
|
||||
* I add middlewares by full class names(\Slim\Middleware\ErrorMiddleware::class) because that way
|
||||
* Slim initiates them with options from Container. They already configured, don't need to pass any
|
||||
* options manually.
|
||||
*
|
||||
* I don't use imports(eg. use Slim\Middleware\ErrorMiddleware) here because each package unlikely
|
||||
* be used in code twice. It helps to keep that file short and make Git history cleaner.
|
||||
*
|
||||
* This class declared as final because two classes with middlewares can cause confusion. Edit
|
||||
* template of this class or use your own implementation instead(overwrite index.php to import your
|
||||
* custom class).
|
||||
*/
|
||||
final class RegisterMiddlewares
|
||||
{
|
||||
/**
|
||||
* Adds middlewares to Slim app instance.
|
||||
*
|
||||
* @param \Slim\App $app App instance.
|
||||
*/
|
||||
public function __invoke(\Slim\App $app): void
|
||||
{
|
||||
// Parse json, form data and xml
|
||||
$app->addBodyParsingMiddleware();
|
||||
|
||||
// Add Routing Middleware
|
||||
$app->addRoutingMiddleware();
|
||||
|
||||
// Add Error Middleware
|
||||
$app->add(\Slim\Middleware\ErrorMiddleware::class);
|
||||
}
|
||||
}
|
@ -15,39 +15,26 @@
|
||||
* Generated by: https://github.com/openapitools/openapi-generator.git
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
/**
|
||||
* NOTE: This class is auto generated by the openapi generator program.
|
||||
* https://github.com/openapitools/openapi-generator
|
||||
* Do not edit the class manually.
|
||||
*/
|
||||
namespace OpenAPIServer;
|
||||
namespace OpenAPIServer\App;
|
||||
|
||||
use Slim\Factory\AppFactory;
|
||||
use Slim\Interfaces\RouteInterface;
|
||||
use Slim\Exception\HttpNotImplementedException;
|
||||
use Psr\Container\ContainerInterface;
|
||||
use InvalidArgumentException;
|
||||
use Dyorg\TokenAuthentication;
|
||||
use Dyorg\TokenAuthentication\TokenSearch;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use OpenAPIServer\Mock\OpenApiDataMocker;
|
||||
use OpenAPIServer\Mock\OpenApiDataMockerRouteMiddleware;
|
||||
use Slim\Psr7\Factory\ResponseFactory;
|
||||
use Exception;
|
||||
|
||||
/**
|
||||
* SlimRouter Class Doc Comment
|
||||
* RegisterRoutes Class Doc Comment
|
||||
*
|
||||
* @package OpenAPIServer
|
||||
* @author OpenAPI Generator team
|
||||
* @link https://github.com/openapitools/openapi-generator
|
||||
*/
|
||||
class SlimRouter
|
||||
class RegisterRoutes
|
||||
{
|
||||
|
||||
/** @var App instance */
|
||||
private $slimApp;
|
||||
|
||||
/** @var array[] list of all api operations */
|
||||
private $operations = [
|
||||
[
|
||||
@ -843,191 +830,36 @@ class SlimRouter
|
||||
];
|
||||
|
||||
/**
|
||||
* Class constructor
|
||||
* Add routes to Slim app.
|
||||
*
|
||||
* @param ContainerInterface|array $settings Either a ContainerInterface or an associative array of app settings
|
||||
* @param \Slim\App $app Pre-configured Slim application instance
|
||||
*
|
||||
* @throws HttpNotImplementedException When implementation class doesn't exists
|
||||
* @throws Exception when not supported authorization schema type provided
|
||||
*/
|
||||
public function __construct($settings = [])
|
||||
public function __invoke(\Slim\App $app): void
|
||||
{
|
||||
if ($settings instanceof ContainerInterface) {
|
||||
// Set container to create App with on AppFactory
|
||||
AppFactory::setContainer($settings);
|
||||
}
|
||||
$this->slimApp = AppFactory::create();
|
||||
|
||||
// middlewares requires Psr\Container\ContainerInterface
|
||||
$container = $this->slimApp->getContainer();
|
||||
|
||||
$authPackage = 'OpenAPIServer\Auth';
|
||||
$basicAuthenticator = function (ServerRequestInterface &$request, TokenSearch $tokenSearch) use ($authPackage) {
|
||||
$message = "How about extending AbstractAuthenticator class by {$authPackage}\BasicAuthenticator?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
};
|
||||
$apiKeyAuthenticator = function (ServerRequestInterface &$request, TokenSearch $tokenSearch) use ($authPackage) {
|
||||
$message = "How about extending AbstractAuthenticator class by {$authPackage}\ApiKeyAuthenticator?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
};
|
||||
$oAuthAuthenticator = function (ServerRequestInterface &$request, TokenSearch $tokenSearch) use ($authPackage) {
|
||||
$message = "How about extending AbstractAuthenticator class by {$authPackage}\OAuthAuthenticator?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
};
|
||||
|
||||
$userOptions = $this->getSetting($settings, 'tokenAuthenticationOptions', null);
|
||||
|
||||
// mocker options
|
||||
$mockerOptions = $this->getSetting($settings, 'mockerOptions', null);
|
||||
$dataMocker = $mockerOptions['dataMocker'] ?? new OpenApiDataMocker();
|
||||
$responseFactory = new ResponseFactory();
|
||||
$getMockStatusCodeCallback = $mockerOptions['getMockStatusCodeCallback'] ?? null;
|
||||
$mockAfterCallback = $mockerOptions['afterCallback'] ?? null;
|
||||
|
||||
foreach ($this->operations as $operation) {
|
||||
$callback = function ($request, $response, $arguments) use ($operation) {
|
||||
$callback = function ($request) use ($operation) {
|
||||
$message = "How about extending {$operation['classname']} by {$operation['apiPackage']}\\{$operation['userClassname']} class implementing {$operation['operationId']} as a {$operation['httpMethod']} method?";
|
||||
throw new HttpNotImplementedException($request, $message);
|
||||
};
|
||||
$middlewares = [];
|
||||
|
||||
if (class_exists("\\{$operation['apiPackage']}\\{$operation['userClassname']}")) {
|
||||
$callback = "\\{$operation['apiPackage']}\\{$operation['userClassname']}:{$operation['operationId']}";
|
||||
// Notice how we register the controller using the class name?
|
||||
// PHP-DI will instantiate the class for us only when it's actually necessary
|
||||
$callback = ["\\{$operation['apiPackage']}\\{$operation['userClassname']}", $operation['operationId']];
|
||||
}
|
||||
|
||||
foreach ($operation['authMethods'] as $authMethod) {
|
||||
switch ($authMethod['type']) {
|
||||
case 'http':
|
||||
$authenticatorClassname = "\\{$authPackage}\\BasicAuthenticator";
|
||||
if (class_exists($authenticatorClassname)) {
|
||||
$basicAuthenticator = new $authenticatorClassname($container);
|
||||
}
|
||||
|
||||
$middlewares[] = new TokenAuthentication($this->getTokenAuthenticationOptions([
|
||||
'authenticator' => $basicAuthenticator,
|
||||
'regex' => $authMethod['isBearer'] ? '/Bearer\s+(.*)$/i' : '/Basic\s+(.*)$/i',
|
||||
'header' => 'Authorization',
|
||||
'parameter' => null,
|
||||
'cookie' => null,
|
||||
'argument' => null,
|
||||
], $userOptions));
|
||||
break;
|
||||
case 'apiKey':
|
||||
$authenticatorClassname = "\\{$authPackage}\\ApiKeyAuthenticator";
|
||||
if (class_exists($authenticatorClassname)) {
|
||||
$apiKeyAuthenticator = new $authenticatorClassname($container);
|
||||
}
|
||||
|
||||
$middlewares[] = new TokenAuthentication($this->getTokenAuthenticationOptions([
|
||||
'authenticator' => $apiKeyAuthenticator,
|
||||
'regex' => '/^(.*)$/i',
|
||||
'header' => $authMethod['isKeyInHeader'] ? $authMethod['keyParamName'] : null,
|
||||
'parameter' => $authMethod['isKeyInQuery'] ? $authMethod['keyParamName'] : null,
|
||||
'cookie' => $authMethod['isKeyInCookie'] ? $authMethod['keyParamName'] : null,
|
||||
'argument' => null,
|
||||
], $userOptions));
|
||||
break;
|
||||
case 'oauth2':
|
||||
$authenticatorClassname = "\\{$authPackage}\\OAuthAuthenticator";
|
||||
if (class_exists($authenticatorClassname)) {
|
||||
$oAuthAuthenticator = new $authenticatorClassname($container, $authMethod['scopes']);
|
||||
}
|
||||
|
||||
$middlewares[] = new TokenAuthentication($this->getTokenAuthenticationOptions([
|
||||
'authenticator' => $oAuthAuthenticator,
|
||||
'regex' => '/Bearer\s+(.*)$/i',
|
||||
'header' => 'Authorization',
|
||||
'parameter' => null,
|
||||
'cookie' => null,
|
||||
'argument' => null,
|
||||
], $userOptions));
|
||||
break;
|
||||
default:
|
||||
throw new Exception('Unknown authorization schema type');
|
||||
}
|
||||
}
|
||||
|
||||
if (is_callable($getMockStatusCodeCallback)) {
|
||||
$mockSchemaResponses = array_map(function ($item) {
|
||||
return json_decode($item['jsonSchema'], true);
|
||||
}, $operation['responses']);
|
||||
$middlewares[] = new OpenApiDataMockerRouteMiddleware($dataMocker, $mockSchemaResponses, $responseFactory, $getMockStatusCodeCallback, $mockAfterCallback);
|
||||
}
|
||||
|
||||
$this->addRoute(
|
||||
$route = $app->map(
|
||||
[$operation['httpMethod']],
|
||||
"{$operation['basePathWithoutHost']}{$operation['path']}",
|
||||
$callback,
|
||||
$middlewares
|
||||
$callback
|
||||
)->setName($operation['operationId']);
|
||||
|
||||
foreach ($middlewares as $middleware) {
|
||||
$route->add($middleware);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Merges user defined options with dynamic params
|
||||
*
|
||||
* @param array $staticOptions Required static options
|
||||
* @param array $userOptions User options
|
||||
*
|
||||
* @return array Merged array
|
||||
*/
|
||||
private function getTokenAuthenticationOptions(array $staticOptions, array $userOptions = null)
|
||||
{
|
||||
if (is_array($userOptions) === false) {
|
||||
return $staticOptions;
|
||||
}
|
||||
|
||||
return array_merge($userOptions, $staticOptions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns app setting by name.
|
||||
*
|
||||
* @param ContainerInterface|array $settings Either a ContainerInterface or an associative array of app settings
|
||||
* @param string $settingName Setting name
|
||||
* @param mixed $default Default setting value.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
private function getSetting($settings, $settingName, $default = null)
|
||||
{
|
||||
if ($settings instanceof ContainerInterface && $settings->has($settingName)) {
|
||||
return $settings->get($settingName);
|
||||
} elseif (is_array($settings) && array_key_exists($settingName, $settings)) {
|
||||
return $settings[$settingName];
|
||||
}
|
||||
|
||||
return $default;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add route with multiple methods
|
||||
*
|
||||
* @param string[] $methods Numeric array of HTTP method names
|
||||
* @param string $pattern The route URI pattern
|
||||
* @param callable|string $callable The route callback routine
|
||||
* @param array|null $middlewares List of middlewares
|
||||
*
|
||||
* @return RouteInterface
|
||||
*
|
||||
* @throws InvalidArgumentException If the route pattern isn't a string
|
||||
*/
|
||||
public function addRoute(array $methods, string $pattern, $callable, $middlewares = [])
|
||||
{
|
||||
$route = $this->slimApp->map($methods, $pattern, $callable);
|
||||
foreach ($middlewares as $middleware) {
|
||||
$route->add($middleware);
|
||||
}
|
||||
return $route;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns Slim Framework instance
|
||||
*
|
||||
* @return App
|
||||
*/
|
||||
public function getSlimApp()
|
||||
{
|
||||
return $this->slimApp;
|
||||
}
|
||||
}
|
@ -22,7 +22,6 @@
|
||||
*/
|
||||
namespace OpenAPIServer\Auth;
|
||||
|
||||
use Psr\Container\ContainerInterface;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Dyorg\TokenAuthentication;
|
||||
use Dyorg\TokenAuthentication\TokenSearch;
|
||||
@ -37,12 +36,6 @@ use Dyorg\TokenAuthentication\Exceptions\UnauthorizedExceptionInterface;
|
||||
*/
|
||||
abstract class AbstractAuthenticator
|
||||
{
|
||||
|
||||
/**
|
||||
* @var ContainerInterface|null Slim app container instance
|
||||
*/
|
||||
protected $container;
|
||||
|
||||
/**
|
||||
* @var string[]|null List of required scopes
|
||||
*/
|
||||
@ -62,12 +55,10 @@ abstract class AbstractAuthenticator
|
||||
/**
|
||||
* Authenticator constructor
|
||||
*
|
||||
* @param ContainerInterface|null $container Slim app container instance
|
||||
* @param string[]|null $requiredScope List of required scopes
|
||||
* @param string[]|null $requiredScope List of required scopes
|
||||
*/
|
||||
public function __construct(ContainerInterface $container = null, $requiredScope = null)
|
||||
public function __construct($requiredScope = null)
|
||||
{
|
||||
$this->container = $container;
|
||||
$this->requiredScope = $requiredScope;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,7 @@
|
||||
<IfModule mod_env.c>
|
||||
SetEnv APP_ENV 'production'
|
||||
</IfModule>
|
||||
|
||||
<IfModule mod_rewrite.c>
|
||||
RewriteEngine On
|
||||
RewriteCond %{REQUEST_FILENAME} !-f
|
||||
|
@ -22,48 +22,63 @@
|
||||
|
||||
require_once __DIR__ . '/../vendor/autoload.php';
|
||||
|
||||
use OpenAPIServer\SlimRouter;
|
||||
use Psr\Http\Message\ServerRequestInterface;
|
||||
use Psr\Http\Message\ResponseInterface;
|
||||
use OpenAPIServer\Mock\OpenApiDataMocker;
|
||||
use DI\Bridge\Slim\Bridge;
|
||||
use DI\ContainerBuilder;
|
||||
use OpenAPIServer\App\RegisterDependencies;
|
||||
use OpenAPIServer\App\RegisterRoutes;
|
||||
use OpenAPIServer\App\RegisterMiddlewares;
|
||||
use Slim\Factory\ServerRequestCreatorFactory;
|
||||
use Slim\ResponseEmitter;
|
||||
|
||||
// load config file
|
||||
$config = [];
|
||||
if (is_array($prodConfig = @include(__DIR__ . '/../config/prod/config.inc.php'))) {
|
||||
$config = $prodConfig;
|
||||
} elseif (is_array($devConfig = @include(__DIR__ . '/../config/dev/config.inc.php'))) {
|
||||
$config = $devConfig;
|
||||
} else {
|
||||
throw new InvalidArgumentException('Config file missed or broken.');
|
||||
// Instantiate PHP-DI ContainerBuilder
|
||||
$builder = new ContainerBuilder();
|
||||
|
||||
// consider prod by default
|
||||
$env;
|
||||
switch (strtolower($_SERVER['APP_ENV'] ?? 'prod')) {
|
||||
case 'development':
|
||||
case 'dev':
|
||||
$env = 'dev';
|
||||
break;
|
||||
case 'production':
|
||||
case 'prod':
|
||||
default:
|
||||
$env = 'prod';
|
||||
}
|
||||
|
||||
$router = new SlimRouter($config);
|
||||
$app = $router->getSlimApp();
|
||||
// Main configuration
|
||||
$builder->addDefinitions(__DIR__ . "/../config/{$env}/default.inc.php");
|
||||
|
||||
// Parse json, form data and xml
|
||||
$app->addBodyParsingMiddleware();
|
||||
// Config file for the environment if exists
|
||||
$userConfig = __DIR__ . "/../config/{$env}/config.inc.php";
|
||||
if (file_exists($userConfig)) {
|
||||
$builder->addDefinitions($userConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* The routing middleware should be added before the ErrorMiddleware
|
||||
* Otherwise exceptions thrown from it will not be handled
|
||||
*/
|
||||
$app->addRoutingMiddleware();
|
||||
// Set up dependencies
|
||||
$dependencies = new RegisterDependencies();
|
||||
$dependencies($builder);
|
||||
|
||||
/**
|
||||
* Add Error Handling Middleware
|
||||
*
|
||||
* @param bool $displayErrorDetails -> Should be set to false in production
|
||||
* @param bool $logErrors -> Parameter is passed to the default ErrorHandler
|
||||
* @param bool $logErrorDetails -> Display error details in error log
|
||||
* which can be replaced by a callable of your choice.
|
||||
// Build PHP-DI Container instance
|
||||
$container = $builder->build();
|
||||
|
||||
* Note: This middleware should be added last. It will not handle any exceptions/errors
|
||||
* for middleware added after it.
|
||||
*/
|
||||
$app->addErrorMiddleware(
|
||||
$config['slimSettings']['displayErrorDetails'] ?? false,
|
||||
$config['slimSettings']['logErrors'] ?? true,
|
||||
$config['slimSettings']['logErrorDetails'] ?? true
|
||||
);
|
||||
// Instantiate the app
|
||||
$app = Bridge::create($container);
|
||||
|
||||
$app->run();
|
||||
// Register middleware
|
||||
$middleware = new RegisterMiddlewares();
|
||||
$middleware($app);
|
||||
|
||||
// Register routes
|
||||
// yes, it's anti-pattern you shouldn't get deps from container directly
|
||||
$routes = $container->get(RegisterRoutes::class);
|
||||
$routes($app);
|
||||
|
||||
// Create Request object from globals
|
||||
$serverRequestCreator = ServerRequestCreatorFactory::create();
|
||||
$request = $serverRequestCreator->createServerRequestFromGlobals();
|
||||
|
||||
// Run App & Emit Response
|
||||
$response = $app->handle($request);
|
||||
$responseEmitter = new ResponseEmitter();
|
||||
$responseEmitter->emit($response);
|
||||
|
Loading…
x
Reference in New Issue
Block a user