Commit 2d9fd20a authored by webchick's avatar webchick

#834842 by Damien Tournoud, chx: Fixed oversight in field query routing API, and added tests.

parent a1f25d31
......@@ -763,14 +763,38 @@ public function age($age) {
* @endcode
*/
public function execute() {
// Give a chance to other modules to alter the query.
drupal_alter('entity_query', $this);
// Execute the query using the correct callback.
$result = call_user_func($this->queryCallback(), $this);
// Sanity checks.
if (!empty($this->propertyConditions)) {
throw new EntityFieldQueryException(t('Property query conditions were not handled in !function.', array('!function' => $function)));
}
if (!empty($this->propertyOrderBy)) {
throw new EntityFieldQueryException(t('Property query order by was not handled in !function.', array('!function' => $function)));
}
return $result;
}
/**
* Determines the query callback to use for this entity query.
*
* @return
* A callback that can be used with call_user_func().
*/
public function queryCallback() {
// Use the override from $this->executeCallback. It can be set either
// while building the query, or using hook_entity_query_alter().
if (function_exists($this->executeCallback)) {
return $this->executeCallback($this);
return $this->executeCallback;
}
// If there are no field conditions and sorts, and no execute callback
// then we default to querying entity tables in SQL.
if (empty($this->fields)) {
return $this->propertyQuery();
return array($this, 'propertyQuery');
}
// If no override, find the storage engine to be used.
foreach ($this->fields as $field) {
......@@ -781,18 +805,13 @@ public function execute() {
throw new EntityFieldQueryException(t("Can't handle more than one field storage engine"));
}
}
if (empty($storage)) {
throw new EntityFieldQueryException(t("Field storage engine not found."));
}
$function = $storage . '_field_storage_query';
$result = $function($this);
if (!empty($this->propertyConditions)) {
throw new EntityFieldQueryException(t('Property query conditions were not handled in !function.', array('!function' => $function)));
if ($storage) {
// Use hook_field_storage_query() from the field storage.
return $storage . '_field_storage_query';
}
if (!empty($this->propertyOrderBy)) {
throw new EntityFieldQueryException(t('Property query order by was not handled in !function.', array('!function' => $function)));
else {
throw new EntityFieldQueryException(t("Field storage engine not found."));
}
return $result;
}
/**
......
......@@ -191,3 +191,24 @@ function field_test_field_delete($entity_type, $entity, $field, $instance, $item
$args = func_get_args();
field_test_memorize(__FUNCTION__, $args);
}
/**
* Implements hook_entity_query_alter().
*/
function field_test_entity_query_alter(&$query) {
if (!empty($query->alterMyExecuteCallbackPlease)) {
$query->executeCallback = 'field_test_dummy_field_storage_query';
}
}
/**
* Pseudo-implements hook_field_storage_query().
*/
function field_test_dummy_field_storage_query(EntityFieldQuery $query) {
// Return dummy values that will be checked by the test.
return array(
'user' => array(
1 => entity_create_stub_entity('user', array(1, NULL, NULL)),
),
);
}
......@@ -818,6 +818,60 @@ class EntityFieldQueryTestCase extends DrupalWebTestCase {
$this->assertTrue($pass, t("Can't query the universe."));
}
/**
* Tests the routing feature of EntityFieldQuery.
*/
function testEntityFieldQueryRouting() {
// Entity-only query.
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'test_entity_bundle_key');
$this->assertIdentical($query->queryCallback(), array($query, 'propertyQuery'), t('Entity-only queries are handled by the propertyQuery handler.'));
// Field-only query.
$query = new EntityFieldQuery();
$query->fieldCondition($this->fields[0], 'value', '3');
$this->assertIdentical($query->queryCallback(), 'field_sql_storage_field_storage_query', t('Pure field queries are handled by the Field storage handler.'));
// Mixed entity and field query.
$query = new EntityFieldQuery();
$query
->entityCondition('entity_type', 'test_entity_bundle_key')
->fieldCondition($this->fields[0], 'value', '3');
$this->assertIdentical($query->queryCallback(), 'field_sql_storage_field_storage_query', t('Mixed queries are handled by the Field storage handler.'));
// Overriding with $query->executeCallback.
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'test_entity_bundle_key');
$query->executeCallback = 'field_test_dummy_field_storage_query';
$this->assertEntityFieldQuery($query, array(
array('user', 1),
), t('executeCallback can override the query handler.'));
// Overriding with $query->executeCallback via hook_entity_query_alter().
$query = new EntityFieldQuery();
$query->entityCondition('entity_type', 'test_entity_bundle_key');
// Add a flag that will be caught by field_test_entity_query_alter().
$query->alterMyExecuteCallbackPlease = TRUE;
$this->assertEntityFieldQuery($query, array(
array('user', 1),
), t('executeCallback can override the query handler when set in a hook_entity_query_alter().'));
// Mixed-storage queries.
$query = new EntityFieldQuery();
$query
->fieldCondition($this->fields[0], 'value', '3')
->fieldCondition($this->fields[1], 'shape', 'squ', 'STARTS_WITH');
// Alter the storage of the field.
$query->fields[1]['storage']['module'] = 'dummy_storage';
try {
$query->queryCallback();
}
catch (EntityFieldQueryException $exception) {
$pass = ($exception->getMessage() == t("Can't handle more than one field storage engine"));
}
$this->assertTrue($pass, t('Cannot query across field storage engines.'));
}
/**
* Fetches the results of an EntityFieldQuery and compares.
*
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment