diff --git a/core/includes/common.inc b/core/includes/common.inc index 5a90646..d59c936 100644 --- a/core/includes/common.inc +++ b/core/includes/common.inc @@ -2809,6 +2809,17 @@ function drupal_render(&$elements, $is_recursive_call = FALSE) { $current->postRenderCache = NestedArray::mergeDeep($current->postRenderCache, $parent->postRenderCache); $stack->push($current); }; + /** @var \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver */ + $controller_resolver = \Drupal::service('controller_resolver'); + if (isset($elements['#access_callback'])) { + if (is_string($elements['#access_callback']) && strpos($elements['#access_callback'], '::') === FALSE) { + $callable = $controller_resolver->getControllerFromDefinition($elements['#access_callback']); + } + else { + $callable = $elements['#access_callback']; + } + $elements['#access'] = call_user_func($callable, $elements); + } // Early-return nothing if user does not have access. if (empty($elements) || (isset($elements['#access']) && !$elements['#access'])) { @@ -2856,8 +2867,6 @@ function drupal_render(&$elements, $is_recursive_call = FALSE) { // Make any final changes to the element before it is rendered. This means // that the $element or the children can be altered or corrected before the // element is rendered into the final text. - /** @var \Drupal\Core\Controller\ControllerResolverInterface $controller_resolver */ - $controller_resolver = \Drupal::service('controller_resolver'); if (isset($elements['#pre_render'])) { foreach ($elements['#pre_render'] as $callable) { if (is_string($callable) && strpos($callable, '::') === FALSE) { diff --git a/core/lib/Drupal/Core/Access/AccessManagerInterface.php b/core/lib/Drupal/Core/Access/AccessManagerInterface.php index df88ba6..1f8fc6d 100644 --- a/core/lib/Drupal/Core/Access/AccessManagerInterface.php +++ b/core/lib/Drupal/Core/Access/AccessManagerInterface.php @@ -45,7 +45,7 @@ * @param array $parameters * Optional array of values to substitute into the route path patern. * @param \Drupal\Core\Session\AccountInterface $account - * The current user. + * Run access checks for this account. Defaults to the current user. * @param \Symfony\Component\HttpFoundation\Request $route_request * Optional incoming request object. If not provided, one will be built * using the route information and the current request from the container. diff --git a/core/lib/Drupal/Core/Routing/RouteMatch.php b/core/lib/Drupal/Core/Routing/RouteMatch.php index 0a66610..8b29958 100644 --- a/core/lib/Drupal/Core/Routing/RouteMatch.php +++ b/core/lib/Drupal/Core/Routing/RouteMatch.php @@ -159,7 +159,7 @@ public function createUrlObject(array $options = array()) { /** * {@inheritdoc} */ - public function access(AccountInterface $account) { + public function access(AccountInterface $account = NULL) { return $this->getAccessManager()->checkNamedRoute($this->getRouteName(), $this->getRawParameters()->all(), $account); } diff --git a/core/lib/Drupal/Core/Routing/RouteMatchInterface.php b/core/lib/Drupal/Core/Routing/RouteMatchInterface.php index ad51db1..35944f8 100644 --- a/core/lib/Drupal/Core/Routing/RouteMatchInterface.php +++ b/core/lib/Drupal/Core/Routing/RouteMatchInterface.php @@ -87,12 +87,12 @@ public function getRawParameters(); * Determines whether the route is accessible or not. * * @param \Drupal\Core\Session\AccountInterface $account - * The current user. + * Run access checks for this account. Defaults to the current user. * * @return bool * Returns TRUE if the user has access to the route, otherwise FALSE. */ - public function access(AccountInterface $account); + public function access(AccountInterface $account = NULL); /** * Creates a Url object from this route match. diff --git a/core/lib/Drupal/Core/Url.php b/core/lib/Drupal/Core/Url.php index 368551e..e8eb800 100644 --- a/core/lib/Drupal/Core/Url.php +++ b/core/lib/Drupal/Core/Url.php @@ -388,6 +388,7 @@ public function toRenderArray() { '#route_name' => $this->getRouteName(), '#route_parameters' => $this->getRouteParameters(), '#options' => $this->getOptions(), + '#access_callback' => array(get_class(), 'renderAccess'), ); } } @@ -419,19 +420,32 @@ public function getInternalPath() { * Determines whether the route is accessible or not. * * @param \Drupal\Core\Session\AccountInterface $account - * The current user. + * Run access checks for this account. Defaults to the current user. * * @return bool * Returns TRUE if the user has access to the url, otherwise FALSE. */ - public function access(AccountInterface $account) { - return $this->getAccessManager()->checkNamedRoute($this->getRouteName(), $this->getRouteParameters(), $account); + public function access(AccountInterface $account = NULL) { + return $account->hasPermission('link to any page') || $this->accessManager()->checkNamedRoute($this->getRouteName(), $this->getRouteParameters(), $account); + } + + /** + * Checks a Url render element against applicable access check services. + * + * @param array $element + * A render element as returned from \Drupal\Core\Url::toRenderArray(). + * + * @return bool + * Returns TRUE if the current user has access to the url, otherwise FALSE. + */ + public static function renderAccess(array $element) { + return (new static($element['#route_name'], $element['#route_parameters'], $element['#options']))->access(); } /** * @return \Drupal\Core\Access\AccessManagerInterface */ - protected function getAccessManager() { + protected function accessManager() { if (!isset($this->accessManager)) { $this->accessManager = \Drupal::service('access_manager'); } diff --git a/core/modules/system/src/Plugin/Block/SystemBrandingBlock.php b/core/modules/system/src/Plugin/Block/SystemBrandingBlock.php index 77e63e1..d9abc4d 100644 --- a/core/modules/system/src/Plugin/Block/SystemBrandingBlock.php +++ b/core/modules/system/src/Plugin/Block/SystemBrandingBlock.php @@ -15,6 +15,7 @@ use Drupal\Core\Routing\UrlGeneratorInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Component\Utility\Xss; +use Drupal\Core\Url; use Symfony\Component\DependencyInjection\ContainerInterface; /** @@ -111,26 +112,26 @@ public function blockForm($form, FormStateInterface $form_state) { $theme = $form_state['block_theme']; // Get permissions. - $administer_themes_access = $this->currentUser->hasPermission('administer themes'); - $administer_site_configuration_access = $this->currentUser->hasPermission('administer site configuration'); - - if ($administer_themes_access) { - // Get paths to theme settings pages. - $appearance_settings_url = $this->urlGenerator->generateFromRoute('system.theme_settings'); - $theme_settings_url = $this->urlGenerator->generateFromRoute('system.theme_settings_theme', array('theme' => $theme)); + $url_system_theme_settings = new Url('system.theme_settings'); + $url_system_theme_settings_theme = new Url('system.theme_settings_theme', array('theme' => $theme)); + if ($url_system_theme_settings->access() && $url_system_theme_settings_theme->access()) { // Provide links to the Appearance Settings and Theme Settings pages // if the user has access to administer themes. - $site_logo_description = $this->t('Defined on the Appearance Settings or Theme Settings page.', array('@appearance' => $appearance_settings_url, '@theme' => $theme_settings_url)); + $site_logo_description = $this->t('Defined on the Appearance Settings or Theme Settings page.', array( + '@appearance' => $url_system_theme_settings->toString(), + '@theme' => $url_system_theme_settings_theme->toString(), + )); } else { // Explain that the user does not have access to the Appearance and Theme // Settings pages. $site_logo_description = $this->t('Defined on the Appearance or Theme Settings page. You do not have the appropriate permissions to change the site logo.'); } - if ($administer_site_configuration_access) { + $url_system_site_information_settings = new Url('system.site_information_settings'); + if ($url_system_site_information_settings->access()) { // Get paths to settings pages. - $site_information_url = $this->urlGenerator->generateFromRoute('system.site_information_settings'); + $site_information_url = $url_system_site_information_settings->toString(); // Provide link to Site Information page if the user has access to // administer site configuration.