You are here

function node_reference_field_prepare_view in References 7.2

Implements hook_field_prepare_view().

File

node_reference/node_reference.module, line 204
Defines a field type for referencing one node from another.

Code

function node_reference_field_prepare_view($entity_type, $entities, $field, $instances, $langcode, &$items) {
  $checked_ids =& drupal_static(__FUNCTION__, array());

  // Set an 'access' property on each item (TRUE if the node exists and is
  // accessible by the current user).
  // Extract ids to check.
  $ids = array();
  if (is_array($items)) {
    foreach ($items as $id => $entity_items) {
      foreach ($entity_items as $delta => $item) {
        if (is_array($item)) {

          // Default to 'not accessible'.
          $items[$id][$delta]['access'] = FALSE;
          if (!empty($item['nid']) && is_numeric($item['nid'])) {
            $ids[$item['nid']] = $item['nid'];
          }
        }
      }
    }
  }
  if ($ids) {

    // Load information about ids that we haven't already loaded during this
    // page request.
    $ids_to_check = array_diff($ids, array_keys($checked_ids));
    if (!empty($ids_to_check)) {
      $query = db_select('node', 'n')
        ->addTag('node_access')
        ->addMetaData('id', 'node_reference_field_prepare_view')
        ->addMetaData('field', $field)
        ->fields('n', array(
        'nid',
      ))
        ->condition('n.nid', $ids_to_check, 'IN');

      // Unless the user has the right permissions, restrict on the node status.
      // 'view_unpublished' contrib module and the
      // 'view all unpublished content'
      // permission is provided by the 'workbench_moderation' contrib module.)
      if (!user_access('bypass node access') && !user_access('view any unpublished content') && !user_access('view all unpublished content')) {

        // ... AND n.status = 1.
        $status_condition = db_or()
          ->condition('n.status', NODE_PUBLISHED);

        // Take the 'view own unpublished content' permission into account to
        // decide whether some unpublished nodes should still be visible. We
        // only need the items in $ids_to_check because those are the only
        // entries that we are interested in. Any other nodes created by the
        // user are simply ignored so lets only retrieve that subset.
        if (user_access('view own unpublished content') && ($own_unpublished = db_query('SELECT nid FROM {node} WHERE uid = :uid AND status = :status AND nid IN (:nodes)', array(
          ':uid' => $GLOBALS['user']->uid,
          ':status' => NODE_NOT_PUBLISHED,
          ':nodes' => $ids_to_check,
        ))
          ->fetchCol())) {

          // ... AND (n.status = 1 OR n.nid IN (own unpublished))
          $status_condition
            ->condition('n.nid', $own_unpublished, 'IN');
        }
        $query
          ->condition($status_condition);
      }
      $accessible_ids = $query
        ->execute()
        ->fetchAllAssoc('nid');

      // Populate our static list so that we do not query on those ids again.
      foreach ($ids_to_check as $id) {
        $checked_ids[$id] = isset($accessible_ids[$id]);
      }
    }
    foreach ($items as $id => $entity_items) {
      foreach ($entity_items as $delta => $item) {
        if (is_array($item) && !empty($item['nid']) && !empty($checked_ids[$item['nid']])) {
          $items[$id][$delta]['access'] = TRUE;
        }
      }
    }
  }
}