it-swarm.asia

هل لديك مثال لاستدعاء وصول hook_menu ()؟

لقد قمت بتنزيل أمثلة المشروع ، ولكن في وحدة menu_example الوحدة النمطية كل access callback تم تعيينها على true .. من الصعب فهم كيفية عملها.

في المثال الخاص بي ، يجب أن يكون إدخال مينو الخاص بي مرئيًا على العقد ، ولكن فقط للأدوار التي لديها أذونات لتعديل عقده الخاصة.

لا يمكنني العثور على مثال مطوّل أكثر من رد الاتصال.

هل لدى أحد واحد؟

18
Strae

تحرير: فاتني الجزء المتعلق بإذن "تحرير العقدة الخاصة" ، لأنه عندها يجب عليك ليس فقط التحقق من الإذن ولكن أيضًا إذا كانت هذه العقدة تنتمي إلى المستخدم الحالي. لقد قمت بتحديث المثال الخاص بي أدناه ولكني أترك الشرح أعلاه كما كان.

هل إدخال القائمة الخاص بك أسفل العقدة/nid (مثل العقدة/1234/شيء)؟ ثم ربما لا تحتاج حتى إلى اتصال وصول مخصص.

إذا قمت بتعريف مسار القائمة الخاص بك مثل المثال التالي ، فسيستدعي فقط استدعاء الوصول (وبالتالي استدعاء صفحتك) ، إذا كنت تعرض عقدة صالحة.

'node/%node/something'

هذا يعني أنه سيتم استدعاء node_load (1234) للمثال أعلاه ويستمر فقط إذا تم إرجاع كائن عقدة صالح. لذا يمكنك تحديد الإذن الخاص بك باستخدام وسيطات الوصول كالمعتاد.

ومع ذلك ، فإن كتابة رد وصول سهل للغاية. إنها مجرد وظيفة ستتلقى أي وسيطات حددتها في وسيطات الوصول. على سبيل المثال ، رد اتصال الوصول الافتراضي هو ser_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');
}

بدلاً من ترميز سلسلة الإذن ، يمكنك تمريرها كحجة للدالة أو أي شيء تريد القيام به.

12
Berdir

دروبال نفسه مثال على كيفية كتابة التعليمات البرمجية.

المثال الأسهل هو aggregator_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',
  );

في هذه الحالة ، يكون استدعاء الوصول هو الافتراضي ( ser_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 إذا لم يكن لدى المستخدم حق الوصول إلى القائمة.
  • يمكن أيضًا استخدام رد وصول عندما يجب أن تظهر القائمة في ظروف معينة فقط.
19
kiamlaluno