You are here

menu_per_role.module in Menu Per Role 8

Same filename and directory in other branches
  1. 5 menu_per_role.module
  2. 6 menu_per_role.module
  3. 7 menu_per_role.module

File

menu_per_role.module
View source
<?php

/**
 * @file
 * Allows restricting access to menu items per role.
 */
declare (strict_types=1);
use Drupal\Core\Entity\EntityTypeInterface;
use Drupal\Core\Field\BaseFieldDefinition;
use Drupal\Core\Field\FieldStorageDefinitionInterface;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Routing\RouteMatchInterface;
use Drupal\menu_per_role\Form\MenuPerRoleAdminSettings;

/**
 * Implements hook_help().
 */
function menu_per_role_help($route_name, RouteMatchInterface $route_match) {
  switch ($route_name) {
    case 'help.page.menu_per_role':
      $output = '';
      $output .= '<h3>' . t('About') . '</h3>';
      $output .= '<p>' . t('The Menu Per Role module allows you to restrict access of menu items per roles.') . '</p>';
      $output .= '<h3>' . t('Limitation') . '</h3>';
      $output .= '<p>' . t("Menu Per role only acts on content menu link (content entity). Menu links provided by configuration (example: Views) or by *.links.menu.yml files can't be managed by this module.") . '</p>';
      $output .= '<h3>' . t('Configuration') . '</h3>';
      $output .= '<p>' . t('Just activate the Menu Per Role module and edit a menu item as usual. There will be one or two fieldsets, depending on the configuration of the module, that allows you to restrict access by role.') . '</p>';
      $output .= '<p>' . t("If you don't check any roles the default access permissions will be kept. Otherwise the module will additionally restrict access to the chosen user roles.") . '</p>';
      return $output;
  }
}

/**
 * Implements hook_entity_base_field_info().
 *
 * Adds two fields to menu_link_content, so access restrictions can be set.
 */
function menu_per_role_entity_base_field_info(EntityTypeInterface $entity_type) {
  $fields = [];
  if ($entity_type
    ->id() != 'menu_link_content') {
    return $fields;
  }
  $fields['menu_per_role__show_role'] = BaseFieldDefinition::create('entity_reference')
    ->setName('menu_per_role__show_role')
    ->setTargetEntityTypeId('menu_link_content')
    ->setLabel(t('Roles able to see the menu link'))
    ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED)
    ->setSetting('target_type', 'user_role')
    ->setDisplayOptions('form', [
    'type' => 'options_buttons',
    'weight' => 0,
  ]);
  $fields['menu_per_role__hide_role'] = BaseFieldDefinition::create('entity_reference')
    ->setName('menu_per_role__hide_role')
    ->setTargetEntityTypeId('menu_link_content')
    ->setLabel(t('Roles not able see the menu link.'))
    ->setCardinality(FieldStorageDefinitionInterface::CARDINALITY_UNLIMITED)
    ->setSetting('target_type', 'user_role')
    ->setDisplayOptions('form', [
    'type' => 'options_buttons',
    'weight' => 0,
  ]);
  return $fields;
}

/**
 * Implements hook_form_FORM_ID_alter().
 *
 * Alter menu_link_content fields to hide extra fields on content.
 */
function menu_per_role_form_menu_link_content_form_alter(&$form, FormStateInterface $form_state, $form_id) {
  $config = \Drupal::config('menu_per_role.settings');

  // Get config properties.
  $hide_show_mode = !is_null($config
    ->get('hide_show')) ? $config
    ->get('hide_show') : MenuPerRoleAdminSettings::MODE_DISPLAY_BOTH;
  $hide_on_content_mode = !is_null($config
    ->get('hide_on_content')) ? $config
    ->get('hide_on_content') : MenuPerRoleAdminSettings::MODE_DISPLAY_ON_CONTENT_ALWAYS;

  // Check if content mode setting applies, and if fields should be hidden.
  $is_content = FALSE;
  if ($hide_on_content_mode != MenuPerRoleAdminSettings::MODE_DISPLAY_ON_CONTENT_ALWAYS) {

    /** @var \Drupal\menu_link_content\Form\MenuLinkContentForm $form_obj */
    $form_obj = $form_state
      ->getFormObject();

    /** @var \Drupal\menu_link_content\MenuLinkContentInterface $menu_link */
    $menu_link = $form_obj
      ->getEntity();
    if (!$menu_link
      ->isNew()) {
      $link_url = $menu_link
        ->getUrlObject();
      if ($link_url
        ->isRouted()) {
        $route_params = $link_url
          ->getRouteParameters();
        if (array_key_exists('node', $route_params)) {

          // Nodes routes will contain a 'node' with 'nid' value.
          if ($hide_on_content_mode == MenuPerRoleAdminSettings::MODE_DISPLAY_ON_CONTENT_NO_NODE_ACCESS) {

            // For the existence of any hook_node_grants() implementations.
            $is_content = !empty(\Drupal::moduleHandler()
              ->getImplementations('node_grants'));
          }

          // If false, then check if the setting is display never.
          $is_content = $is_content || $hide_on_content_mode == MenuPerRoleAdminSettings::MODE_DISPLAY_ON_CONTENT_NEVER;
        }
      }
    }
  }

  // Check for the display of each field.
  $display_show_roles = !$is_content && $hide_show_mode != MenuPerRoleAdminSettings::MODE_DISPLAY_ONLY_HIDE;
  $display_hide_roles = !$is_content && $hide_show_mode != MenuPerRoleAdminSettings::MODE_DISPLAY_ONLY_SHOW;

  // Hide fields if they need to be.
  if (!$display_show_roles) {
    $form['menu_per_role__show_role']['#access'] = FALSE;
  }
  if (!$display_hide_roles) {
    $form['menu_per_role__hide_role']['#access'] = FALSE;
  }
}