crudConfig = $crudConfig; $this->apiCrudConfig = $apiCrudConfig; parent::__construct(); } /** * Load routes for CRUD and CRUD Api. * * @param mixed $resource * @param mixed|null $type */ 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->apiCrudConfig as $crudConfig) { $collection->addCollection($this->loadApi($crudConfig)); } return $collection; } /** * @param mixed $resource * @param null $type * * @return bool */ public function supports($resource, $type = null) { return 'CRUD' === $type; } /** * Load routes for api single. * * @param $crudConfig */ 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; } // 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'], 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 (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, 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 (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; } /** * Load routes for CRUD (without api). * * @param $crudConfig */ 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; } }