From 4a5e9447c00ab79030cd7b98b5c79bab1a6236fb Mon Sep 17 00:00:00 2001 From: Dries Buytaert Date: Fri, 5 Nov 2010 19:57:28 +0000 Subject: [PATCH] - Patch #938462 by bojanz: Fix EntityFieldQuery fatal error in certain cases and document bundle limitations. --- includes/entity.inc | 16 ++++++++++-- modules/field/tests/field_test.entity.inc | 21 +++++++++++++++ modules/simpletest/tests/entity_query.test | 30 ++++++++++++++++------ 3 files changed, 57 insertions(+), 10 deletions(-) diff --git a/includes/entity.inc b/includes/entity.inc index f7a108009e0..7f9a78da7dd 100644 --- a/includes/entity.inc +++ b/includes/entity.inc @@ -549,6 +549,10 @@ class EntityFieldQuery { * * 'bundle', 'revision_id' and 'entity_id' have no such restrictions. * + * Note: The "comment" and "taxonomy_term" entity types don't support bundle + * conditions. For "taxonomy_term", propertyCondition('vid') can be used + * instead. + * * @param $name * 'entity_type', 'bundle', 'revision_id' or 'entity_id'. * @param $value @@ -680,6 +684,9 @@ class EntityFieldQuery { * If called multiple times, the query will order by each specified column in * the order this method is called. * + * Note: The "comment" and "taxonomy_term" entity types don't support ordering + * by bundle. For "taxonomy_term", propertyOrderBy('vid') can be used instead. + * * @param $name * 'entity_type', 'bundle', 'revision_id' or 'entity_id'. * @param $direction @@ -965,6 +972,7 @@ class EntityFieldQuery { throw new EntityFieldQueryException(t('Entity %entity has no base table.', array('%entity' => $entity_type))); } $base_table = $entity_info['base table']; + $base_table_schema = drupal_get_schema($base_table); $select_query = db_select($base_table); $select_query->addExpression(':entity_type', 'entity_type', array(':entity_type' => $entity_type)); // Process the property conditions. @@ -997,8 +1005,11 @@ class EntityFieldQuery { // Handle bundles. if (!empty($entity_info['entity keys']['bundle'])) { $sql_field = $entity_info['entity keys']['bundle']; - $select_query->addField($base_table, $sql_field, 'bundle'); $having = FALSE; + + if (!empty($base_table_schema['fields'][$sql_field])) { + $select_query->addField($base_table, $sql_field, 'bundle'); + } } else { $sql_field = 'bundle'; @@ -1057,7 +1068,8 @@ class EntityFieldQuery { } $return = array(); foreach ($select_query->execute() as $partial_entity) { - $entity = entity_create_stub_entity($partial_entity->entity_type, array($partial_entity->entity_id, $partial_entity->revision_id, $partial_entity->bundle)); + $bundle = isset($partial_entity->bundle) ? $partial_entity->bundle : NULL; + $entity = entity_create_stub_entity($partial_entity->entity_type, array($partial_entity->entity_id, $partial_entity->revision_id, $bundle)); $return[$partial_entity->entity_type][$partial_entity->$id_key] = $entity; $this->ordered_results[] = $partial_entity; } diff --git a/modules/field/tests/field_test.entity.inc b/modules/field/tests/field_test.entity.inc index 353bb3de04b..37695bd4906 100644 --- a/modules/field/tests/field_test.entity.inc +++ b/modules/field/tests/field_test.entity.inc @@ -62,13 +62,16 @@ function field_test_entity_info() { 'bundles' => array('bundle1' => array('label' => 'Bundle1'), 'bundle2' => array('label' => 'Bundle2')), 'view modes' => $test_entity_modes, ), + // In this case, the bundle key is not stored in the database. 'test_entity_bundle' => array( 'name' => t('Test Entity with a specified bundle.'), 'base table' => 'test_entity_bundle', 'fieldable' => TRUE, + 'controller class' => 'TestEntityBundleController', 'field cache' => FALSE, 'entity keys' => array( 'id' => 'ftid', + 'bundle' => 'fttype', ), 'bundles' => array('test_entity_2' => array('label' => 'Test entity 2')), 'view modes' => $test_entity_modes, @@ -409,3 +412,21 @@ function field_test_entity_form_submit_builder($form, &$form_state) { entity_form_submit_build_entity('test_entity', $entity, $form, $form_state); return $entity; } + +/** + * Controller class for the test_entity_bundle entity type. + * + * This extends the DrupalDefaultEntityController class, adding required + * special handling for bundles (since they are not stored in the database). + */ +class TestEntityBundleController extends DrupalDefaultEntityController { + + protected function attachLoad(&$entities, $revision_id = FALSE) { + // Add bundle information. + foreach ($entities as $key => $entity) { + $entity->fttype = 'test_entity_bundle'; + $entities[$key] = $entity; + } + parent::attachLoad($entities, $revision_id); + } +} diff --git a/modules/simpletest/tests/entity_query.test b/modules/simpletest/tests/entity_query.test index 171c51730d3..7aa4963abd1 100644 --- a/modules/simpletest/tests/entity_query.test +++ b/modules/simpletest/tests/entity_query.test @@ -113,7 +113,7 @@ class EntityFieldQueryTestCase extends DrupalWebTestCase { $entity = new stdClass(); $entity->ftid = 5; - $entity->fttype = 'bundle2'; + $entity->fttype = 'test_entity_bundle'; $entity->{$this->field_names[1]}[LANGUAGE_NONE][0]['shape'] = 'square'; $entity->{$this->field_names[1]}[LANGUAGE_NONE][0]['color'] = 'red'; $entity->{$this->field_names[1]}[LANGUAGE_NONE][1]['shape'] = 'circle'; @@ -164,6 +164,14 @@ class EntityFieldQueryTestCase extends DrupalWebTestCase { * Tests EntityFieldQuery. */ function testEntityFieldQuery() { + $query = new EntityFieldQuery(); + $query + ->entityCondition('entity_type', 'test_entity_bundle') + ->entityCondition('entity_id', '5'); + $this->assertEntityFieldQuery($query, array( + array('test_entity_bundle', 5), + ), t('Test query on an entity type with a generated bundle.')); + // Test entity_type condition. $query = new EntityFieldQuery(); $query->entityCondition('entity_type', 'test_entity_bundle_key'); @@ -974,6 +982,7 @@ class EntityFieldQueryTestCase extends DrupalWebTestCase { for ($i = 6; $i < 10; $i++) { $entity = new stdClass(); $entity->ftid = $i; + $entity->fttype = 'test_entity_bundle'; $entity->{$this->field_names[0]}[LANGUAGE_NONE][0]['value'] = $i - 5; drupal_write_record('test_entity_bundle', $entity); field_attach_insert('test_entity_bundle', $entity); @@ -1112,15 +1121,20 @@ class EntityFieldQueryTestCase extends DrupalWebTestCase { */ function assertEntityFieldQuery($query, $intended_results, $message, $ordered = FALSE) { $results = array(); - foreach ($query->execute() as $entity_type => $entity_ids) { - foreach ($entity_ids as $entity_id => $stub_entity) { - $results[] = array($entity_type, $entity_id); + try { + foreach ($query->execute() as $entity_type => $entity_ids) { + foreach ($entity_ids as $entity_id => $stub_entity) { + $results[] = array($entity_type, $entity_id); + } } + if (!isset($ordered) || !$ordered) { + sort($results); + sort($intended_results); + } + $this->assertEqual($results, $intended_results, $message); } - if (!isset($ordered) || !$ordered) { - sort($results); - sort($intended_results); + catch (Exception $e) { + $this->fail('Exception thrown: '. $e->getMessage()); } - $this->assertEqual($results, $intended_results, $message); } }