protected function getRouteByNames(DrupalStyle $io, $route_name) { $routes = $this->routeProvider->getRoutesByNames($route_name); foreach ($routes as $name => $route) { $tableHeader = [$this->trans('commands.router.debug.messages.route'), '<info>' . $name . '</info>']; $tableRows = []; $tableRows[] = ['<comment>' . $this->trans('commands.router.debug.messages.path') . '</comment>', $route->getPath()]; $tableRows[] = ['<comment>' . $this->trans('commands.router.debug.messages.defaults') . '</comment>']; $attributes = $this->addRouteAttributes($route->getDefaults()); foreach ($attributes as $attribute) { $tableRows[] = $attribute; } $tableRows[] = ['<comment>' . $this->trans('commands.router.debug.messages.requirements') . '</comment>']; $requirements = $this->addRouteAttributes($route->getRequirements()); foreach ($requirements as $requirement) { $tableRows[] = $requirement; } $tableRows[] = ['<comment>' . $this->trans('commands.router.debug.messages.options') . '</comment>']; $options = $this->addRouteAttributes($route->getOptions()); foreach ($options as $option) { $tableRows[] = $option; } $io->table($tableHeader, $tableRows, 'compact'); } }
/** * {@inheritdoc} */ public function load($menu_name, MenuTreeParameters $parameters) { $data = $this->treeStorage->loadTreeData($menu_name, $parameters); // Pre-load all the route objects in the tree for access checks. if ($data['route_names']) { $this->routeProvider->getRoutesByNames($data['route_names']); } return $this->createInstances($data['tree']); }
/** * {@inheritdoc} */ public function buildForm(array $form, FormStateInterface $form_state) { $settings = $this->config('rest_api_doc.settings'); $enabled_route_names = $settings->get('routes'); $available_route_names = $this->state->get('rest_api_doc.rest_route_names'); if (empty($available_route_names)) { return array( 'no_routes' => array( '#markup' => $this->t('No REST enabled routes exist, please configure your REST end-points'), ), ); } else { $routes = $this->routeProvider->getRoutesByNames($available_route_names); $descriptions = array(); foreach ($routes as $route_name => $route) { $descriptions[$route_name] = $route_name . ' (' . $route->getPath() . ')'; } $form['routes'] = array( '#type' => 'checkboxes', '#title' => $this->t('Enabled routes'), '#description' => $this->t('Provide documentation for the following route names'), '#options' => array_combine($available_route_names, $descriptions), '#default_value' => $enabled_route_names, ); $form['overview'] = array( '#type' => 'textarea', '#default_value' => $settings->get('overview'), '#title' => $this->t('REST API overview'), '#description' => $this->t('Description to show on summary page. You may use site-wide tokens and some markup.'), ); } return parent::buildForm($form, $form_state); }
/** * {@inheritdoc} */ public function getActionsForRoute($route_appears) { if (!isset($this->instances[$route_appears])) { $route_names = array(); $this->instances[$route_appears] = array(); // @todo - optimize this lookup by compiling or caching. foreach ($this->getDefinitions() as $plugin_id => $action_info) { if (in_array($route_appears, $action_info['appears_on'])) { $plugin = $this->createInstance($plugin_id); $route_names[] = $plugin->getRouteName(); $this->instances[$route_appears][$plugin_id] = $plugin; } } // Pre-fetch all the action route objects. This reduces the number of SQL // queries that would otherwise be triggered by the access manager. if (!empty($route_names)) { $this->routeProvider->getRoutesByNames($route_names); } } $links = array(); /** @var $plugin \Drupal\Core\Menu\LocalActionInterface */ foreach ($this->instances[$route_appears] as $plugin_id => $plugin) { $route_name = $plugin->getRouteName(); $route_parameters = $plugin->getRouteParameters($this->routeMatch); $links[$plugin_id] = array('#theme' => 'menu_local_action', '#link' => array('title' => $this->getTitle($plugin), 'url' => Url::fromRoute($route_name, $route_parameters), 'localized_options' => $plugin->getOptions($this->routeMatch)), '#access' => $this->accessManager->checkNamedRoute($route_name, $route_parameters, $this->account), '#weight' => $plugin->getWeight()); } return $links; }
/** * {@inheritdoc} */ public function getTasksBuild($current_route_name, RefinableCacheableDependencyInterface &$cacheability) { $tree = $this->getLocalTasksForRoute($current_route_name); $build = array(); // Collect all route names. $route_names = array(); foreach ($tree as $instances) { foreach ($instances as $child) { $route_names[] = $child->getRouteName(); } } // Pre-fetch all routes involved in the tree. This reduces the number // of SQL queries that would otherwise be triggered by the access manager. $routes = $route_names ? $this->routeProvider->getRoutesByNames($route_names) : array(); foreach ($tree as $level => $instances) { /** @var $instances \Drupal\Core\Menu\LocalTaskInterface[] */ foreach ($instances as $plugin_id => $child) { $route_name = $child->getRouteName(); $route_parameters = $child->getRouteParameters($this->routeMatch); // Given that the active flag depends on the route we have to add the // route cache context. $cacheability->addCacheContexts(['route']); $active = $this->isRouteActive($current_route_name, $route_name, $route_parameters); // The plugin may have been set active in getLocalTasksForRoute() if // one of its child tabs is the active tab. $active = $active || $child->getActive(); // @todo It might make sense to use link render elements instead. $link = ['title' => $this->getTitle($child), 'url' => Url::fromRoute($route_name, $route_parameters), 'localized_options' => $child->getOptions($this->routeMatch)]; $access = $this->accessManager->checkNamedRoute($route_name, $route_parameters, $this->account, TRUE); $build[$level][$plugin_id] = ['#theme' => 'menu_local_task', '#link' => $link, '#active' => $active, '#weight' => $child->getWeight(), '#access' => $access]; $cacheability->addCacheableDependency($access)->addCacheableDependency($child); } } return $build; }
/** * {@inheritdoc} */ public function getTasksBuild($current_route_name) { $tree = $this->getLocalTasksForRoute($current_route_name); $build = array(); // Collect all route names. $route_names = array(); foreach ($tree as $instances) { foreach ($instances as $child) { $route_names[] = $child->getRouteName(); } } // Pre-fetch all routes involved in the tree. This reduces the number // of SQL queries that would otherwise be triggered by the access manager. $routes = $route_names ? $this->routeProvider->getRoutesByNames($route_names) : array(); foreach ($tree as $level => $instances) { /** @var $instances \Drupal\Core\Menu\LocalTaskInterface[] */ foreach ($instances as $plugin_id => $child) { $route_name = $child->getRouteName(); $route_parameters = $child->getRouteParameters($this->routeMatch); // Find out whether the user has access to the task. $access = $this->accessManager->checkNamedRoute($route_name, $route_parameters, $this->account); if ($access) { $active = $this->isRouteActive($current_route_name, $route_name, $route_parameters); // The plugin may have been set active in getLocalTasksForRoute() if // one of its child tabs is the active tab. $active = $active || $child->getActive(); // @todo It might make sense to use link render elements instead. $link = array('title' => $this->getTitle($child), 'url' => Url::fromRoute($route_name, $route_parameters), 'localized_options' => $child->getOptions($this->routeMatch)); $build[$level][$plugin_id] = array('#theme' => 'menu_local_task', '#link' => $link, '#active' => $active, '#weight' => $child->getWeight(), '#access' => $access); } } } return $build; }
/** * Controller callback for API overview. */ public function summary() { $route_names = $this->config->get('routes'); if (empty($route_names)) { $return = array( '#markup' => $this->t('No REST API endpoints configured or available.'), ); if ($this->currentUser()->hasPermission('administer rest_api_doc')) { $return['#markup'] .= ' ' . $this->t('Please !link routes used for REST API documentation.', array( '!link' => $this->l($this->t('configure'), Url::fromRoute('rest_api_doc.settings')), ));; } return $return; } $overview = $this->token->replace(Xss::filterAdmin($this->config->get('overview'))); $return['overview'] = array( '#markup' => $overview, ); $links = array(); $routes = $this->routeProvider->getRoutesByNames($route_names); foreach ($routes as $route_name => $route) { $path = $route->getPath(); $links[$path] = $this->l($path, Url::fromRoute('rest_api_doc.documentation_detail', array( 'path' => str_replace('/', '::', $path), ))); } $return['toc'] = array( '#title' => $this->t('Available end-points'), '#theme' => 'item_list', '#items' => $links, ); return $return; }
/** * {@inheritdoc} */ public function getActionsForRoute($route_appears) { if (!isset($this->instances[$route_appears])) { $route_names = array(); $this->instances[$route_appears] = array(); // @todo - optimize this lookup by compiling or caching. foreach ($this->getDefinitions() as $plugin_id => $action_info) { if (in_array($route_appears, $action_info['appears_on'])) { $plugin = $this->createInstance($plugin_id); $route_names[] = $plugin->getRouteName(); $this->instances[$route_appears][$plugin_id] = $plugin; } } // Pre-fetch all the action route objects. This reduces the number of SQL // queries that would otherwise be triggered by the access manager. if (!empty($route_names)) { $this->routeProvider->getRoutesByNames($route_names); } } $links = array(); /** @var $plugin \Drupal\Core\Menu\LocalActionInterface */ foreach ($this->instances[$route_appears] as $plugin_id => $plugin) { $cacheability = new CacheableMetadata(); $route_name = $plugin->getRouteName(); $route_parameters = $plugin->getRouteParameters($this->routeMatch); $access = $this->accessManager->checkNamedRoute($route_name, $route_parameters, $this->account, TRUE); $links[$plugin_id] = array('#theme' => 'menu_local_action', '#link' => array('title' => $this->getTitle($plugin), 'url' => Url::fromRoute($route_name, $route_parameters), 'localized_options' => $plugin->getOptions($this->routeMatch)), '#access' => $access, '#weight' => $plugin->getWeight()); $cacheability->addCacheableDependency($access); // For backward compatibility in 8.0.x, plugins that do not implement // the \Drupal\Core\Cache\CacheableDependencyInterface are assumed // to be cacheable forever. if ($plugin instanceof CacheableDependencyInterface) { $cacheability->addCacheableDependency($plugin); } else { $cacheability->setCacheMaxAge(Cache::PERMANENT); } $cacheability->applyTo($links[$plugin_id]); } $links['#cache']['contexts'][] = 'route'; return $links; }
/** * Load all the non-admin routes at once. */ protected function loadNonAdminRoutes() { if ($routes = $this->state->get('routing.non_admin_routes', array())) { $this->routeProvider->getRoutesByNames($routes); } }
/** * {@inheritdoc} */ protected function interact(InputInterface $input, OutputInterface $output) { $io = new DrupalStyle($input, $output); // --module option $module = $input->getOption('module'); if (!$module) { // @see Drupal\Console\Command\Shared\ModuleTrait::moduleQuestion $module = $this->moduleQuestion($io); $input->setOption('module', $module); } // --class option $class = $input->getOption('class'); if (!$class) { $class = $io->ask($this->trans('commands.generate.controller.questions.class'), 'DefaultController', function ($class) { return $this->validator->validateClassName($class); }); $input->setOption('class', $class); } $routes = $input->getOption('routes'); if (!$routes) { while (true) { $title = $io->askEmpty($this->trans('commands.generate.controller.questions.title'), function ($title) use($routes) { if ($routes && empty(trim($title))) { return false; } if (!$routes && empty(trim($title))) { throw new \InvalidArgumentException($this->trans('commands.generate.controller.messages.title-empty')); } if (in_array($title, array_column($routes, 'title'))) { throw new \InvalidArgumentException(sprintf($this->trans('commands.generate.controller.messages.title-already-added'), $title)); } return $title; }); if ($title === '') { break; } $method = $io->ask($this->trans('commands.generate.controller.questions.method'), 'hello', function ($method) use($routes) { if (in_array($method, array_column($routes, 'method'))) { throw new \InvalidArgumentException(sprintf($this->trans('commands.generate.controller.messages.method-already-added'), $method)); } return $method; }); $path = $io->ask($this->trans('commands.generate.controller.questions.path'), sprintf('/%s/hello/{name}', $module), function ($path) use($routes) { if (count($this->routeProvider->getRoutesByPattern($path)) > 0 || in_array($path, array_column($routes, 'path'))) { throw new \InvalidArgumentException(sprintf($this->trans('commands.generate.controller.messages.path-already-added'), $path)); } return $path; }); $classMachineName = $this->stringConverter->camelCaseToMachineName($class); $routeName = $module . '.' . $classMachineName . '_' . $method; if ($this->routeProvider->getRoutesByNames([$routeName]) || in_array($routeName, $routes)) { $routeName .= '_' . rand(0, 100); } $routes[] = ['title' => $title, 'name' => $routeName, 'method' => $method, 'path' => $path]; } $input->setOption('routes', $routes); } // --test option $test = $input->getOption('test'); if (!$test) { $test = $io->confirm($this->trans('commands.generate.controller.questions.test'), true); $input->setOption('test', $test); } // --services option // @see use Drupal\Console\Command\Shared\ServicesTrait::servicesQuestion $services = $this->servicesQuestion($io); $input->setOption('services', $services); }