Чи є у вас приклад зворотного дзвінка з доступом до вибору ho_menu ()?


18

Я завантажив проект прикладів , але в модулі menu_example все access callbackвстановлено на true.. важко зрозуміти, як це працює.

У моєму прикладі мінопис повинен бути видно на вузлах, але лише для ролей, які мають дозволи редагувати власні вузли.

Я не можу знайти приклад дещо докладнішого зворотного виклику доступу.

У когось є?

Відповіді:


12

Редагувати: я пропустив частину про дозвіл "редагувати власний вузол", тому що тоді ви повинні перевірити не лише дозвіл, але й якщо цей вузол належить поточному користувачеві. Я оновив приклад нижче, але я залишаю вище пояснення таким, яким воно було.

Чи є запис у меню нижче node / nid (наприклад, node / 1234 / something)? Тоді вам, мабуть, навіть не потрібен спеціальний зворотний дзвінок доступу.

Якщо ви визначите шлях свого меню, як у наведеному нижче прикладі, він буде викликати лише зворотний дзвінок доступу (а отже, і зворотній дзвінок на сторінці), якщо ви переглядаєте дійсний вузол.

'node/%node/something'

Це означає, що він буде викликати node_load (1234) для наведеного вище прикладу і продовжуватиметься лише у разі повернення дійсного об'єкта вузла. Таким чином, ви можете визначити свій дозвіл за допомогою аргументів доступу, як зазвичай.

Однак, написання зворотного дзвінка доступу дуже просто. Це просто функція, яка отримуватиме всі аргументи, які ви визначили в аргументах доступу. Наприклад, виклик доступу по замовчуванням user_access () і при визначенні ваших аргументів доступу подобаються 'access arguments' => array('a permission string'), то це призведе до наступного виклику: user_access('a permission string').

Якщо у вас є кілька аргументів, вони будуть передані як другий, третій і так далі аргумент вашій функції. Для доступу до поточно активного вузла можна скористатися menu_get_object () .

Таким чином, ви можете написати такий зворотний дзвінок доступу таким чином, але знову ж таки, можливо, вам навіть не знадобиться його створювати.

function yourmodule_access_check() {
  global $user;
  $node = menu_get_object();

  return $node && $node->uid == $user->uid && user_access('edit own ' . $node->type . ' content');
}

Замість жорсткого кодування рядка дозволів, ви можете передавати його як аргумент функції або що завгодно.


ніколи не міг досягти останнього прикладу: за допомогою $items['node/%node/edit']['access callback'] = 'admin_access_only'; та $node = menu_get_object();в зворотному звороті fn, $nodeнічого не повертав. Я використовував замість цього, $node = node_load(arg(1)); який працював ... Подальші пояснення були б дуже вітаються
Kojo

19

Drupal - це сам приклад того, як писати код.

Найпростіший приклад - agregator_menu () , який містить наступний код.

  $items['admin/config/services/aggregator'] = array(
    'title' => 'Feed aggregator', 
    'description' => "Configure which content your site aggregates from other sites, how often it polls them, and how they're categorized.", 
    'page callback' => 'aggregator_admin_overview', 
    'access arguments' => array('administer news feeds'), 
    'weight' => 10, 
    'file' => 'aggregator.admin.inc',
  );
  $items['admin/config/services/aggregator/add/feed'] = array(
    'title' => 'Add feed', 
    'page callback' => 'drupal_get_form', 
    'page arguments' => array('aggregator_form_feed'), 
    'access arguments' => array('administer news feeds'), 
    'type' => MENU_LOCAL_ACTION, 
    'file' => 'aggregator.admin.inc',
  );

У цьому випадку зворотний виклик доступу є типовим ( user_access () ), а аргументи доступу - це масив, що містить рядок для дозволу. Код не може перевірити більше, ніж дозвіл; якщо дозволів на перевірку два, або умови для перевірки - це не лише дозволи, то зворотний виклик доступу повинен бути іншим, включаючи спеціальний.

node_menu () визначає деякі меню, які використовують зворотний дзвінок доступу, відмінний від типового. Функція містить наступний код.

  foreach (node_type_get_types() as $type) {
    $type_url_str = str_replace('_', '-', $type->type);
    $items['node/add/' . $type_url_str] = array(
      'title' => $type->name, 
      'title callback' => 'check_plain', 
      'page callback' => 'node_add', 
      'page arguments' => array($type->type), 
      'access callback' => 'node_access', 
      'access arguments' => array('create', $type->type), 
      'description' => $type->description, 
      'file' => 'node.pages.inc',
    );
  }

