diff --git includes/entity.inc includes/entity.inc index 1884612..32b259e 100644 --- includes/entity.inc +++ includes/entity.inc @@ -462,6 +462,15 @@ class EntityFieldQuery { public $range = array(); /** + * The query pager. + * + * @var array + * + * @see EntityFieldQuery::pager() + */ + public $pager = array(); + + /** * Query behavior for deleted data. * * TRUE to return only deleted data, FALSE to return only non-deleted data, @@ -792,6 +801,65 @@ class EntityFieldQuery { } /** + * Enable a pager for the query. + * + * @param $limit + * An integer specifying the number of elements per page. If passed a false + * value (FALSE, 0, NULL), the pager is disabled. + * @param $element + * An optional integer to distinguish between multiple pagers on one page. + * + * @return EntityFieldQuery + * The called object. + */ + public function pager($limit = 10, $element = NULL) { + if (!isset($element)) { + $element = PagerDefault::$maxElement++; + } + else if ($element >= PagerDefault::$maxElement) { + PagerDefault::$maxElement = $element + 1; + } + + $this->pager = array( + 'limit' => $limit, + 'element' => $element, + ); + return $this; + } + + /** + * Enable sortable tables for this query. + * + * @param $header + * An EFQ Header array based on which the order clause is added to the query. + * + * @return EntityFieldQuery + * The called object. + */ + public function tableSort($headers) { + $order = tablesort_get_order($headers); + $direction = tablesort_get_sort($headers); + + foreach ($headers as $key => $header) { + if (!is_array($header) || ($header['data'] != $order['name'])) { + continue; + } + + if ($header['type'] == 'property') { + $this->propertyOrderBy($header['specifier'], $direction); + } + else if ($header['type'] == 'entity') { + $this->entityOrderBy($header['specifier'], $direction); + } + else if ($header['type'] == 'field') { + $this->fieldOrderBy($header['specifier']['field'], $header['specifier']['column'], $direction); + } + } + + return $this; + } + + /** * Filters on the data being deleted. * * @param $deleted @@ -1009,7 +1077,7 @@ class EntityFieldQuery { if (isset($this->entityConditions['bundle'])) { $this->addCondition($select_query, $sql_field, $this->entityConditions['bundle'], $having); } - + // Order the query. foreach ($this->order as $order) { if ($order['type'] == 'entity') { @@ -1023,14 +1091,14 @@ class EntityFieldQuery { $select_query->orderBy("$base_table." . $order['specifier'], $order['direction']); } } - + return $this->finishQuery($select_query); } /** * Finishes the query. * - * Adds tags, metaData, range and returns the requested list or count. + * Adds tags, metaData, range, pager and returns the requested list or count. * * @param SelectQuery $select_query * A SelectQuery which has entity_type, entity_id, revision_id and bundle @@ -1055,6 +1123,17 @@ class EntityFieldQuery { if ($this->count) { return $select_query->countQuery()->execute()->fetchField(); } + if ($this->pager && !$this->count) { + $count_query = clone $this; + $total = $count_query->count()->execute(); + + $page = pager_find_page(); + $start = $page * $limit; + + pager_default_initialize($total, $limit, $element); + $this->range($start, $limit); + $select_query->range($this->range['start'], $this->range['length']); + } $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)); diff --git modules/field/modules/field_sql_storage/field_sql_storage.module modules/field/modules/field_sql_storage/field_sql_storage.module index ea52707..0ce4d7b 100644 --- modules/field/modules/field_sql_storage/field_sql_storage.module +++ modules/field/modules/field_sql_storage/field_sql_storage.module @@ -549,7 +549,7 @@ function field_sql_storage_field_storage_query(EntityFieldQuery $query) { $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.'); @@ -565,7 +565,7 @@ function field_sql_storage_field_storage_query(EntityFieldQuery $query) { $sql_field = $key == 'entity_type' ? 'fcet.type' : "$field_base_table.$key"; $query->addCondition($select_query, $sql_field, $condition); } - + // Order the query. foreach ($query->order as $order) { if ($order['type'] == 'entity') { diff --git modules/simpletest/tests/entity_query.test modules/simpletest/tests/entity_query.test index 32edf38..0f4b978 100644 --- modules/simpletest/tests/entity_query.test +++ modules/simpletest/tests/entity_query.test @@ -1092,6 +1092,238 @@ class EntityFieldQueryTestCase extends DrupalWebTestCase { } /** + * Tests the pager integration of EntityFieldQuery. + */ + function testEntityFieldQueryPager() { + // Test pager in propertyQuery + $_GET['page'] = "0,1"; + $query = new EntityFieldQuery(); + $query + ->entityCondition('entity_type', 'test_entity_bundle_key') + ->propertyOrderBy('ftid', 'ASC') + ->pager(3, 0); + $this->assertEntityFieldQuery($query, array( + array('test_entity_bundle_key', 1), + array('test_entity_bundle_key', 2), + array('test_entity_bundle_key', 3), + ), t('Test pager integration in propertyQuery: page 1.'), TRUE); + + $query = new EntityFieldQuery(); + $query + ->entityCondition('entity_type', 'test_entity_bundle_key') + ->propertyOrderBy('ftid', 'ASC') + ->pager(3, 1); + $this->assertEntityFieldQuery($query, array( + array('test_entity_bundle_key', 4), + array('test_entity_bundle_key', 5), + array('test_entity_bundle_key', 6), + ), t('Test pager integration in propertyQuery: page 2.'), TRUE); + + // Test pager in field storage + $_GET['page'] = "0,1"; + $query = new EntityFieldQuery(); + $query + ->entityCondition('entity_type', 'test_entity_bundle_key') + ->fieldCondition($this->fields[0], 'value', 0, '>') + ->propertyOrderBy('ftid', 'ASC') + ->pager(2, 0); + $this->assertEntityFieldQuery($query, array( + array('test_entity_bundle_key', 1), + array('test_entity_bundle_key', 2), + ), t('Test pager integration in field storage: page 1.'), TRUE); + + $query = new EntityFieldQuery(); + $query + ->entityCondition('entity_type', 'test_entity_bundle_key') + ->fieldCondition($this->fields[0], 'value', 0, '>') + ->propertyOrderBy('ftid', 'ASC') + ->pager(2, 1); + $this->assertEntityFieldQuery($query, array( + array('test_entity_bundle_key', 3), + array('test_entity_bundle_key', 4), + ), t('Test pager integration in field storage: page 2.'), TRUE); + + unset($_GET['page']); + } + + /** + * Tests the TableSort integration of EntityFieldQuery. + */ + function testEntityFieldQueryTableSort() { + // Test TableSort in propertyQuery + $_GET['sort'] = 'asc'; + $_GET['order'] = 'Id'; + $header = array( + 'id' => array('data' => 'Id', 'type' => 'property', 'specifier' => 'ftid'), + 'type' => array('data' => 'Type', 'type' => 'entity', 'specifier' => 'bundle'), + ); + $query = new EntityFieldQuery(); + $query + ->entityCondition('entity_type', 'test_entity_bundle_key') + ->tableSort($header); + $this->assertEntityFieldQuery($query, array( + array('test_entity_bundle_key', 1), + array('test_entity_bundle_key', 2), + array('test_entity_bundle_key', 3), + array('test_entity_bundle_key', 4), + array('test_entity_bundle_key', 5), + array('test_entity_bundle_key', 6), + ), t('Test TableSort by property: ftid ASC in propertyQuery.'), TRUE); + + $_GET['sort'] = 'desc'; + $_GET['order'] = 'Id'; + $query = new EntityFieldQuery(); + $query + ->entityCondition('entity_type', 'test_entity_bundle_key') + ->tableSort($header); + $this->assertEntityFieldQuery($query, array( + array('test_entity_bundle_key', 6), + array('test_entity_bundle_key', 5), + array('test_entity_bundle_key', 4), + array('test_entity_bundle_key', 3), + array('test_entity_bundle_key', 2), + array('test_entity_bundle_key', 1), + ), t('Test TableSort by property: ftid DESC in propertyQuery.'), TRUE); + + $_GET['sort'] = 'asc'; + $_GET['order'] = 'Type'; + $query = new EntityFieldQuery(); + $query + ->entityCondition('entity_type', 'test_entity_bundle_key') + ->tableSort($header); + $this->assertEntityFieldQuery($query, array( + array('test_entity_bundle_key', 1), + array('test_entity_bundle_key', 2), + array('test_entity_bundle_key', 3), + array('test_entity_bundle_key', 4), + array('test_entity_bundle_key', 5), + array('test_entity_bundle_key', 6), + ), t('Test TableSort by entity: bundle ASC in propertyQuery.'), TRUE); + + $_GET['sort'] = 'desc'; + $_GET['order'] = 'Type'; + $query = new EntityFieldQuery(); + $query + ->entityCondition('entity_type', 'test_entity_bundle_key') + ->tableSort($header); + $this->assertEntityFieldQuery($query, array( + array('test_entity_bundle_key', 5), + array('test_entity_bundle_key', 6), + array('test_entity_bundle_key', 1), + array('test_entity_bundle_key', 2), + array('test_entity_bundle_key', 3), + array('test_entity_bundle_key', 4), + ), t('Test TableSort by entity: bundle DESC in propertyQuery.'), TRUE); + + // Test TableSort in field storage + $_GET['sort'] = 'asc'; + $_GET['order'] = 'Id'; + $header = array( + 'id' => array('data' => 'Id', 'type' => 'property', 'specifier' => 'ftid'), + 'type' => array('data' => 'Type', 'type' => 'entity', 'specifier' => 'bundle'), + 'field' => array('data' => 'Field', 'type' => 'field', 'specifier' => array('field' => $this->field_names[0], 'column' => 'value')), + ); + $query = new EntityFieldQuery(); + $query + ->entityCondition('entity_type', 'test_entity_bundle_key') + ->fieldCondition($this->fields[0], 'value', 0, '>') + ->tableSort($header); + $this->assertEntityFieldQuery($query, array( + array('test_entity_bundle_key', 1), + array('test_entity_bundle_key', 2), + array('test_entity_bundle_key', 3), + array('test_entity_bundle_key', 4), + array('test_entity_bundle_key', 5), + array('test_entity_bundle_key', 6), + ), t('Test TableSort by property: ftid ASC in field storage.'), TRUE); + + $_GET['sort'] = 'desc'; + $_GET['order'] = 'Id'; + $query = new EntityFieldQuery(); + $query + ->entityCondition('entity_type', 'test_entity_bundle_key') + ->fieldCondition($this->fields[0], 'value', 0, '>') + ->tableSort($header); + $this->assertEntityFieldQuery($query, array( + array('test_entity_bundle_key', 6), + array('test_entity_bundle_key', 5), + array('test_entity_bundle_key', 4), + array('test_entity_bundle_key', 3), + array('test_entity_bundle_key', 2), + array('test_entity_bundle_key', 1), + ), t('Test TableSort by property: ftid DESC in field storage.'), TRUE); + + $_GET['sort'] = 'asc'; + $_GET['order'] = 'Type'; + $query = new EntityFieldQuery(); + $query + ->entityCondition('entity_type', 'test_entity_bundle_key') + ->fieldCondition($this->fields[0], 'value', 0, '>') + ->tableSort($header) + ->entityOrderBy('entity_id', 'DESC'); + $this->assertEntityFieldQuery($query, array( + array('test_entity_bundle_key', 4), + array('test_entity_bundle_key', 3), + array('test_entity_bundle_key', 2), + array('test_entity_bundle_key', 1), + array('test_entity_bundle_key', 6), + array('test_entity_bundle_key', 5), + ), t('Test TableSort by entity: bundle ASC in field storage.'), TRUE); + + $_GET['sort'] = 'desc'; + $_GET['order'] = 'Type'; + $query = new EntityFieldQuery(); + $query + ->entityCondition('entity_type', 'test_entity_bundle_key') + ->fieldCondition($this->fields[0], 'value', 0, '>') + ->tableSort($header) + ->entityOrderBy('entity_id', 'ASC'); + $this->assertEntityFieldQuery($query, array( + array('test_entity_bundle_key', 5), + array('test_entity_bundle_key', 6), + array('test_entity_bundle_key', 1), + array('test_entity_bundle_key', 2), + array('test_entity_bundle_key', 3), + array('test_entity_bundle_key', 4), + ), t('Test TableSort by entity: bundle DESC in field storage.'), TRUE); + + $_GET['sort'] = 'asc'; + $_GET['order'] = 'Field'; + $query = new EntityFieldQuery(); + $query + ->entityCondition('entity_type', 'test_entity_bundle_key') + ->fieldCondition($this->fields[0], 'value', 0, '>') + ->tableSort($header); + $this->assertEntityFieldQuery($query, array( + array('test_entity_bundle_key', 1), + array('test_entity_bundle_key', 2), + array('test_entity_bundle_key', 3), + array('test_entity_bundle_key', 4), + array('test_entity_bundle_key', 5), + array('test_entity_bundle_key', 6), + ), t('Test TableSort by field ASC.'), TRUE); + + $_GET['sort'] = 'desc'; + $_GET['order'] = 'Field'; + $query = new EntityFieldQuery(); + $query + ->entityCondition('entity_type', 'test_entity_bundle_key') + ->fieldCondition($this->fields[0], 'value', 0, '>') + ->tableSort($header); + $this->assertEntityFieldQuery($query, array( + array('test_entity_bundle_key', 6), + array('test_entity_bundle_key', 5), + array('test_entity_bundle_key', 4), + array('test_entity_bundle_key', 3), + array('test_entity_bundle_key', 2), + array('test_entity_bundle_key', 1), + ), t('Test TableSort by field DESC.'), TRUE); + + unset($_GET['sort']); + unset($_GET['order']); + } + + /** * Fetches the results of an EntityFieldQuery and compares. * * @param $query