[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/sites/all/modules/menu_per_role/ -> menu_per_role.module (source)

   1  <?php
   2  // $Id: menu_per_role.module,v 1.6.2.14 2010/10/19 08:53:15 alexiswilke Exp $
   3  
   4  /**
   5   * @file
   6   * Allows restricting access to menu items per role
   7   */
   8  
   9  /*
  10   * Permission for who can access the menu per role forms.
  11   */
  12  function menu_per_role_perm() {
  13    return array('administer menu_per_role');
  14  }
  15  
  16  /*
  17   * Determines access for a give menu item id
  18   *
  19   * \warning
  20   * This function is NOT called automatically up to version 6.10.
  21   * You need to apply the patch provided in this module so it
  22   * actually works in older versions. See file:
  23   *
  24   * drupal-6.6-menu_per_role.patch
  25   *
  26   * \param[in] $mlid The menu item identifier
  27   *
  28   * \return NULL if this module does not forbid the viewing of this menu item,
  29   * FALSE otherwise
  30   */
  31  function _menu_per_role_access($mlid) {
  32    global $user;
  33  
  34    if ($user->uid == 1 || empty($mlid) || user_access('administer menu_per_role')) {
  35      // Admins do not lose access whatever this module would otherwise say
  36      // Also, if the menu link identifier is not set, ignore the request
  37      return NULL;
  38    }
  39  
  40    // check whether this role has visibility access (must be present)
  41    $rids = _menu_per_role_get_roles($mlid, 0);
  42    if (!empty($rids) && count(array_intersect($rids, array_keys($user->roles))) == 0) {
  43      // not permitted by the rids...
  44      return FALSE;
  45    }
  46  
  47    // check whether this role has visibility access (must not be present)
  48    $hrids = _menu_per_role_get_roles($mlid, 1);
  49    if (!empty($hrids) && count(array_intersect($hrids, array_keys($user->roles))) > 0) {
  50      // not permitted by the hrids...
  51      return FALSE;
  52    }
  53  
  54    // this module is not preventing user from seeing this menu entry
  55    return NULL;
  56  }
  57  
  58  
  59  /*
  60   * Implementation of hook_form_alter().
  61   */
  62  function menu_per_role_form_alter(&$form, $form_state, $form_id) {
  63    if (!user_access('administer menu_per_role')) {
  64      return;
  65    }
  66  
  67    if ($form_id == 'menu_edit_item') {
  68      $f = &$form;
  69      $form['submit']['#weight'] = 10;
  70    }
  71    if (isset($form['#node']) && $form['#node']->type .'_node_form' == $form_id && isset($form['menu'])) {
  72      $f = &$form['menu'];
  73    }
  74    if (isset($f)) {
  75      $default_value_roles = $form['menu']['mlid']['#value']
  76        ? _menu_per_role_get_roles($form['menu']['mlid']['#value'], 0)
  77        : array();
  78      $default_value_hide_from_roles = $form['menu']['mlid']['#value']
  79        ? _menu_per_role_get_roles($form['menu']['mlid']['#value'], 1)
  80        : array();
  81      $f['menu_per_role'] = array(
  82        '#type' => 'fieldset',
  83        '#title' => t('Restrict item visibility'),
  84        '#collapsible' => TRUE,
  85        '#collapsed' => (count($default_value_roles) + count($default_value_hide_from_roles)) == 0,
  86        '#weight' => 5,
  87        '#description' => t('Check to know whether the user has proper visibility permissions to see this menu item. Note that both checks are always performed.'),
  88      );
  89      $f['menu_per_role']['menu_per_role_roles'] = array(
  90        '#type' => 'checkboxes',
  91        '#title' => t('Show menu item only to selected roles'),
  92        '#options' => user_roles(),
  93        '#default_value' => $default_value_roles,
  94        '#description' => t('Check no role to leave the access permission to the default. A user who is not part of at least one of the selected roles will not see this menu item.'),
  95      );
  96      $f['menu_per_role']['menu_per_role_hide_from_roles'] = array(
  97        '#type' => 'checkboxes',
  98        '#title' => t('Hide menu item from selected roles'),
  99        '#options' => user_roles(),
 100        '#default_value' => $default_value_hide_from_roles,
 101        '#description' => t('Check no role to leave the access permission to the default. A user who is part of any one of these roles will not see this menu item.'),
 102      );
 103      $form['#submit'][] = '_menu_per_role_form_submit';
 104    }
 105  }
 106  
 107  
 108  /*
 109   * Internal function to save the data in our table.
 110   */
 111  function _menu_per_role_form_submit($form, &$form_state) {
 112    global $db_type;
 113  
 114    if ($form_state['submitted']) {
 115      $mlid = $form_state['values']['menu']['mlid'];
 116      if ($mlid) {
 117        // hide but to those roles
 118        $rids = array();
 119        $roles = isset($form_state['values']['menu_per_role_roles']) ?
 120                       $form_state['values']['menu_per_role_roles']
 121                       : $form_state['values']['menu']['menu_per_role']['menu_per_role_roles'];
 122        foreach ($roles as $rid => $checked) {
 123          if ($checked) {
 124            $rids[] = $rid;
 125          }
 126        }
 127        $rids_str = implode(',', $rids);
 128        // show but to those roles
 129        $hrids = array();
 130        $roles = isset($form_state['values']['menu_per_role_hide_from_roles']) ?
 131                       $form_state['values']['menu_per_role_hide_from_roles']
 132                       : $form_state['values']['menu']['menu_per_role']['menu_per_role_hide_from_roles'];
 133        foreach ($roles as $rid => $checked) {
 134          if ($checked) {
 135            $hrids[] = $rid;
 136          }
 137        }
 138        $hrids_str = implode(',', $hrids);
 139        // save in our table
 140        //db_lock_table('menu_per_role');
 141        if ($rids_str || $hrids_str) {
 142          db_query("UPDATE {menu_per_role} SET rids = '%s', hrids = '%s' WHERE mlid = %d", $rids_str, $hrids_str, $mlid);
 143          if (db_affected_rows() == 0) {
 144            // if nothing was affected, the row did not exist yet
 145            // (although with MySQL this may fail because db_affected_rows() may only return
 146            // rows that have been changed instead of the # of rows that match the WHERE clause.)
 147            if ($db_type != 'pgsql') {
 148              $insert = !db_result(db_query("SELECT 1 FROM {menu_per_role} WHERE mlid = %d", $mlid));
 149            }
 150            else {
 151              $insert = TRUE;
 152            }
 153            if ($insert) {
 154              db_query("INSERT INTO {menu_per_role} (mlid, rids, hrids) VALUES (%d, '%s', '%s')", $mlid, $rids_str, $hrids_str);
 155            }
 156          }
 157        }
 158        else {
 159          // we don't need to save it when empty, instead, remove that completely
 160          db_query("DELETE FROM {menu_per_role} WHERE mlid = %d", $mlid);
 161        }
 162        //db_unlock_tables();
 163        // reset the menus
 164        menu_cache_clear_all();
 165      }
 166      else if (isset($form_state['values']['menu_per_role_roles'])) {
 167        drupal_set_message(t('The menu link identifier was not defined on Submit in <b>Menu per Role</b>. You are most certainly adding a new menu item. For this feature to work when adding a menu item, you must apply the patch defined in <a href="http://drupal.org/node/326210" target="_blank">node #326210</a>. That patch is included in this module for that purpose.'), 'error');
 168      }
 169    }
 170  }
 171  
 172  
 173  /*
 174   * When the menu item is being submitted, the core also calls the
 175   * hook_menu_link_alter(&$item, $menu);
 176   *
 177   * By catching that function, we can set the special alter option
 178   * that will let our module receive a call whenever the menu is
 179   * ready for display but was not yet displayed. At that time we
 180   * can mark the access as FALSE.
 181   */
 182  function menu_per_role_menu_link_alter(&$item, $menu)
 183  {
 184    // TODO: The following marks ALL menu items as alterable.
 185    //       Any time a menu item is saved, it is marked as
 186    //       such. I have no clue, at this time, of a way to
 187    //       avoid such nonsense. Hints welcome!
 188    $item['options']['alter'] = TRUE;
 189  }
 190  
 191  
 192  /*
 193   * Before a menu item gets displayed, the core calls the hook:
 194   * hook_translated_menu_link_alter(&$item, $map);
 195   * (but only if $item['options']['alter'] is TRUE)
 196   *
 197   * This function is used to alter the access right based on
 198   * the role definition of the item.
 199   */
 200  function menu_per_role_translated_menu_link_alter(&$item, $map)
 201  {
 202    // avoid checking the role if the item access is already false
 203    if ($item['access'] && _menu_per_role_access($item['mlid']) === FALSE) {
 204      $item['access'] = FALSE;
 205    }
 206  }
 207  
 208  
 209  /**
 210   * Gets all roles with access to the specified menu item
 211   * No roles mean that access is granted by this module.
 212   *
 213   * $show set to 0 for show to roles, 1 for hide from roles
 214   */
 215  function _menu_per_role_get_roles($mlid, $show) {
 216    static $menu_per_role;
 217  
 218    if (!isset($menu_per_role)) {
 219      // read all the data ONCE, it is likely very small
 220      $menu_per_role = array();
 221      $result = db_query("SELECT * FROM {menu_per_role}");
 222      while ($row = db_fetch_object($result)) {
 223        if ($row->rids || $row->hrids) {
 224          $menu_per_role[$row->mlid][0] = explode(',', $row->rids);
 225          $menu_per_role[$row->mlid][1] = explode(',', $row->hrids);
 226        }
 227      }
 228    }
 229  
 230    if (isset($menu_per_role[$mlid])) {
 231      return $menu_per_role[$mlid][$show];
 232    }
 233  
 234    // not defined, everyone has the right to use it
 235    return array();
 236  }
 237  
 238  // vim: ts=2 sw=2 et syntax=php


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7