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->apiCrudConfig as $crudConfig) { $collection->addCollection($this->loadApi($crudConfig)); } return $collection; } /** * @param null $type * * @return bool */ public function supports($resource, $type = null) { return 'CRUD' === $type; } /** * Load routes for api single. */ 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'] ?? '_entity' === $name ? 'single' : null; if ('collection' === $singleCollection) { // continue; } $controllerAction = match ($name) { '_entity' => 'entityApi', '_index' => 'indexApi', default => $name.'Api', }; $defaults = [ '_controller' => $controller.':'.($action['controller_action'] ?? $controllerAction), ]; // path are rewritten // if name === 'default', we rewrite it to nothing :-) $localName = \in_array($name, ['_entity', '_index'], true) ? '' : '/'.$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'], static fn ($value, $key) => $value, \ARRAY_FILTER_USE_BOTH )); if (0 === \count($methods)) { 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, true)) { unset($methods[\array_search(Request::METHOD_POST, $methods, true)]); $entityPostRoute = $this->createEntityPostRoute( $name, $crudConfig, $action, $controller ); $collection->add( "chill_api_single_{$crudConfig['name']}_{$name}_create", $entityPostRoute ); } if (0 === \count($methods)) { // 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; } /** * Load routes for CRUD (without api). */ 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 ('index' === $name) { $path = '{_locale}'.$crudConfig['base_path']; $route = new Route($path, $defaults); } elseif ('new' === $name) { $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; } 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; } }