You are here

function _field_reference_potential_references_standard in Field reference 7

Helper function for field_reference_potential_references().

List of referenceable fields defined by content types.

1 call to _field_reference_potential_references_standard()
field_reference_potential_references in ./field_reference.module
Retrieves an array of candidate referenceable fields.

File

./field_reference.module, line 650
Defines a field type for referencing a field from another.

Code

function _field_reference_potential_references_standard($field, $instance, $options) {
  $references = array();
  if (!empty($field['settings']['fields'])) {
    $field_info_fields = field_info_fields();
    $field_info_instances = field_info_instances();

    // Get the table we need to look in.
    $storage = FIELD_LOAD_CURRENT;
    if (!empty($options['string'])) {

      // Treat each word as a separate keyword to conjunct so we can get more specific results.
      $keywords = explode(' ', $options['string']);

      //$keywords = array($options['string']);
    }

    // These things will always be selected.
    $selects = array(
      'entity_type',
      'bundle',
    );

    // These things will be juggled depending on what we need.
    $field_selects = array();
    if ($field['settings']['granularity']['entity']) {
      $field_selects[] = 'entity_id';
    }
    if ($field['settings']['granularity']['revision']) {
      $field_selects[] = 'revision_id';
      $storage = FIELD_LOAD_REVISION;
    }
    if ($field['settings']['granularity']['language']) {
      $field_selects[] = 'language';
    }
    if ($field['settings']['granularity']['value']) {
      $field_selects[] = 'delta';
    }

    // This is a dummy entry in the array to allow an empty combination, it won't
    // actually be selected.
    $field_selects[] = NULL;
    $field_select_groups = array();
    if ($field['settings']['allow_general']) {
      $total_field_selects = count($field_selects) * count($field_selects);
      for ($i = 1; $i < $total_field_selects - 1; $i++) {
        $field_select_group = array();
        for ($j = 0; $j < $total_field_selects; $j++) {
          if (pow(2, $j) & $i) {
            $field_select_group[] = $field_selects[$j];
          }
        }
        $field_select_groups[] = $field_select_group;
      }
    }
    else {
      $field_select_groups[] = $field_selects;
    }
    $sub_queries = array();
    $aliases = array();
    $entity_type_info = array();
    $placeholder_count = 0;
    foreach ($field['settings']['fields'] as $entity_type => $entity_type_data) {
      if (empty($entity_type_info[$entity_type])) {
        $entity_type_info[$entity_type] = field_reference_entity_get_info($entity_type);
      }
      $entity_table = $entity_type_info[$entity_type]['base table'];
      $entity_id = $entity_type_info[$entity_type]['entity keys']['id'];
      if (!empty($entity_type_info[$entity_type]['entity keys']['label'])) {
        $entity_label = $entity_type_info[$entity_type]['entity keys']['label'];
      }
      foreach ($entity_type_data as $bundle => $bundle_data) {
        foreach ($bundle_data as $field_key) {
          foreach ($field_select_groups as $field_select_group) {
            $storage_data = $field_info_fields[$field_key]['storage']['details']['sql'][$storage];

            // @todo: Does this work for all cases?  Assumes single table?
            $table = key($storage_data);
            $sub_query = db_select($table, 'field');
            $sub_query
              ->condition('entity_type', $entity_type);
            $sub_query
              ->condition('bundle', $bundle);
            $sub_query
              ->join($entity_table, 'entity', 'field.entity_id = entity.' . $entity_id);

            // Don't fetch the entity label, only filter on it.  Use the entity_label() function later to get the label.
            if (isset($entity_label)) {
              $conditions = array(
                'conditions' => array(
                  'entity.' . $entity_label,
                ),
              );
            }

            // Special case nodes to check node access.
            if ($entity_type == 'node') {
              $sub_query
                ->addTag('node_access');
            }

            // @todo Assumes single table?
            foreach ($storage_data[$table] as $v_key) {
              $ph_key = $placeholder_count++;
              $sub_query
                ->addExpression(':field_key' . $ph_key, 'field_key', array(
                ':field_key' . $ph_key => $field_key,
              ));
              $conditions['wheres'][] = "'" . $field_key . "'";
            }
            $field_label = $field_info_instances[$entity_type][$bundle][$field_key]['label'];
            if (!trim($field_label)) {
              $field_label = $field_key;
            }
            $sub_query
              ->addExpression(':field_label' . $ph_key, 'field_label', array(
              ':field_label' . $ph_key => $field_label,
            ));
            $conditions['wheres'][] = "'" . $field_label . "'";
            foreach ($selects as $select) {
              $sub_query
                ->addField('field', $select);
              $conditions['conditions'][] = 'field.' . $select;
            }

            // Add entity value to select.
            array_unshift($field_selects, $v_key);
            array_unshift($field_select_group, $v_key);
            foreach ($field_selects as $select) {
              if ($select) {
                if (in_array($select, $field_select_group)) {

                  //$sub_query->addField('field', $select);
                  $sub_query
                    ->addExpression('field.' . $select, $select);
                  $conditions['conditions'][] = 'field.' . $select;
                }
                else {
                  $sub_query
                    ->addExpression(':field_reference_null', $select, array(
                    ':field_reference_null' => '',
                  ));
                }
              }
            }
            if (!empty($keywords)) {
              foreach ($keywords as $keyword_position => $keyword) {
                $keyword_condition = db_or();
                foreach ($conditions as $conditions_type => $conditions_data) {
                  foreach ($conditions_data as $condition_key => $condition) {
                    switch ($options['match']) {
                      case 'contains':
                        if ($conditions_type == 'conditions') {
                          $keyword_condition
                            ->condition($condition, '%' . $keyword . '%', 'LIKE');
                        }
                        elseif ($conditions_type == 'wheres') {
                          $condition_placeholder = ':' . $conditions_type . $condition_key;
                          $keyword_placeholder = ':' . $conditions_type . $condition_key . '_' . $keyword_position;
                          $keyword_condition
                            ->where($condition_placeholder . ' LIKE ' . $keyword_placeholder, array(
                            $condition_placeholder => $condition,
                            $keyword_placeholder => '%' . $keyword . '%',
                          ));
                        }
                        break;
                      case 'starts_with':
                        if ($conditions_type == 'conditions') {
                          $keyword_condition
                            ->condition($condition, $keyword . '%', 'LIKE');
                        }
                        elseif ($conditions_type == 'wheres') {
                          $condition_placeholder = ':' . $conditions_type . $condition_key;
                          $keyword_placeholder = ':' . $conditions_type . $condition_key . '_' . $keyword_position;
                          $keyword_condition
                            ->where($condition_placeholder . ' LIKE ' . $keyword_placeholder, array(
                            $condition_placeholder => $condition,
                            $keyword_placeholder => $keyword . '%',
                          ));
                        }
                        break;
                      case 'equals':
                      default:

                        // no match type or incorrect match type: use "="
                        if ($conditions_type == 'conditions') {
                          $keyword_condition
                            ->condition($condition, $keyword);
                        }
                        elseif ($conditions_type == 'wheres') {
                          $condition_placeholder = ':' . $conditions_type . $condition_key;
                          $keyword_placeholder = ':' . $conditions_type . $condition_key . '_' . $keyword_position;
                          $keyword_condition
                            ->where($condition_placeholder . ' = ' . $keyword_placeholder, array(
                            $condition_placeholder => $condition,
                            $keyword_placeholder => $keyword,
                          ));
                        }
                        break;
                    }
                  }
                }
                $sub_query
                  ->condition($keyword_condition);
              }
            }
            $sub_queries[] = $sub_query;
          }
        }
      }
    }
    if (!empty($sub_queries)) {
      $query = array_shift($sub_queries);
      foreach ($sub_queries as $sub_query) {
        $query
          ->union($sub_query);
      }
      if (!empty($options['limit'])) {
        $query
          ->range(0, $options['limit']);
      }

      // Note can't do order by, see: http://drupal.org/node/1145076
      $result = $query
        ->execute();
      while ($field_reference = $result
        ->fetchAssoc()) {

        // If only selecting within entity, skip fields from other entity types or bundles.
        if (!$field['settings']['granularity']['entity'] && ($instance['entity_type'] != $field_reference['entity_type'] || $instance['bundle'] != $field_reference['bundle'])) {
          continue;
        }
        $key = field_reference_key_create($field_reference);
        $value_key = $field_reference['field_key'] . '_value';
        if (isset($references[$key])) {

          // Existing entry, only update value.
          if (empty($options['prevent_label']) && !empty($field['settings']['show_value'])) {

            // Add value.
            if (!empty($field_reference[$value_key])) {
              $references[$key]['val'][] = $field_reference[$value_key];
            }
          }
        }
        else {

          // New entry.
          $label = array();
          if (empty($options['prevent_label'])) {
            if (empty($field['settings']['hide_field_locator'])) {
              $label['loc'] = field_reference_label_create($field_reference);
            }
            if (!empty($field['settings']['show_value'])) {

              // Add value.
              if (!empty($field_reference[$value_key])) {
                $label['val'] = array(
                  $field_reference[$value_key],
                );
              }
            }
            if (!empty($field['settings']['append_id']) && $options['append_id'] !== FALSE || $options['append_id']) {
              $label['id'] = ' [' . $key . ']';
            }
          }
          $references[$key] = $label;
        }
      }
    }
  }
  $refs = array();
  foreach ($references as $key => $ref) {
    $refs[$key] = '';
    if (!empty($ref['loc'])) {
      $refs[$key] .= $ref['loc'];
    }
    if (!empty($ref['val'])) {
      $refs[$key] .= ' {' . t('Current val:') . implode(',', $ref['val']) . '}';
    }
    if (!empty($ref['id'])) {
      $refs[$key] .= $ref['id'];
    }
    if (empty($refs[$key])) {

      // We gotta show something...
      $refs[$key] .= $key;
    }
  }

  // To implement hook_field_reference_labels, copy the above for-loop and modify it.
  drupal_alter('field_reference_labels', $refs, $references);
  return $refs;
}