first impl for api

This commit is contained in:
2021-05-05 20:33:34 +02:00
parent 19fdf2a503
commit f02e33fda7
16 changed files with 849 additions and 87 deletions

View File

@@ -133,7 +133,7 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
$loader->load('services/search.yaml');
$loader->load('services/serializer.yaml');
$this->configureCruds($container, $config['cruds'], $loader);
$this->configureCruds($container, $config['cruds'], $config['apis'], $loader);
}
/**
@@ -214,47 +214,91 @@ class ChillMainExtension extends Extension implements PrependExtensionInterface,
* @param array $config the config under 'cruds' key
* @return null
*/
protected function configureCruds(ContainerBuilder $container, $config, Loader\YamlFileLoader $loader)
protected function configureCruds(ContainerBuilder $container, $crudConfig, $apiConfig, Loader\YamlFileLoader $loader)
{
if (count($config) === 0) {
if ((count($crudConfig) + count($apiConfig)) === 0) {
return;
}
// dump(array_keys($container->getDefinitions()));
$loader->load('services/crud.yaml');
$container->setParameter('chill_main_crud_route_loader_config', $config);
$container->setParameter('chill_main_crud_route_loader_config', $crudConfig);
$container->setParameter('chill_main_api_route_loader_config', $apiConfig);
return;
/*
$definition = new Definition();
$definition
->setClass(\Chill\MainBundle\CRUD\Routing\CRUDRoutesLoader::class)
->addArgument('%chill_main_crud_route_loader_config%')
->addArgument('%chill_main_api_route_loader_config%')
;
$container->setDefinition('chill_main_crud_route_loader', $definition);
*/
$alreadyExistingNames = [];
foreach ($config as $crudEntry) {
$controller = $crudEntry['controller'];
$controllerServiceName = 'cscrud_'.$crudEntry['name'].'_controller';
$name = $crudEntry['name'];
foreach ($crudConfig as $crudEntry) {
$this->configureCrudController($container, $crudEntry, 'crud');
}
// check for existing crud names
if (\in_array($name, $alreadyExistingNames)) {
throw new LogicException(sprintf("the name %s is defined twice in CRUD", $name));
}
if (!$container->has($controllerServiceName)) {
$controllerDefinition = new Definition($controller);
$controllerDefinition->addTag('controller.service_arguments');
$controllerDefinition->setAutoconfigured(true);
$controllerDefinition->setClass($crudEntry['controller']);
$container->setDefinition($controllerServiceName, $controllerDefinition);
}
$container->setParameter('chill_main_crud_config_'.$name, $crudEntry);
$container->getDefinition($controllerServiceName)
->addMethodCall('setCrudConfig', ['%chill_main_crud_config_'.$name.'%']);
foreach ($apiConfig as $crudEntry) {
$this->configureCrudController($container, $crudEntry, 'crud');
}
}
/**
* Add a controller for each definition, and add a methodCall to inject crud configuration to controller
*/
private function configureCrudController(ContainerBuilder $container, array $crudEntry, string $apiOrCrud): void
{
$controller = $crudEntry['controller'];
$controllerServiceName = 'cscrud_'.$crudEntry['name'].'_controller';
$name = $crudEntry['name'];
// check for existing crud names
/*if (\in_array($name, $alreadyExistingNames)) {
throw new LogicException(sprintf("the name %s is defined twice in CRUD", $name));
}*/
if (!$container->has($controllerServiceName)) {
$controllerDefinition = new Definition($controller);
$controllerDefinition->addTag('controller.service_arguments');
$controllerDefinition->setAutoconfigured(true);
$controllerDefinition->setClass($crudEntry['controller']);
$container->setDefinition($controllerServiceName, $controllerDefinition);
}
$container->setParameter('chill_main_'.$apiOrCrud.'_config_'.$name, $crudEntry);
$container->getDefinition($controllerServiceName)
->addMethodCall('setCrudConfig', ['%chill_main_'.$apiOrCrud.'_config_'.$name.'%']);
/*
dump($controllerClass);
if ($container->hasDefinition($controllerClass)) {
dump('container has controller class');
$controllerServiceName = $controllerClass;
$controller = $container->getDefinition($controllerServiceName);
$param = 'chill_main_'.$apiOrCrud.'_config_'.$crudEntry['name'];
$container->setParameter($param, $crudEntry);
$controller->addMethodCall('setCrudConfig', ['%'.$param.'%']);
dump(__LINE__, $controller);
$controller->setDefinition($controllerServiceName, $controller);
} else {
$controllerServiceName = 'cs'.$apiOrCrud.'_'.$crudEntry['name'].'_controller';
$controller = new Definition($controllerClass);
$controller->addTag('controller.service_arguments');
$controller->setAutoconfigured(true);
$controller->setClass($controllerClass);
$param = 'chill_main_'.$apiOrCrud.'_config_'.$crudEntry['name'];
$container->setParameter($param, $crudEntry);
$controller->addMethodCall('setCrudConfig', ['%'.$param.'%']);
dump(__LINE__, $controller);
$container->setDefinition($controllerServiceName, $controller);
}*/
}
}

View File

@@ -0,0 +1,103 @@
<?php
/*
* Copyright (C) 2018 Champs Libres Cooperative <info@champs-libres.coop>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
namespace Chill\MainBundle\DependencyInjection\CompilerPass;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\DependencyInjection\Compiler\CompilerPassInterface;
use Symfony\Component\DependencyInjection\Reference;
use Chill\MainBundle\Routing\MenuComposer;
use Symfony\Component\DependencyInjection\Definition;
/**
*
*
*/
class CRUDControllerCompilerPass implements CompilerPassInterface
{
public function process(ContainerBuilder $container)
{
$crudConfig = $container->getParameter('chill_main_crud_route_loader_config');
$apiConfig = $container->getParameter('chill_main_api_route_loader_config');
foreach ($crudConfig as $crudEntry) {
$this->configureCrudController($container, $crudEntry, 'crud');
}
foreach ($apiConfig as $crudEntry) {
$this->configureCrudController($container, $crudEntry, 'crud');
}
}
/**
* Add a controller for each definition, and add a methodCall to inject crud configuration to controller
*/
private function configureCrudController(ContainerBuilder $container, array $crudEntry, string $apiOrCrud): void
{
$controller = $crudEntry['controller'];
$controllerServiceName = 'cscrud_'.$crudEntry['name'].'_controller';
$name = $crudEntry['name'];
// check for existing crud names
/*if (\in_array($name, $alreadyExistingNames)) {
throw new LogicException(sprintf("the name %s is defined twice in CRUD", $name));
}
if (!$container->has($controllerServiceName)) {
$controllerDefinition = new Definition($controller);
$controllerDefinition->addTag('controller.service_arguments');
$controllerDefinition->setAutoconfigured(true);
$controllerDefinition->setClass($crudEntry['controller']);
$container->setDefinition($controllerServiceName, $controllerDefinition);
}
$container->setParameter('chill_main_'.$apiOrCrud.'_config_'.$name, $crudEntry);
$container->getDefinition($controllerServiceName)
->addMethodCall('setCrudConfig', ['%chill_main_'.$apiOrCrud.'_config_'.$name.'%']);
/*
dump($controllerClass);
*/
$controllerClass = $crudEntry['controller'];
dump('in_array', $controllerClass, \in_array($controllerClass, \array_keys($container->getDefinitions())));
if ($container->hasDefinition($controllerClass)) {
dump('container has controller class');
$controllerServiceName = $controllerClass;
$controller = $container->getDefinition($controllerServiceName);
$param = 'chill_main_'.$apiOrCrud.'_config_'.$crudEntry['name'];
$container->setParameter($param, $crudEntry);
$controller->addMethodCall('setCrudConfig', ['%'.$param.'%']);
dump(__LINE__, $controller);
$controller->setDefinition($controllerServiceName, $controller);
} else {
$controllerServiceName = 'cs'.$apiOrCrud.'_'.$crudEntry['name'].'_controller';
$controller = new Definition($controllerClass);
$controller->addTag('controller.service_arguments');
$controller->setAutoconfigured(true);
$controller->setClass($controllerClass);
$param = 'chill_main_'.$apiOrCrud.'_config_'.$crudEntry['name'];
$container->setParameter($param, $crudEntry);
$controller->addMethodCall('setCrudConfig', ['%'.$param.'%']);
dump(__LINE__, $controller);
$container->setDefinition($controllerServiceName, $controller);
}
}
}

View File

@@ -8,6 +8,7 @@ use Chill\MainBundle\DependencyInjection\Widget\Factory\WidgetFactoryInterface;
use Symfony\Component\Config\Definition\Builder\ArrayNodeDefinition;
use Chill\MainBundle\DependencyInjection\Widget\AddWidgetConfigurationTrait;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\HttpFoundation\Request;
/**
@@ -140,7 +141,7 @@ class Configuration implements ConfigurationInterface
->scalarNode('controller_action')
->defaultNull()
->info('the method name to call in the route. Will be set to the action name if left empty.')
->example("'action'")
->example("action")
->end()
->scalarNode('path')
->defaultNull()
@@ -168,6 +169,72 @@ class Configuration implements ConfigurationInterface
->end()
->end()
->arrayNode('apis')
->defaultValue([])
->arrayPrototype()
->children()
->scalarNode('class')->cannotBeEmpty()->isRequired()->end()
->scalarNode('controller')
->cannotBeEmpty()
->defaultValue(\Chill\MainBundle\CRUD\Controller\ApiController::class)
->end()
->scalarNode('name')->cannotBeEmpty()->isRequired()->end()
->scalarNode('base_path')->cannotBeEmpty()->isRequired()->end()
->scalarNode('base_role')->defaultNull()->end()
->arrayNode('actions')
->useAttributeAsKey('name')
->arrayPrototype()
->children()
->scalarNode('controller_action')
->defaultNull()
->info('the method name to call in the route. Will be set to the concatenation of action name + \'Api\' if left empty.')
->example("showApi")
->end()
->scalarNode('path')
->defaultNull()
->info('the path that will be **appended** after the base path. Do not forget to add '
. 'arguments for the method. By default, will set to the action name, including an `{id}` '
. 'parameter. A suffix of action name will be appended, except if the action name is "entity".')
->example('/{id}/my-action')
->end()
->arrayNode('requirements')
->ignoreExtraKeys(false)
->info('the requirements for the route. Will be set to `[ \'id\' => \'\d+\' ]` if left empty.')
->end()
->enumNode('single-collection')
->values(['single', 'collection'])
->info('indicates if the returned object is a single element or a collection')
->end()
->arrayNode('methods')
->addDefaultsIfNotSet()
->info('the allowed methods')
->children()
->booleanNode(Request::METHOD_GET)->defaultTrue()->end()
->booleanNode(Request::METHOD_HEAD)->defaultTrue()->end()
->booleanNode(Request::METHOD_POST)->defaultFalse()->end()
->booleanNode(Request::METHOD_DELETE)->defaultFalse()->end()
->booleanNode(Request::METHOD_PUT)->defaultFalse()->end()
->end()
->end()
->arrayNode('roles')
->info("The role require for each http method")
->children()
->scalarNode(Request::METHOD_GET)->defaultNull()->end()
->scalarNode(Request::METHOD_HEAD)->defaultNull()->end()
->scalarNode(Request::METHOD_POST)->defaultNull()->end()
->scalarNode(Request::METHOD_DELETE)->defaultNull()->end()
->scalarNode(Request::METHOD_PUT)->defaultNull()->end()
->end()
->end()
->end()
->end()
->end()
->end()
->end()
->end()
->end() // end of root/children
->end() // end of root
;