mirror of
https://gitlab.com/Chill-Projet/chill-bundles.git
synced 2025-06-07 18:44:08 +00:00
229 lines
7.7 KiB
PHP
229 lines
7.7 KiB
PHP
<?php
|
|
/*
|
|
* Chill is a software for social workers
|
|
*
|
|
* Copyright (C) 2019, Champs Libres Cooperative SCRLFS, <http://www.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\CRUD\Routing;
|
|
|
|
use Symfony\Component\Config\Loader\Loader;
|
|
use Symfony\Component\Routing\Route;
|
|
use Symfony\Component\Routing\RouteCollection;
|
|
use Symfony\Component\HttpFoundation\Request;
|
|
use Chill\MainBundle\CRUD\Controller\ApiController;
|
|
use Chill\MainBundle\CRUD\Controller\CRUDController;
|
|
|
|
/**
|
|
* Class CRUDRoutesLoader
|
|
* Load the route for CRUD
|
|
*
|
|
* @package Chill\MainBundle\CRUD\Routing
|
|
*/
|
|
class CRUDRoutesLoader extends Loader
|
|
{
|
|
protected array $crudConfig = [];
|
|
|
|
protected array $apiCrudConfig = [];
|
|
|
|
/**
|
|
* @var bool
|
|
*/
|
|
private $isLoaded = false;
|
|
|
|
private const ALL_SINGLE_METHODS = [
|
|
Request::METHOD_GET,
|
|
Request::METHOD_POST,
|
|
Request::METHOD_PUT,
|
|
Request::METHOD_DELETE
|
|
];
|
|
|
|
private const ALL_INDEX_METHODS = [ Request::METHOD_GET, Request::METHOD_HEAD ];
|
|
|
|
/**
|
|
* CRUDRoutesLoader constructor.
|
|
*
|
|
* @param $crudConfig the config from cruds
|
|
* @param $apicrudConfig the config from api_crud
|
|
*/
|
|
public function __construct(array $crudConfig, array $apiConfig)
|
|
{
|
|
$this->crudConfig = $crudConfig;
|
|
$this->apiConfig = $apiConfig;
|
|
}
|
|
|
|
/**
|
|
* @param mixed $resource
|
|
* @param null $type
|
|
* @return bool
|
|
*/
|
|
public function supports($resource, $type = null)
|
|
{
|
|
return 'CRUD' === $type;
|
|
}
|
|
|
|
/**
|
|
* Load routes for CRUD and CRUD Api
|
|
*/
|
|
public function load($resource, $type = null): RouteCollection
|
|
{
|
|
if (true === $this->isLoaded) {
|
|
throw new \RuntimeException('Do not add the "CRUD" loader twice');
|
|
}
|
|
|
|
$collection = new RouteCollection();
|
|
|
|
foreach ($this->crudConfig as $crudConfig) {
|
|
$collection->addCollection($this->loadCrudConfig($crudConfig));
|
|
}
|
|
foreach ($this->apiConfig as $crudConfig) {
|
|
$collection->addCollection($this->loadApi($crudConfig));
|
|
}
|
|
|
|
return $collection;
|
|
}
|
|
|
|
/**
|
|
* Load routes for CRUD (without api)
|
|
*
|
|
* @param $crudConfig
|
|
* @return RouteCollection
|
|
*/
|
|
protected function loadCrudConfig($crudConfig): RouteCollection
|
|
{
|
|
$collection = new RouteCollection();
|
|
$controller ='cscrud_'.$crudConfig['name'].'_controller';
|
|
|
|
foreach ($crudConfig['actions'] as $name => $action) {
|
|
// defaults (controller name)
|
|
$defaults = [
|
|
'_controller' => $controller.':'.($action['controller_action'] ?? $name)
|
|
];
|
|
|
|
if ($name === 'index') {
|
|
$path = "{_locale}".$crudConfig['base_path'];
|
|
$route = new Route($path, $defaults);
|
|
} elseif ($name === 'new') {
|
|
$path = "{_locale}".$crudConfig['base_path'].'/'.$name;
|
|
$route = new Route($path, $defaults);
|
|
} else {
|
|
$path = "{_locale}".$crudConfig['base_path'].($action['path'] ?? '/{id}/'.$name);
|
|
$requirements = $action['requirements'] ?? [
|
|
'{id}' => '\d+'
|
|
];
|
|
$route = new Route($path, $defaults, $requirements);
|
|
}
|
|
|
|
$collection->add('chill_crud_'.$crudConfig['name'].'_'.$name, $route);
|
|
}
|
|
|
|
return $collection;
|
|
}
|
|
|
|
/**
|
|
* Load routes for api single
|
|
*
|
|
* @param $crudConfig
|
|
* @return RouteCollection
|
|
*/
|
|
protected function loadApi(array $crudConfig): RouteCollection
|
|
{
|
|
$collection = new RouteCollection();
|
|
$controller = 'csapi_'.$crudConfig['name'].'_controller';
|
|
|
|
foreach ($crudConfig['actions'] as $name => $action) {
|
|
// filter only on single actions
|
|
$singleCollection = $action['single_collection'] ?? $name === '_entity' ? 'single' : NULL;
|
|
if ('collection' === $singleCollection) {
|
|
// continue;
|
|
}
|
|
|
|
// compute default action
|
|
switch ($name) {
|
|
case '_entity':
|
|
$controllerAction = 'entityApi';
|
|
break;
|
|
case '_index':
|
|
$controllerAction = 'indexApi';
|
|
break;
|
|
default:
|
|
$controllerAction = $name.'Api';
|
|
break;
|
|
}
|
|
|
|
$defaults = [
|
|
'_controller' => $controller.':'.($action['controller_action'] ?? $controllerAction)
|
|
];
|
|
|
|
// path are rewritten
|
|
// if name === 'default', we rewrite it to nothing :-)
|
|
$localName = \in_array($name, [ '_entity', '_index' ]) ? '' : '/'.$name;
|
|
if ('collection' === $action['single_collection'] || '_index' === $name) {
|
|
$localPath = $action['path'] ?? $localName.'.{_format}';
|
|
} else {
|
|
$localPath = $action['path'] ?? '/{id}'.$localName.'.{_format}';
|
|
}
|
|
$path = $crudConfig['base_path'].$localPath;
|
|
|
|
$requirements = $action['requirements'] ?? [ '{id}' => '\d+' ];
|
|
|
|
$methods = \array_keys(\array_filter($action['methods'], function($value, $key) { return $value; },
|
|
ARRAY_FILTER_USE_BOTH));
|
|
|
|
if (count($methods) === 0) {
|
|
throw new \RuntimeException("The api configuration named \"{$crudConfig['name']}\", action \"{$name}\", ".
|
|
"does not have any allowed methods. You should remove this action from the config ".
|
|
"or allow, at least, one method");
|
|
}
|
|
|
|
if ('_entity' === $name && \in_array(Request::METHOD_POST, $methods)) {
|
|
unset($methods[\array_search(Request::METHOD_POST, $methods)]);
|
|
$entityPostRoute = $this->createEntityPostRoute($name, $crudConfig, $action,
|
|
$controller);
|
|
$collection->add("chill_api_single_{$crudConfig['name']}_{$name}_create",
|
|
$entityPostRoute);
|
|
}
|
|
|
|
if (count($methods) === 0) {
|
|
// the only method was POST,
|
|
// continue to next
|
|
continue;
|
|
}
|
|
|
|
$route = new Route($path, $defaults, $requirements);
|
|
$route->setMethods($methods);
|
|
|
|
$collection->add('chill_api_single_'.$crudConfig['name'].'_'.$name, $route);
|
|
}
|
|
|
|
return $collection;
|
|
}
|
|
|
|
private function createEntityPostRoute(string $name, $crudConfig, array $action, $controller): Route
|
|
{
|
|
$localPath = $action['path'].'.{_format}';
|
|
$defaults = [
|
|
'_controller' => $controller.':'.($action['controller_action'] ?? 'entityPost')
|
|
];
|
|
$path = $crudConfig['base_path'].$localPath;
|
|
$requirements = $action['requirements'] ?? [];
|
|
$route = new Route($path, $defaults, $requirements);
|
|
$route->setMethods([ Request::METHOD_POST ]);
|
|
|
|
return $route;
|
|
}
|
|
}
|