Ejemplo n.º 1
0
/**
 * Execute an EntityFieldQuery.
 *
 * This hook is called to find the entities having certain entity and field
 * conditions and sort them in the given field order. If the field storage
 * engine also handles property sorts and orders, it should unset those
 * properties in the called object to signal that those have been handled.
 *
 * @param EntityFieldQuery $query
 *   An EntityFieldQuery.
 *
 * @return
 *   See EntityFieldQuery::execute() for the return values.
 */
function hook_field_storage_query($query)
{
    $groups = array();
    if ($query->age == FIELD_LOAD_CURRENT) {
        $tablename_function = '_field_sql_storage_tablename';
        $id_key = 'entity_id';
    } else {
        $tablename_function = '_field_sql_storage_revision_tablename';
        $id_key = 'revision_id';
    }
    $table_aliases = array();
    // Add tables for the fields used.
    foreach ($query->fields as $key => $field) {
        $tablename = $tablename_function($field);
        // Every field needs a new table.
        $table_alias = $tablename . $key;
        $table_aliases[$key] = $table_alias;
        if ($key) {
            $select_query->join($tablename, $table_alias, "{$table_alias}.entity_type = {$field_base_table}.entity_type AND {$table_alias}.{$id_key} = {$field_base_table}.{$id_key}");
        } else {
            $select_query = db_select($tablename, $table_alias);
            $select_query->addTag('entity_field_access');
            $select_query->addMetaData('base_table', $tablename);
            $select_query->fields($table_alias, array('entity_type', 'entity_id', 'revision_id', 'bundle'));
            $field_base_table = $table_alias;
        }
        if ($field['cardinality'] != 1) {
            $select_query->distinct();
        }
    }
    // Add field conditions.
    foreach ($query->fieldConditions as $key => $condition) {
        $table_alias = $table_aliases[$key];
        $field = $condition['field'];
        // Add the specified condition.
        $sql_field = "{$table_alias}." . _field_sql_storage_columnname($field['field_name'], $condition['column']);
        $query->addCondition($select_query, $sql_field, $condition);
        // Add delta / language group conditions.
        foreach (array('delta', 'language') as $column) {
            if (isset($condition[$column . '_group'])) {
                $group_name = $condition[$column . '_group'];
                if (!isset($groups[$column][$group_name])) {
                    $groups[$column][$group_name] = $table_alias;
                } else {
                    $select_query->where("{$table_alias}.{$column} = " . $groups[$column][$group_name] . ".{$column}");
                }
            }
        }
    }
    if (isset($query->deleted)) {
        $select_query->condition("{$field_base_table}.deleted", (int) $query->deleted);
    }
    // Is there a need to sort the query by property?
    $has_property_order = FALSE;
    foreach ($query->order as $order) {
        if ($order['type'] == 'property') {
            $has_property_order = TRUE;
        }
    }
    if ($query->propertyConditions || $has_property_order) {
        if (empty($query->entityConditions['entity_type']['value'])) {
            throw new EntityFieldQueryException('Property conditions and orders must have an entity type defined.');
        }
        $entity_type = $query->entityConditions['entity_type']['value'];
        $entity_base_table = _field_sql_storage_query_join_entity($select_query, $entity_type, $field_base_table);
        $query->entityConditions['entity_type']['operator'] = '=';
        foreach ($query->propertyConditions as $property_condition) {
            $query->addCondition($select_query, "{$entity_base_table}." . $property_condition['column'], $property_condition);
        }
    }
    foreach ($query->entityConditions as $key => $condition) {
        $query->addCondition($select_query, "{$field_base_table}.{$key}", $condition);
    }
    // Order the query.
    foreach ($query->order as $order) {
        if ($order['type'] == 'entity') {
            $key = $order['specifier'];
            $select_query->orderBy("{$field_base_table}.{$key}", $order['direction']);
        } elseif ($order['type'] == 'field') {
            $specifier = $order['specifier'];
            $field = $specifier['field'];
            $table_alias = $table_aliases[$specifier['index']];
            $sql_field = "{$table_alias}." . _field_sql_storage_columnname($field['field_name'], $specifier['column']);
            $select_query->orderBy($sql_field, $order['direction']);
        } elseif ($order['type'] == 'property') {
            $select_query->orderBy("{$entity_base_table}." . $order['specifier'], $order['direction']);
        }
    }
    return $query->finishQuery($select_query, $id_key);
}
 /**
  * {@inheritdoc}
  */
 public function finishQuery($select_query, $id_key = 'entity_id')
 {
     $entity_type = $this->entityConditions['entity_type']['value'];
     foreach ($this->getRelationships() as $delta => $relationship) {
         // A relational filter consists of a chain of relationships and a value
         // for a condition at the end.
         // Relationships start with the entity base table.
         $entity_info = entity_get_info($entity_type);
         $entity_table = $entity_table_alias = $entity_info['base table'];
         // Add the table if the base entity table was not added because:
         // 1. There was a fieldCondition or fieldOrderBy, AND
         // 2. There was no property condition ot order.
         if ($delta == 0) {
             $is_entity_table_present = FALSE;
             $field_base_table_alias = NULL;
             foreach ($select_query->getTables() as $table_info) {
                 // Search for the base table and check if the entity table is present
                 // for the resource's entity type.
                 if (!$field_base_table_alias && empty($table_info['join type'])) {
                     $field_base_table_alias = $table_info['alias'];
                 }
                 if ($table_info['table'] == $entity_table) {
                     $is_entity_table_present = TRUE;
                     break;
                 }
             }
             if (!$is_entity_table_present && $field_base_table_alias) {
                 // We have the base table and we need to join it to the entity table.
                 _field_sql_storage_query_join_entity($select_query, $entity_type, $field_base_table_alias);
             }
         }
         // Pop the last item, since it is the one that has to match the filter and
         // will have the WHERE associated.
         $condition = array_pop($relationship['relational_filters']);
         foreach ($relationship['relational_filters'] as $relational_filter) {
             /* @var RelationalFilterInterface $relational_filter */
             if ($relational_filter->getType() == RelationalFilterInterface::TYPE_FIELD) {
                 $field_table_name = _field_sql_storage_tablename(field_info_field($relational_filter->getName()));
                 $field_table_alias = $this::aliasJoinTable($field_table_name, $select_query);
                 $select_query->addJoin('INNER', $field_table_name, $field_table_alias, sprintf('%s.%s = %s.%s', $entity_table_alias, $entity_info['entity keys']['id'], $field_table_alias, $id_key));
                 // Get the entity type being referenced.
                 $entity_info = entity_get_info($relational_filter->getEntityType());
                 $entity_table_alias = $this->aliasJoinTable($entity_info['base table'], $select_query);
                 $select_query->addJoin('INNER', $entity_info['base table'], $entity_table_alias, sprintf('%s.%s = %s.%s', $field_table_name, _field_sql_storage_columnname($relational_filter->getName(), $relational_filter->getColumn()), $entity_table_alias, $entity_info['entity keys']['id']));
             } elseif ($relational_filter->getType() == RelationalFilterInterface::TYPE_PROPERTY) {
                 // In this scenario we want to join with the new table entity. This
                 // will only work if the property contains the referenced entity ID
                 // (which is not unreasonable).
                 $host_entity_table = $entity_table;
                 $entity_info = entity_get_info($relational_filter->getEntityType());
                 $entity_table_alias = $this->aliasJoinTable($entity_info['base table'], $select_query);
                 $select_query->addJoin('INNER', $entity_info['base table'], $entity_table_alias, sprintf('%s.%s = %s.%s', $host_entity_table, $relational_filter->getName(), $entity_table_alias, $entity_info['entity keys']['id']));
             }
         }
         /* @var RelationalFilterInterface $condition */
         if ($condition->getType() == RelationalFilterInterface::TYPE_FIELD) {
             // Make the join to the filed table for the condition.
             $field_table_name = _field_sql_storage_tablename(field_info_field($condition->getName()));
             $field_column = _field_sql_storage_columnname($condition->getName(), $condition->getColumn());
             $field_table_alias = $this::aliasJoinTable($field_table_name, $select_query);
             $select_query->addJoin('INNER', $field_table_name, $field_table_alias, sprintf('%s.%s = %s.%s', $entity_table_alias, $entity_info['entity keys']['id'], $field_table_alias, $id_key));
             if (in_array($relationship['operator'], array('IN', 'BETWEEN'))) {
                 $select_query->condition($field_table_name . '.' . $field_column, $relationship['value'], $relationship['operator'][0]);
             } else {
                 for ($index = 0; $index < count($relationship['value']); $index++) {
                     $select_query->condition($field_table_name . '.' . $field_column, $relationship['value'][$index], $relationship['operator'][$index]);
                 }
             }
         } elseif ($condition->getType() == RelationalFilterInterface::TYPE_PROPERTY) {
             if (in_array($relationship['operator'], array('IN', 'BETWEEN'))) {
                 $select_query->condition($entity_table_alias . '.' . $condition->getName(), $relationship['value'], $relationship['operator'][0]);
             } else {
                 for ($index = 0; $index < count($relationship['value']); $index++) {
                     $select_query->condition($entity_table_alias . '.' . $condition->getName(), $relationship['value'][$index], $relationship['operator'][$index]);
                 }
             }
         }
     }
     return parent::finishQuery($select_query, $id_key);
 }