Updated to Drupal 8.5. Core Media not yet in use.
[yaffs-website] / web / modules / contrib / admin_toolbar / admin_toolbar_links_access_filter / admin_toolbar_links_access_filter.module
diff --git a/web/modules/contrib/admin_toolbar/admin_toolbar_links_access_filter/admin_toolbar_links_access_filter.module b/web/modules/contrib/admin_toolbar/admin_toolbar_links_access_filter/admin_toolbar_links_access_filter.module
new file mode 100644 (file)
index 0000000..7b44768
--- /dev/null
@@ -0,0 +1,193 @@
+<?php
+
+/**
+ * @file
+ * This module don't show menu links that you don't have access permission for.
+ */
+
+use Drupal\Core\Session\AccountInterface;
+use Drupal\Core\Url;
+use Drupal\user\Entity\Role;
+use Symfony\Component\Routing\Exception\RouteNotFoundException;
+use Drupal\Core\Routing\RouteMatchInterface;
+
+/**
+ * Implements hook_help().
+ */
+function admin_toolbar_links_access_filter_help($route_name, RouteMatchInterface $route_match) {
+  switch ($route_name) {
+    // Main module help.
+    case 'help.page.admin_toolbar_links_access_filter':
+      $output = '';
+      $output .= '<h3>' . t('About') . '</h3>';
+      $output .= '<p>' . t("The Admin Toolbar Links Access Filter module Provides a workaround for the common problem that users with <em>Use the administration pages and help</em> permission see menu links they don't have access permission for. Once the issue <a href='@url'>Hide empty admin categories</a> be solved, this module will be deprecated.", ['@url' => Url::fromUri('https://www.drupal.org/node/296693')->toString()]) . '</p>';
+
+      return $output;
+  }
+}
+
+/**
+ * Implements hook_preprocess_menu().
+ *
+ * Hides links from admin menu, if user doesn't have access rights.
+ */
+function admin_toolbar_links_access_filter_preprocess_menu(&$variables) {
+  if (empty($variables['items'])) {
+    // Additional empty check to prevent exotic situations, where the preprocess
+    // function is entered even without items.
+    // @see https://www.drupal.org/node/2833885
+    return;
+  }
+  // Ensure that menu_name exists.
+  if (!isset($variables['menu_name'])) {
+    // In rare cases (for unknown reasons) menu_name may not be set.
+    // As fallback, we can fetch it from the first menu item.
+    $first_link = reset($variables['items']);
+    /** @var Drupal\Core\Menu\MenuLinkDefault $original_link */
+    // Fetch the menu_name from the original link.
+    $original_link = $first_link['original_link'];
+    $variables['menu_name'] = $original_link->getMenuName();
+  }
+  if ($variables['menu_name'] == 'admin') {
+    if (!admin_toolbar_links_access_filter_user_has_admin_role($variables['user'])) {
+      admin_toolbar_links_access_filter_filter_non_accessible_links($variables['items']);
+    }
+  }
+}
+
+/**
+ * Hides links from admin menu, if user doesn't have access rights.
+ */
+function admin_toolbar_links_access_filter_filter_non_accessible_links(array &$items) {
+  foreach ($items as $route => &$item) {
+    $route_name = $route;
+    $route_params = [];
+    if (!empty($item['original_link'])) {
+      /** @var \Drupal\Core\Menu\MenuLinkBase $original_link */
+      $original_link = $item['original_link'];
+      if ($original_link->getUrlObject()->isExternal()) {
+        // Do not filter external URL at all.
+        continue;
+      }
+      $route_name = $original_link->getRouteName();
+      $route_params = $original_link->getRouteParameters();
+    }
+
+    // Check, if user has access rights to the route.
+    if (!\Drupal::accessManager()->checkNamedRoute($route_name, $route_params)) {
+      unset($items[$route]);
+    }
+    else {
+      if (!empty($items[$route]['below'])) {
+        // Recursively call this function for the child items.
+        admin_toolbar_links_access_filter_filter_non_accessible_links($items[$route]['below']);
+      }
+      if (empty($items[$route]['below']) && \Drupal::moduleHandler()->moduleExists('admin_toolbar')) {
+
+        // Every child item has been cleared out.
+        // Now check, if the given route represents an overview page only,
+        // without having functionality on its own. In this case, we can safely
+        // unset this item, as there aren't any children left.
+        // This assumption is only valid, when the admin_toolbar module is
+        // installed because otherwise we won't have child items at all.
+        if (admin_toolbar_links_access_filter_is_overview_page($route)) {
+          unset($items[$route]);
+        }
+        else {
+          // Let's remove the expanded flag.
+          $items[$route]['is_expanded'] = FALSE;
+        }
+      }
+    }
+  }
+}
+
+/**
+ * Implements template_preprocess_admin_block_content().
+ */
+function admin_toolbar_links_access_filter_admin_block_content(&$variables) {
+  if (!admin_toolbar_links_access_filter_user_has_admin_role($variables['user'])) {
+    foreach ($variables['content'] as $key => &$item) {
+      if (isset($item['url']) && $item['url'] instanceof Url) {
+        /* @var \Drupal\Core\Url $url */
+        $url = $item['url'];
+        if ($url->access()) {
+          continue;
+        }
+        unset($variables['content'][$key]);
+      }
+
+      // The key is structured in the form: "ID title route",
+      // concatenated with spaces.
+      $key_parts = explode(' ', $key);
+      $route = end($key_parts);
+
+      // Special handling for Views pages, as they are not defined
+      // system routes.
+      // @TODO check the permission for Views + find a generic way for similar
+      // cases. Best way would be to get the link entity somehow to properly
+      // check permissions.
+      if (strpos($route, 'views_view:') === 0) {
+        continue;
+      }
+
+      // Check, if user has access rights to the route.
+      if (!\Drupal::accessManager()->checkNamedRoute($route)) {
+        unset($variables['content'][$key]);
+      }
+    }
+  }
+}
+
+/**
+ * Checks if the given route name is an overview page.
+ *
+ * Checks if the given route name matches a pure (admin) overview page that can
+ * be skipped, if there are no child items set. The typical example are routes
+ * having the SystemController::systemAdminMenuBlockPage() function as their
+ * controller callback set.
+ *
+ * @param string $route_name
+ *   The route name to check.
+ *
+ * @return bool
+ *   TRUE, if the given route name matches a pure admin overview page route,
+ *   FALSE otherwise.
+ */
+function admin_toolbar_links_access_filter_is_overview_page($route_name) {
+  // @var \Drupal\Core\Routing\RouteProviderInterface $route_provider.
+  $route_provider = \Drupal::service('router.route_provider');
+  $overview_page_controllers = [
+    '\Drupal\system\Controller\AdminController::index',
+    '\Drupal\system\Controller\SystemController::overview',
+    '\Drupal\system\Controller\SystemController::systemAdminMenuBlockPage',
+  ];
+  try {
+    $route = $route_provider->getRouteByName($route_name);
+    $controller = $route->getDefault('_controller');
+    return !empty($controller) && in_array($controller, $overview_page_controllers);
+  }
+  catch (RouteNotFoundException $ex) {
+
+  }
+  return FALSE;
+}
+
+/**
+ * Checks, if the given user has admin rights.
+ *
+ * @param \Drupal\Core\Session\AccountInterface $account
+ *   The account to check.
+ *
+ * @return bool
+ *   TRUE, if the given user account has at least one role with admin rights
+ *   assigned, FALSE otherwise.
+ */
+function admin_toolbar_links_access_filter_user_has_admin_role(AccountInterface $account) {
+  foreach ($account->getRoles() as $role_id) {
+    if (Role::load($role_id)->isAdmin()) {
+      return TRUE;
+    }
+  }
+  return FALSE;
+}