Hook_menu () erişim geri aramasının bir örneği var mı?


18

Ben indirdiğiniz örnekler proje ama menu_example modülü tüm access callbackayarlanır truenasıl çalıştığını anlamak zor ...

Örneğimde, meno girdim düğümlerde görünür olmalı, ancak yalnızca kendi düğümlerini düzenleme izni olan roller için olmalıdır.

Ben bir erişim geri arama biraz daha ayrıntılı bir örnek bulamıyorum.

Biri var mı?

Yanıtlar:


12

Düzenleme: "Kendi düğümü düzenle" izni ile ilgili bölümü kaçırdım, çünkü o zaman sadece izni kontrol etmekle kalmaz, aynı zamanda bu düğüm geçerli kullanıcıya aitse. Aşağıdaki örneğimi güncelledim ancak yukarıdaki açıklamayı olduğu gibi bırakıyorum.

Menü girişiniz düğüm / nid'in altında mı (örn. Düğüm / 1234 / bir şey)? O zaman muhtemelen özel erişim geri aramasına ihtiyacınız yoktur.

Menü yolunuzu aşağıdaki örnek gibi tanımlarsanız, geçerli bir düğümü görüntülüyorsanız, yalnızca erişim geri aramasını (ve dolayısıyla sayfa geri aramanızı) çağırır.

'node/%node/something'

Bu, yukarıdaki örnek için node_load (1234) öğesini çağıracağı ve yalnızca geçerli bir düğüm nesnesi döndürüldüğünde devam edeceği anlamına gelir. Böylece erişim argümanlarıyla izninizi her zamanki gibi tanımlayabilirsiniz.

Bununla birlikte, bir erişim geri araması yazmak gerçekten basittir. Bu yalnızca erişim bağımsız değişkenlerinde tanımladığınız bağımsız değişkenleri alacak bir işlevdir. Örneğin, varsayılan erişim geri arama olduğunu user_access () ve size erişim argümanları gibi tanımladığınızda 'access arguments' => array('a permission string'), aşağıdaki çağrı neden olacaktır: user_access('a permission string').

Birden fazla argümanınız varsa, bunlar işlevinize ikinci, üçüncü vb. Şu anda etkin olan düğüme erişmek için menu_get_object () öğesini kullanabilirsiniz .

Böylece erişim geri aramanızı bu şekilde yazabilirsiniz, ancak yine de bir tane oluşturmanız gerekmeyebilir.

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

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

İzin dizesini kodlamak yerine, işleve veya yapmak istediğiniz her şeye argüman olarak iletebilirsiniz.


Asla son örneği elde edemedi: fn ile $items['node/%node/edit']['access callback'] = 'admin_access_only'; ve $node = menu_get_object();geri aramada $nodehiçbir şey döndürmedi. Bunun yerine $node = node_load(arg(1)); çalıştım ... Daha fazla açıklama gerçekten memnuniyetle karşılanacaktır
Kojo

19

Drupal'ın kendisi kod yazmanın bir örneğidir.

Daha kolay olan örnek, aşağıdaki kodu içeren aggregator_menu () yöntemidir.

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

Bu durumda, erişim geri araması varsayılan değerdir ( user_access () ) ve erişim bağımsız değişkenleri izin için dizeyi içeren bir dizidir. Kod bir izinden fazlasını kontrol edemez; denetlenecek izinler iki ise veya denetlenecek koşullar yalnızca izinler değilse, erişim geri aramasının özel bir izin de dahil olmak üzere farklı olması gerekir.

node_menu () , varsayılandan farklı bir erişim geri araması kullanan bazı menüleri tanımlar. İşlev aşağıdaki kodu içerir.

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

Access callback ( node_access () ) olarak tanımlanan işlev şudur :

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

Dikkat edilmesi gereken üç nokta vardır:

  • "Access arguments" ile bildirilen argümanlar işleve aynı sırada iletilir; işlev yalnızca geri arama erişimi kullanılmadığından üçüncü bir parametre kullanır.
  • TRUEKullanıcı menüye erişirse ve kullanıcının menüye erişimi yoksa işlev geri döner FALSE.
  • Bir menünün yalnızca belirli durumlarda gösterilmesi gerektiğinde erişim geri araması da kullanılabilir.

Özel bir access callbackişlev bildirirken , .moduledosyanızda yaşaması gerekir , çünkü Drupal bunu filebildirimde bulamaz (en azından benim için).
tyler.frankenstein
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.