Функція, яка визначена як зворотний виклик доступу ( node_access () ), є наступною:

function node_access($op, $node, $account = NULL) {
  $rights = &drupal_static(__FUNCTION__, array());

  if (!$node || !in_array($op, array('view', 'update', 'delete', 'create'), TRUE)) {
    // If there was no node to check against, or the $op was not one of the
    // supported ones, we return access denied.
    return FALSE;
  }
  // If no user object is supplied, the access check is for the current user.
  if (empty($account)) {
    $account = $GLOBALS['user'];
  }

  // $node may be either an object or a node type. Since node types cannot be
  // an integer, use either nid or type as the static cache id.

  $cid = is_object($node) ? $node->nid : $node;

  // If we've already checked access for this node, user and op, return from
  // cache.
  if (isset($rights[$account->uid][$cid][$op])) {
    return $rights[$account->uid][$cid][$op];
  }

  if (user_access('bypass node access', $account)) {
    $rights[$account->uid][$cid][$op] = TRUE;
    return TRUE;
  }
  if (!user_access('access content', $account)) {
    $rights[$account->uid][$cid][$op] = FALSE;
    return FALSE;
  }

  // We grant access to the node if both of the following conditions are met:
  // - No modules say to deny access.
  // - At least one module says to grant access.
  // If no module specified either allow or deny, we fall back to the
  // node_access table.
  $access = module_invoke_all('node_access', $node, $op, $account);
  if (in_array(NODE_ACCESS_DENY, $access, TRUE)) {
    $rights[$account->uid][$cid][$op] = FALSE;
    return FALSE;
  }
  elseif (in_array(NODE_ACCESS_ALLOW, $access, TRUE)) {
    $rights[$account->uid][$cid][$op] = TRUE;
    return TRUE;
  }

  // Check if authors can view their own unpublished nodes.
  if ($op == 'view' && !$node->status && user_access('view own unpublished content', $account) && $account->uid == $node->uid && $account->uid != 0) {
    $rights[$account->uid][$cid][$op] = TRUE;
    return TRUE;
  }

  // If the module did not override the access rights, use those set in the
  // node_access table.
  if ($op != 'create' && $node->nid) {
    if (module_implements('node_grants')) {
      $query = db_select('node_access');
      $query->addExpression('1');
      $query->condition('grant_' . $op, 1, '>=');
      $nids = db_or()->condition('nid', $node->nid);
      if ($node->status) {
        $nids->condition('nid', 0);
      }
      $query->condition($nids);
      $query->range(0, 1);

      $grants = db_or();
      foreach (node_access_grants($op, $account) as $realm => $gids) {
        foreach ($gids as $gid) {
          $grants->condition(db_and()
            ->condition('gid', $gid)
            ->condition('realm', $realm)
          );
        }
      }
      if (count($grants) > 0) {
        $query->condition($grants);
      }
      $result =  (bool) $query
        ->execute()
        ->fetchField();
      $rights[$account->uid][$cid][$op] = $result;
      return $result;
    }
    elseif (is_object($node) && $op == 'view' && $node->status) {
      // If no modules implement hook_node_grants(), the default behavior is to
      // allow all users to view published nodes, so reflect that here.
      $rights[$account->uid][$cid][$op] = TRUE;
      return TRUE;
    }
  }

  return FALSE;
}

Потрібно помітити три моменти:

  • Аргументи, оголошені з "аргументами доступу", будуть передані функції у тому ж порядку; функція використовує третій параметр, оскільки не використовується тільки зворотний виклик доступу.
  • Функція повертається, TRUEякщо користувач має доступ до меню і FALSEякщо користувач не має доступу до меню.
  • Зворотний виклик доступу також може бути використаний, коли меню має відображатися лише в конкретних обставинах.

При оголошенні користувацької access callbackфункції, здається, вона повинна жити у вашому .moduleфайлі, тому що Drupal, здається, не може знайти її в fileдекларації (принаймні для мене).
tyler.frankenstein
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.