Skip to content

Commit

Permalink
Finalize NeonLoader, allow use both loaders simultaneously
Browse files Browse the repository at this point in the history
  • Loading branch information
mabar authored and Milan Felix Šulc committed Feb 10, 2019
1 parent 59a826f commit c38bbdd
Show file tree
Hide file tree
Showing 2 changed files with 128 additions and 45 deletions.
126 changes: 97 additions & 29 deletions src/DI/Loader/NeonLoader.php
Expand Up @@ -4,14 +4,15 @@

use Apitte\Core\Schema\Builder\Controller\Controller;
use Apitte\Core\Schema\Builder\Controller\Method;
use Apitte\Core\Schema\Builder\Controller\MethodRequest;
use Apitte\Core\Schema\Builder\SchemaBuilder;
use Apitte\Core\Schema\EndpointParameter;

class NeonLoader implements ILoader
{

/** @var mixed[] */
private $schema = [];
private $schema;

/**
* @param mixed[] $schema
Expand All @@ -24,52 +25,119 @@ public function __construct(array $schema)
public function load(SchemaBuilder $builder): SchemaBuilder
{
foreach ($this->schema as $class => $settings) {
$schemaController = $builder->addController($class);
$schemaController->setId($settings['id'] ?? null);
$schemaController->setPath($settings['path']);
$this->addControllerMethods($schemaController, $settings);
$schemaController->addTags($settings['tags'] ?? []);
$schemaController->setGroupIds($settings['groupIds'] ?? []);
$schemaController->setGroupPaths($settings['groupPaths'] ?? []);
$controller = $builder->addController($class);
$controller->setId($settings['id'] ?? null);
$controller->setPath($settings['path'] ?? '');
$controller->setGroupIds($settings['groupIds'] ?? []);
$controller->setGroupPaths($settings['groupPaths'] ?? []);
$controller->addTags($settings['tags'] ?? []);
$controller->setOpenApi($settings['openapi'] ?? []);
$this->addControllerMethods($controller, $settings['methods'] ?? []);
}
return $builder;
}

/**
* @param mixed[] $settings
* @param mixed[] $methodsSettings
*/
private function addControllerMethods(Controller $schemaController, array $settings): void
private function addControllerMethods(Controller $controller, array $methodsSettings): void
{
if (!isset($settings['methods'])) {
foreach ($methodsSettings as $name => $settings) {
$method = $controller->addMethod($name);
$method->setId($settings['id'] ?? null);
$method->setPath($settings['path'] ?? '');
$method->setDescription($settings['description'] ?? '');
$method->addMethods($settings['methods'] ?? []);
$method->addTags($settings['tags'] ?? []);
$method->setOpenApi($settings['openapi'] ?? []);
$this->setMethodParameters($method, $settings['parameters'] ?? []);
$this->setNegotiations($method, $settings['negotiations'] ?? []);
$this->setRequest($method, $settings['request'] ?? null);
$this->setRequestMapper($method, $settings['requestMapper'] ?? null);
$this->setResponses($method, $settings['responses'] ?? null);
$this->setResponseMapper($method, $settings['responseMapper'] ?? null);
}
}

/**
* @param mixed[] $parametersSettings
*/
private function setMethodParameters(Method $method, array $parametersSettings): void
{
foreach ($parametersSettings as $name => $settings) {
$parameter = $method->addParameter($name, $settings['type'] ?? EndpointParameter::TYPE_STRING);
$parameter->setIn($settings['in'] ?? EndpointParameter::IN_PATH);
$parameter->setDescription($settings['description'] ?? null);
$parameter->setRequired($settings['required'] ?? true);
$parameter->setAllowEmpty($settings['allowEmpty'] ?? false);
$parameter->setDeprecated($settings['deprecated'] ?? false);
}
}

/**
* @param mixed[] $negotiationsSettings
*/
private function setNegotiations(Method $method, array $negotiationsSettings): void
{
foreach ($negotiationsSettings as $suffix => $settings) {
$negotiation = $method->addNegotiation($suffix);
$negotiation->setDefault($settings['default'] ?? false);
$negotiation->setRenderer($settings['renderer'] ?? null);
}
}

/**
* @param mixed[]|null $requestSettings
*/
private function setRequest(Method $method, ?array $requestSettings): void
{
if ($requestSettings === null) {
return;
}
foreach ($settings['methods'] as $methodName => $methodSettings) {
$method = $schemaController->addMethod($methodName);
$method->setId($methodSettings['id'] ?? null);
$method->addMethods($methodSettings['methods'] ?? []);
$method->setPath($methodSettings['path']);
$method->setDescription($methodSettings['description'] ?? '');
$method->addTags($methodSettings['tags'] ?? []);
$this->setMethodParameters($method, $methodSettings);

$request = new MethodRequest();

$request->setRequired($requestSettings['required'] ?? false);
$request->setDescription($requestSettings['description'] ?? null);
$request->setEntity($requestSettings['entity'] ?? null);

$method->setRequest($request);
}

/**
* @param mixed[]|null $requestMapperSettings
*/
private function setRequestMapper(Method $method, ?array $requestMapperSettings): void
{
if ($requestMapperSettings === null) {
return;
}
$method->setRequestMapper($requestMapperSettings['entity'], $requestMapperSettings['validation'] ?? true);
}

/**
* @param mixed[] $methodSettings
* @param mixed[]|null $responses
*/
private function setMethodParameters(Method $method, array $methodSettings): void
private function setResponses(Method $method, ?array $responses): void
{
if (!isset($methodSettings['parameters'])) {
if ($responses === null) {
return;
}
foreach ($methodSettings['parameters'] as $parameterName => $parameterSettings) {
$parameter = $method->addParameter($parameterName, $parameterSettings['type'] ?? EndpointParameter::TYPE_STRING);
$parameter->setIn($parameterSettings['in'] ?? EndpointParameter::IN_PATH);
$parameter->setDescription($parameterSettings['description'] ?? null);
$parameter->setRequired(isset($parameterSettings['required']) ? (bool) $parameterSettings['required'] : true);
$parameter->setAllowEmpty(isset($parameterSettings['allowEmpty']) ? (bool) $parameterSettings['allowEmpty'] : false);
$parameter->setDeprecated(isset($parameterSettings['deprecated']) ? (bool) $parameterSettings['deprecated'] : false);

foreach ($responses as $response) {
$method->addResponse($response['code'], $response['description'] ?? '');
}
}

/**
* @param mixed[]|null $responseMapperSettings
*/
private function setResponseMapper(Method $method, ?array $responseMapperSettings): void
{
if ($responseMapperSettings === null) {
return;
}
$method->setResponseMapper($responseMapperSettings['entity']);
}

}
47 changes: 31 additions & 16 deletions src/DI/Plugin/CoreSchemaPlugin.php
Expand Up @@ -4,7 +4,6 @@

use Apitte\Core\DI\Loader\DoctrineAnnotationLoader;
use Apitte\Core\DI\Loader\NeonLoader;
use Apitte\Core\Exception\Logical\InvalidStateException;
use Apitte\Core\Schema\Builder\SchemaBuilder;
use Apitte\Core\Schema\Serialization\ArrayHydrator;
use Apitte\Core\Schema\Serialization\ArraySerializator;
Expand All @@ -19,22 +18,29 @@
use Apitte\Core\Schema\Validation\RequestParameterValidation;
use Apitte\Core\Schema\Validation\ResponseMapperValidation;
use Apitte\Core\Schema\Validator\SchemaBuilderValidator;
use Nette\DI\Config\Adapters\NeonAdapter;
use Nette\Utils\Arrays;

class CoreSchemaPlugin extends AbstractPlugin
{

public const PLUGIN_NAME = 'schema';

// Loader types
public const LOADERS = ['annotations', 'neon', 'php'];

/** @var IDecorator[] */
public static $decorators = [];

/** @var mixed[] */
protected $defaults = [
'loader' => 'annotations',
'schema' => [],
'loaders' => [
'annotations' => [
'enable' => true,
],
'neon' => [
'enable' => false,
'files' => [],
],
],
'schema' => [],
'validations' => [
'controllerPath' => ControllerPathValidation::class,
'fullPath' => FullpathValidation::class,
Expand Down Expand Up @@ -95,23 +101,32 @@ protected function compileSchema(): array

protected function loadSchema(SchemaBuilder $builder): SchemaBuilder
{
// Load schema from...
if ($this->config['loader'] === 'annotations') {
$loaders = $this->config['loaders'];

//TODO - resolve limitation - Controller defined by one of loaders cannot be modified by other loaders

if ($loaders['annotations']['enable'] === true) {
$loader = new DoctrineAnnotationLoader($this->getContainerBuilder());

return $loader->load($builder);
$builder = $loader->load($builder);
}

if ($this->config['loader'] === 'neon') {
$loader = new NeonLoader($this->config['schema']);
return $loader->load($builder);
}
if ($loaders['neon']['enable'] === true) {
// Expand path to files
$files = $this->compiler->getExtension()->validateConfig($loaders['neon']['files']);

// Load schema from files
$adapter = new NeonAdapter();
$schema = [];
foreach ($files as $file) {
$schema = Arrays::mergeTree($schema, $adapter->load($file));
}

if ($this->config['loader'] === 'php') {
throw new InvalidStateException('Not implemented');
$loader = new NeonLoader($schema);
$builder = $loader->load($builder);
}

throw new InvalidStateException('Unknown loader type');
return $builder;
}

protected function validateSchema(SchemaBuilder $builder): SchemaBuilder
Expand Down

0 comments on commit c38bbdd

Please sign in to comment.