Bạn có một ví dụ về gọi lại truy cập hook_menu () không?


18

Tôi đã tải xuống dự án ví dụ , nhưng trong mô-đun menu_example tất cả access callbackđược đặt thành true.. khó hiểu làm thế nào nó hoạt động.

Trong ví dụ của tôi, mục nhập meno của tôi sẽ hiển thị trên các nút, nhưng chỉ cho các vai trò có quyền chỉnh sửa các nút của riêng mình.

Tôi không thể tìm thấy một ví dụ dài hơn một chút về một cuộc gọi lại truy cập.

Có ai có một cái không?

Câu trả lời:


12

Chỉnh sửa: Tôi đã bỏ lỡ phần về quyền "chỉnh sửa nút riêng", bởi vì sau đó bạn không chỉ phải kiểm tra quyền mà còn nếu nút đó thuộc về người dùng hiện tại. Tôi đã cập nhật ví dụ của mình bên dưới nhưng tôi để lại lời giải thích ở trên.

Là mục trình đơn của bạn bên dưới nút / nid (ví dụ: nút / 1234 / cái gì đó)? Sau đó, bạn có thể thậm chí không cần một cuộc gọi lại truy cập tùy chỉnh.

Nếu bạn xác định đường dẫn menu của mình như ví dụ sau, nó sẽ chỉ gọi lại cuộc gọi lại truy cập (và do đó gọi lại trang của bạn), nếu bạn đang xem một nút hợp lệ.

'node/%node/something'

Điều này có nghĩa là nó sẽ gọi node_load (1234) cho ví dụ trên và chỉ tiếp tục nếu một đối tượng nút hợp lệ được trả về. Vì vậy, bạn có thể xác định sự cho phép của bạn với các đối số truy cập như bình thường.

Điều đó nói rằng, viết một cuộc gọi lại truy cập thực sự đơn giản. Đây chỉ là một hàm sẽ nhận bất kỳ đối số nào bạn đã xác định trong các đối số truy cập. Ví dụ: cuộc gọi lại truy cập mặc định là user_access () và khi bạn xác định các đối số truy cập của mình như thế nào 'access arguments' => array('a permission string'), nó sẽ dẫn đến cuộc gọi sau : user_access('a permission string').

Nếu bạn có nhiều đối số, chúng sẽ được chuyển thành đối số thứ hai, thứ ba và cứ thế đối với hàm của bạn. Để truy cập nút hiện đang hoạt động, bạn có thể sử dụng menu_get_object () .

Vì vậy, bạn có thể viết cuộc gọi lại truy cập của mình như thế này, nhưng một lần nữa, bạn thậm chí có thể không cần phải tạo một cuộc gọi lại.

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

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

Thay vì mã hóa chuỗi quyền, bạn có thể chuyển nó dưới dạng đối số cho hàm hoặc bất cứ điều gì bạn muốn làm.


không bao giờ có thể đạt được ví dụ cuối cùng: với $items['node/%node/edit']['access callback'] = 'admin_access_only'; $node = menu_get_object();trong fn gọi lại, $nodekhông bao giờ trả lại bất cứ điều gì. Tôi đã sử dụng thay vì $node = node_load(arg(1)); nó hoạt động ... Giải thích thêm sẽ thực sự được hoan nghênh
Kojo

19

Drupal là một ví dụ về cách viết mã.

Ví dụ dễ dàng hơn là gộpator_menu () , chứa mã sau đây.

  $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',
  );

Trong trường hợp này, cuộc gọi lại truy cập là mặc định ( user_access () ) và các đối số truy cập là một mảng chứa chuỗi cho phép. Mã không thể kiểm tra nhiều hơn sự cho phép; nếu các quyền để kiểm tra là hai hoặc các điều kiện để kiểm tra không chỉ là quyền, thì cuộc gọi lại truy cập phải là một quyền khác, bao gồm một quyền tùy chỉnh.

node_menu () xác định một số menu sử dụng hàm gọi lại truy cập khác với menu mặc định. Hàm chứa mã sau đây.

  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',
    );
  }

Hàm được định nghĩa là gọi lại truy cập ( node_access () ) là hàm sau:

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;
}

Có ba điểm cần chú ý:

  • Các đối số được khai báo với "đối số truy cập" sẽ được chuyển đến hàm theo cùng một thứ tự; hàm sử dụng tham số thứ ba vì nó không được sử dụng chỉ truy cập gọi lại.
  • Hàm trả về TRUEnếu người dùng có quyền truy cập vào menu và FALSEnếu người dùng không có quyền truy cập vào menu.
  • Một cuộc gọi lại truy cập cũng có thể được sử dụng khi một menu chỉ được hiển thị trong các trường hợp cụ thể.

Khi khai báo một access callbackchức năng tùy chỉnh , có vẻ như nó phải nằm trong .moduletệp của bạn , bởi vì Drupal dường như không thể tìm thấy nó trong filekhai báo (ít nhất là đối với tôi).
tyler.frankenstein
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.