/** * {@inheritdoc} */ public function isValid($path) { // External URLs and the front page are always valid. if ($path == '<front>' || UrlHelper::isExternal($path)) { return TRUE; } // Check the routing system. $collection = $this->routeProvider->getRoutesByPattern('/' . $path); if ($collection->count() == 0) { return FALSE; } $request = RequestHelper::duplicate($this->requestStack->getCurrentRequest(), '/' . $path); $request->attributes->set('_system_path', $path); // We indicate that a menu administrator is running the menu access check. $request->attributes->set('_menu_admin', TRUE); // Attempt to match this path to provide a fully built request to the // access checker. try { $request->attributes->add($this->requestMatcher->matchRequest($request)); } catch (ParamNotConvertedException $e) { return FALSE; } // Consult the access manager. $routes = $collection->all(); $route = reset($routes); return $this->accessManager->check($route, $request, $this->account); }
/** * Adds in the current user as a context. * * @param \Drupal\page_manager\Event\PageManagerContextEvent $event * The page entity context event. */ public function onPageContext(PageManagerContextEvent $event) { $request = $this->requestStack->getCurrentRequest(); $page = $event->getPage(); $routes = $this->routeProvider->getRoutesByPattern($page->getPath())->all(); $route = reset($routes); if ($route && ($route_contexts = $route->getOption('parameters'))) { foreach ($route_contexts as $route_context_name => $route_context) { // Skip this parameter. if ($route_context_name == 'page_manager_page_variant' || $route_context_name == 'page_manager_page') { continue; } $context_name = $this->t('{@name} from route', ['@name' => $route_context_name]); if ($request->attributes->has($route_context_name)) { $value = $request->attributes->get($route_context_name); } else { // @todo Find a way to add in a fake value for configuration. $value = NULL; } $cacheability = new CacheableMetadata(); $cacheability->setCacheContexts(['route']); $context = new Context(new ContextDefinition($route_context['type'], $context_name, FALSE), $value); $context->addCacheableDependency($cacheability); $page->addContext($route_context_name, $context); } } }
/** * {@inheritdoc} */ public function rewrite(FunctionCallNode $call, TargetInterface $target) { $arguments = $call->getArguments(); if ($arguments[0] instanceof StringNode) { $path = $arguments[0]->toValue(); // If the URL has a scheme (e.g., http://), it's external. if (parse_url($path, PHP_URL_SCHEME)) { return ClassMethodCallNode::create('\\Drupal\\Core\\Url', 'fromUri')->appendArgument(clone $arguments[0]); } elseif ($this->routeExists($path)) { $route = $this->routeProvider->getRoutesByPattern('/' . $path)->getIterator()->key(); return ClassMethodCallNode::create('\\Drupal\\Core\\Url', 'fromRoute')->appendArgument(StringNode::fromValue($route)); } } }
/** * Alters base_route and parent_id into the views local tasks. */ public function alterLocalTasks(&$local_tasks) { $view_route_names = $this->state->get('views.view_route_names'); foreach ($this->getApplicableMenuViews() as $pair) { list($view_id, $display_id) = $pair; /** @var $executable \Drupal\views\ViewExecutable */ $executable = $this->viewStorage->load($view_id)->getExecutable(); $executable->setDisplay($display_id); $menu = $executable->display_handler->getOption('menu'); // We already have set the base_route for default tabs. if (in_array($menu['type'], array('tab'))) { $plugin_id = 'view.' . $executable->storage->id() . '.' . $display_id; $view_route_name = $view_route_names[$executable->storage->id() . '.' . $display_id]; // Don't add a local task for views which override existing routes. if ($view_route_name != $plugin_id) { unset($local_tasks[$plugin_id]); continue; } // Find out the parent route. // @todo Find out how to find both the root and parent tab. $path = $executable->display_handler->getPath(); $split = explode('/', $path); array_pop($split); $path = implode('/', $split); $pattern = '/' . str_replace('%', '{}', $path); if ($routes = $this->routeProvider->getRoutesByPattern($pattern)) { foreach ($routes->all() as $name => $route) { $local_tasks['views_view:' . $plugin_id]['base_route'] = $name; // Skip after the first found route. break; } } } } }
/** * Adds in the current user as a context. * * @param \Drupal\page_manager\Event\PageManagerContextEvent $event * The page entity context event. */ public function onPageContext(PageManagerContextEvent $event) { $request = $this->requestStack->getCurrentRequest(); $executable = $event->getPageExecutable(); $routes = $this->routeProvider->getRoutesByPattern($executable->getPage()->getPath())->all(); $route = reset($routes); if ($route_contexts = $route->getOption('parameters')) { foreach ($route_contexts as $route_context_name => $route_context) { // Skip this parameter. if ($route_context_name == 'page_manager_page') { continue; } $context_name = $this->t('{@name} from route', ['@name' => $route_context_name]); $context = new Context(new ContextDefinition($route_context['type'], $context_name)); if ($request->attributes->has($route_context_name)) { $context->setContextValue($request->attributes->get($route_context_name)); } else { // @todo Find a way to add in a fake value for configuration. } $executable->addContext($route_context_name, $context); } } }
/** * Tests the creation of entity_browser. */ protected function createTests() { $plugin = ['name' => 'test_browser', 'label' => 'Testing entity browser instance', 'display' => 'standalone', 'display_configuration' => ['path' => 'test-browser-test'], 'selection_display' => 'no_display', 'selection_display_configuration' => [], 'widget_selector' => 'single', 'widget_selector_configuration' => [], 'widgets' => [$this->widgetUUID => ['id' => 'view', 'label' => 'View widget', 'uuid' => $this->widgetUUID, 'weight' => 0, 'settings' => ['view' => 'test_view', 'view_display' => 'test_display']]]]; foreach (['display' => 'getDisplay', 'selection_display' => 'getSelectionDisplay', 'widget_selector' => 'getWidgetSelector'] as $plugin_type => $function_name) { $current_plugin = $plugin; unset($current_plugin[$plugin_type]); // Attempt to create an entity_browser without required plugin. try { $entity = $this->controller->create($current_plugin); $entity->{$function_name}(); $this->fail('An entity browser without required ' . $plugin_type . ' created with no exception thrown.'); } catch (PluginException $e) { $this->assertEquals('The "" plugin does not exist.', $e->getMessage(), 'An exception was thrown when an entity_browser was created without a ' . $plugin_type . ' plugin.'); } } // Try to create an entity browser w/o the ID. $current_plugin = $plugin; unset($current_plugin['name']); try { $entity = $this->controller->create($current_plugin); $entity->save(); $this->fail('An entity browser without required name created with no exception thrown.'); } catch (EntityMalformedException $e) { $this->assertEquals('The entity does not have an ID.', $e->getMessage(), 'An exception was thrown when an entity_browser was created without a name.'); } // Create an entity_browser with required values. $entity = $this->controller->create($plugin); $entity->save(); $this->assertTrue($entity instanceof EntityBrowserInterface, 'The newly created entity is an Entity browser.'); // Verify all of the properties. $actual_properties = $this->container->get('config.factory')->get('entity_browser.browser.test_browser')->get(); $this->assertTrue(!empty($actual_properties['uuid']), 'The entity browser UUID is set.'); unset($actual_properties['uuid']); // Ensure that default values are filled in. $expected_properties = ['langcode' => $this->container->get('language_manager')->getDefaultLanguage()->getId(), 'status' => TRUE, 'dependencies' => [], 'name' => 'test_browser', 'label' => 'Testing entity browser instance', 'display' => 'standalone', 'display_configuration' => ['path' => 'test-browser-test'], 'selection_display' => 'no_display', 'selection_display_configuration' => [], 'widget_selector' => 'single', 'widget_selector_configuration' => [], 'widgets' => [$this->widgetUUID => ['id' => 'view', 'label' => 'View widget', 'uuid' => $this->widgetUUID, 'weight' => 0, 'settings' => ['view' => 'test_view', 'view_display' => 'test_display']]]]; $this->assertEquals($actual_properties, $expected_properties, 'Actual config properties are structured as expected.'); // Ensure that rebuilding routes works. $route = $this->routeProvider->getRoutesByPattern('/test-browser-test'); $this->assertTrue($route, 'Route exists.'); }
/** * {@inheritdoc} */ public function onRouterBuilt(RouterBuiltEvent $event) { $this->router = $event->getRouter(); try { $parent = $this->getPath()->getParent()->__toString(); } catch (\LengthException $e) { return; } // First, search the injected router for the parent route. foreach ($this->router as $route) { if ($route->getPath() == $parent) { $this->parent = $route; } } // Next, search the core route provider if no parent was found. if (empty($this->parent)) { $parents = $this->routeProvider->getRoutesByPattern($parent)->getIterator(); if (sizeof($parents) > 0) { $this->parent = new static($parents->key(), $parents->current(), $this->routeProvider); } } }
/** * {@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); }
/** * {@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 $className = $input->getOption('class'); if (!$className) { $className = $io->ask($this->trans('commands.generate.form.questions.class'), 'DefaultForm'); $input->setOption('class', $className); } // --form-id option $formId = $input->getOption('form-id'); if (!$formId) { $formId = $io->ask($this->trans('commands.generate.form.questions.form-id'), $this->stringConverter->camelCaseToMachineName($className)); $input->setOption('form-id', $formId); } // --services option // @see use Drupal\Console\Command\Shared\ServicesTrait::servicesQuestion $services = $this->servicesQuestion($io); $input->setOption('services', $services); // --inputs option $inputs = $input->getOption('inputs'); if (!$inputs) { // @see \Drupal\Console\Command\Shared\FormTrait::formQuestion $inputs = $this->formQuestion($io); $input->setOption('inputs', $inputs); } $path = $input->getOption('path'); if (!$path) { if ($this->formType == 'ConfigFormBase') { $form_path = '/admin/config/{{ module_name }}/{{ class_name_short }}'; $form_path = sprintf('/admin/config/%s/%s', $module, strtolower($this->stringConverter->removeSuffix($className))); } else { $form_path = sprintf('/%s/form/%s', $module, $this->stringConverter->camelCaseToMachineName($this->stringConverter->removeSuffix($className))); } $path = $io->ask($this->trans('commands.generate.form.questions.path'), $form_path, function ($path) { if (count($this->routeProvider->getRoutesByPattern($path)) > 0) { throw new \InvalidArgumentException(sprintf($this->trans('commands.generate.form.messages.path-already-added'), $path)); } return $path; }); $input->setOption('path', $path); } // --link option for links.menu if ($this->formType == 'ConfigFormBase') { $menu_options = $this->menuQuestion($io, $className); $menu_link_gen = $input->getOption('menu_link_gen'); $menu_link_title = $input->getOption('menu_link_title'); $menu_parent = $input->getOption('menu_parent'); $menu_link_desc = $input->getOption('menu_link_desc'); if (!$menu_link_gen || !$menu_link_title || !$menu_parent || !$menu_link_desc) { $input->setOption('menu_link_gen', $menu_options['menu_link_gen']); $input->setOption('menu_link_title', $menu_options['menu_link_title']); $input->setOption('menu_parent', $menu_options['menu_parent']); $input->setOption('menu_link_desc', $menu_options['menu_link_desc']); } } }
/** * Check if a route with the given path exists. * * @param string $path * @return int */ public function routeExists($path) { return $this->routeProvider->getRoutesByPattern('/' . $path)->count(); }
/** * Controller callback for route detail. */ public function routeDetail($path) { $path = str_replace('::', '/', $path); $theme_key = str_replace(array('/', '{', '}'), array('__', '', ''), $path); $routes = $this->routeProvider->getRoutesByPattern($path)->all(); $return = array( 'overview' => array( '#theme' => 'rest_api_doc_detail__' . $theme_key, '#path' => $path, '#title' => $path, ), ); $first = TRUE; foreach ($routes as $route_name => $route) { if (!in_array($route_name, $this->config->get('routes'))) { continue; } $return[$route_name] = array( '#type' => 'details', '#title' => $path . ' (' . implode(', ', $route->getMethods()) . ' )', '#open' => $first, ); $first = FALSE; $controller = $route->getDefault('_controller'); if (strpos($controller, '::') !== FALSE) { list($controller_class, $controller_method) = explode('::', $controller); $reflection = new \ReflectionMethod($controller_class, $controller_method); if ($php_doc = $this->parseMethodDocBlock($reflection)) { $return[$route_name]['summary'] = array( '#markup' => Xss::filterAdmin($php_doc), ); } } $auth = array(); if ($route->getRequirement('_access_rest_csrf')) { $auth['CSRF token'] = $this->t('CSRF token: REQUIRED'); } if ($authentication_methods = $route->getOption('_auth')) { $auth += $authentication_methods; } $return[$route_name]['auth'] = array( '#theme' => 'item_list', '#items' => $auth, '#title' => $this->t('Authentication methods'), ); if ($formats = $route->getRequirement('_format')) { $return[$route_name]['formats'] = array( '#theme' => 'item_list', '#items' => explode('|', $formats), '#title' => $this->t('Supported formats'), ); } if ($permission = $route->getRequirement('_permission')) { if (empty($this->permissions)) { $this->permissions = $this->permissionHandler->getPermissions(); } if (!empty($this->permissions[$permission])) { $return[$route_name]['permisisons'] = array( '#theme' => 'item_list', '#items' => array($this->permissions[$permission]['title']), '#title' => $this->t('Required permissions'), ); } } if ($parameters = $route->getOption('parameters')) { $return[$route_name]['requirements'] = array( '#theme' => 'table', '#rows' => array(), '#caption' => $this->t('Requirements'), '#header' => array( $this->t('Name'), $this->t('Type'), $this->t('Required'), ), ); foreach ($parameters as $name => $detail) { $type = $detail['type']; if (strpos($type, 'entity:') === FALSE) { // We only handle entity parameters from here onwards. continue; } list(, $entity_type_id) = explode(':', $type); $entity_type = $this->entityManager()->getDefinition($entity_type_id); $id_field_name = $entity_type->getKey('id'); $base_fields = $this->entityManager()->getBaseFieldDefinitions($entity_type_id); $id_field = $base_fields[$id_field_name]; $row = array( $name, $id_field->getType(), 'TRUE', ); $return[$route_name]['requirements']['#rows'][] = $row; if ($route->getMethods() == array('DELETE') || $route->getMethods() == array('GET')) { // No body for these two verbs. continue; } $return[$route_name]['detail'] = array( '#theme' => 'table', '#rows' => array(), '#empty' => $this->t('No parameters found'), '#caption' => $this->t('Parameters'), '#header' => array( $this->t('Name'), $this->t('Type'), $this->t('Required'), $this->t('Description'), ), ); foreach ($base_fields as $field_name => $field) { $row = array( $field_name, $field->getType(), $field->isRequired() ? 'TRUE' : 'FALSE', $field->getDescription(), ); $return[$route_name]['detail']['#rows'][] = $row; } $bundle_info = $this->entityManager()->getBundleInfo($entity_type_id); if (count($bundle_info) > 1) { // Multiple bundles. foreach (array_keys($bundle_info) as $bundle) { $label = $bundle_info[$bundle]['label']; $row = array( 'cells' => array( 'colspan' => 4, 'data' => $this->t('Fields available for @label (@bundle_key = @bundle)', array( '@label' => $label, '@bundle_key' => $entity_type->getKey('bundle'), '@bundle' => $bundle, ) ), 'header' => TRUE, ), ); $return[$route_name]['detail']['#rows'][] = $row; $field_definitions = $this->entityManager()->getFieldDefinitions($entity_type_id, $bundle); foreach ($field_definitions as $field_name => $field) { if (!empty($base_fields[$field_name])) { continue; } $row = array( $field_name, $field->getType(), $field->isRequired() ? 'TRUE' : 'FALSE', $field->getDescription(), ); $return[$route_name]['detail']['#rows'][] = $row; } } } else { // Single bundle. $bundle_keys = array_keys($bundle_info); $bundle = array_shift($bundle_keys); $field_definitions = $this->entityManager()->getFieldDefinitions($entity_type_id, $bundle); foreach ($field_definitions as $field_name => $field) { if (!empty($base_fields[$field_name])) { continue; } $row = array( $field_name, $field->getType(), $field->isRequired() ? 'TRUE' : 'FALSE', $field->getDescription(), ); $return[$route_name]['detail']['#rows'][] = $row; } } } } } if ($first) { // No matching enabled routes for this path, return not found. throw new NotFoundHttpException(); } $return['link'] = array( '#markup' => $this->l($this->t('Back to overview'), Url::fromRoute('rest_api_doc.documentation_summary')), ); return $return; }