Apakah Anda memiliki contoh panggilan balik akses hook_menu ()?

18

Saya telah mengunduh proyek contoh , tetapi dalam modul menu_example semua access callbackdiatur ke true.. sulit untuk memahami cara kerjanya.

Dalam contoh saya, entri meno saya harus terlihat pada node, tetapi hanya untuk peran yang memiliki izin untuk mengedit node sendiri.

Saya tidak dapat menemukan contoh verbose lebih sedikit dari panggilan balik akses.

Apakah ada yang punya?

Strae
sumber

Jawaban:

12

Sunting: Saya melewatkan bagian tentang izin "edit node sendiri", karena Anda tidak hanya harus memeriksa izin tetapi juga jika simpul itu milik pengguna saat ini. Saya telah memperbarui contoh saya di bawah ini tetapi saya meninggalkan penjelasan di atas seperti sebelumnya.

Apakah entri menu Anda di bawah node / nid (mis. Node / 1234 / something)? Maka Anda mungkin bahkan tidak memerlukan panggilan balik akses khusus.

Jika Anda menetapkan jalur menu Anda seperti contoh berikut, itu hanya akan memanggil panggilan balik akses (dan karenanya panggilan halaman Anda), jika Anda melihat simpul yang valid.

'node/%node/something'

Ini berarti bahwa ia akan memanggil node_load (1234) untuk contoh di atas dan hanya melanjutkan jika objek simpul yang valid dikembalikan. Jadi Anda dapat mendefinisikan izin Anda dengan argumen akses seperti biasa.

Yang mengatakan, menulis panggilan balik akses sangat sederhana. Ini hanya fungsi yang akan menerima argumen apa pun yang Anda tetapkan dalam argumen akses. Sebagai contoh, akses default callback adalah user_access () dan ketika Anda mendefinisikan akses argumen Anda suka 'access arguments' => array('a permission string'), itu akan mengakibatkan panggilan berikut: user_access('a permission string').

Jika Anda memiliki banyak argumen, argumen ini akan diteruskan sebagai argumen kedua, ketiga dan seterusnya untuk fungsi Anda. Untuk mengakses simpul yang sedang aktif, Anda dapat menggunakan menu_get_object () .

Jadi, Anda dapat menulis panggilan akses kembali seperti ini, tetapi sekali lagi, Anda mungkin tidak perlu membuatnya.

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

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

Alih-alih hardcoding string izin, Anda bisa meneruskannya sebagai argumen ke fungsi atau apa pun yang ingin Anda lakukan.

Berdir
sumber
tidak akan pernah bisa mencapai contoh terakhir: dengan $items['node/%node/edit']['access callback'] = 'admin_access_only'; dan $node = menu_get_object();dalam panggilan balik fn, $nodetidak pernah mengembalikan apa pun. Saya menggunakan $node = node_load(arg(1)); yang bekerja ... Penjelasan lebih lanjut akan sangat diterima
Kojo
19

Drupal sendiri merupakan contoh cara menulis kode.

Contoh yang lebih mudah adalah aggregator_menu () , yang berisi kode berikut.

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

Dalam hal ini, panggilan balik akses adalah default ( user_access () ), dan argumen akses adalah array yang berisi string untuk izin. Kode tidak dapat memeriksa lebih dari izin; jika izin untuk memeriksa dua, atau ketentuan untuk memeriksa bukan hanya izin, maka panggilan balik akses harus berbeda, termasuk yang khusus.

node_menu () mendefinisikan beberapa menu yang menggunakan panggilan balik akses yang berbeda dari yang standar. Fungsi ini berisi kode berikut.

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

Fungsi yang didefinisikan sebagai akses panggilan balik ( node_access () ) adalah sebagai berikut:

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

Ada tiga hal yang perlu diperhatikan:

  • Argumen yang dideklarasikan dengan "argumen akses" akan diteruskan ke fungsi dalam urutan yang sama; fungsi menggunakan parameter ketiga karena tidak digunakan hanya mengakses panggilan balik.
  • Fungsi kembali TRUEjika pengguna memiliki akses ke menu, dan FALSEjika pengguna tidak memiliki akses ke menu.
  • Panggilan balik akses juga dapat digunakan ketika menu harus ditampilkan hanya dalam keadaan tertentu.
kiamlaluno
sumber
Ketika mendeklarasikan access callbackfungsi kustom , tampaknya itu harus hidup dalam .modulefile Anda , karena Drupal sepertinya tidak dapat menemukannya dalam filedeklarasi (setidaknya untuk saya).
tyler.frankenstein