Skip to content
GitLab
Projects
Groups
Snippets
Help
Loading...
Help
What's new
10
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Open sidebar
project
drupal
Commits
0c33e863
Commit
0c33e863
authored
Nov 14, 2010
by
webchick
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
#885014
by bojanz, chx: Fixed add missing pager and tablesort query support to EntityFieldQuery.
parent
4575c982
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
343 additions
and
2 deletions
+343
-2
includes/entity.inc
includes/entity.inc
+103
-1
includes/pager.inc
includes/pager.inc
+1
-1
modules/simpletest/tests/entity_query.test
modules/simpletest/tests/entity_query.test
+232
-0
modules/system/system.api.php
modules/system/system.api.php
+7
-0
No files found.
includes/entity.inc
View file @
0c33e863
...
...
@@ -418,6 +418,16 @@ class EntityFieldQuery {
*/
const
RETURN_ALL
=
NULL
;
/**
* TRUE if the query has already been altered, FALSE if it hasn't.
*
* Used in alter hooks to check for cloned queries that have already been
* altered prior to the clone (for example, the pager count query).
*
* @var boolean
*/
public
$altered
=
FALSE
;
/**
* Associative array of entity-generic metadata conditions.
*
...
...
@@ -461,6 +471,15 @@ class EntityFieldQuery {
*/
public
$range
=
array
();
/**
* The query pager data.
*
* @var array
*
* @see EntityFieldQuery::pager()
*/
public
$pager
=
array
();
/**
* Query behavior for deleted data.
*
...
...
@@ -798,6 +817,68 @@ public function range($start = NULL, $length = NULL) {
return
$this
;
}
/**
* 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.
* If not provided, one is automatically calculated.
*
* @return EntityFieldQuery
* The called object.
*/
public
function
pager
(
$limit
=
10
,
$element
=
NULL
)
{
if
(
!
isset
(
$element
))
{
$element
=
PagerDefault
::
$maxElement
++
;
}
elseif
(
$element
>=
PagerDefault
::
$maxElement
)
{
PagerDefault
::
$maxElement
=
$element
+
1
;
}
$this
->
pager
=
array
(
'limit'
=>
$limit
,
'element'
=>
$element
,
);
return
$this
;
}
/**
* Enable sortable tables for this query.
*
* @param $headers
* An EFQ Header array based on which the order clause is added to the query.
*
* @return EntityFieldQuery
* The called object.
*/
public
function
tableSort
(
&
$headers
)
{
// If 'field' is not initialized, the header columns aren't clickable
foreach
(
$headers
as
$key
=>
$header
)
{
if
(
is_array
(
$header
)
&&
isset
(
$header
[
'specifier'
]))
{
$headers
[
$key
][
'field'
]
=
''
;
}
}
$order
=
tablesort_get_order
(
$headers
);
$direction
=
tablesort_get_sort
(
$headers
);
foreach
(
$headers
as
$header
)
{
if
(
is_array
(
$header
)
&&
(
$header
[
'data'
]
==
$order
[
'name'
]))
{
if
(
$header
[
'type'
]
==
'field'
)
{
$this
->
fieldOrderBy
(
$header
[
'specifier'
][
'field'
],
$header
[
'specifier'
][
'column'
],
$direction
);
}
else
{
$header
[
'direction'
]
=
$direction
;
$this
->
order
[]
=
$header
;
}
}
}
return
$this
;
}
/**
* Filters on the data being deleted.
*
...
...
@@ -911,6 +992,10 @@ public function addMetaData($key, $object) {
public
function
execute
()
{
// Give a chance to other modules to alter the query.
drupal_alter
(
'entity_query'
,
$this
);
$this
->
altered
=
TRUE
;
// Initialize the pager.
$this
->
initializePager
();
// Execute the query using the correct callback.
$result
=
call_user_func
(
$this
->
queryCallback
(),
$this
);
...
...
@@ -966,7 +1051,6 @@ protected function propertyQuery() {
throw
new
EntityFieldQueryException
(
t
(
'For this query an entity type must be specified.'
));
}
$entity_type
=
$this
->
entityConditions
[
'entity_type'
][
'value'
];
unset
(
$this
->
entityConditions
[
'entity_type'
]);
$entity_info
=
entity_get_info
(
$entity_type
);
if
(
empty
(
$entity_info
[
'base table'
]))
{
throw
new
EntityFieldQueryException
(
t
(
'Entity %entity has no base table.'
,
array
(
'%entity'
=>
$entity_type
)));
...
...
@@ -1038,6 +1122,24 @@ protected function propertyQuery() {
return
$this
->
finishQuery
(
$select_query
);
}
/**
* Get the total number of results and initialize a pager for the query.
*
* This query can be detected by checking for ($this->pager && $this->count),
* which allows a driver to return 0 from the count query and disable
* the pager.
*/
function
initializePager
()
{
if
(
$this
->
pager
&&
!
$this
->
count
)
{
$page
=
pager_find_page
(
$this
->
pager
[
'element'
]);
$count_query
=
clone
$this
;
$this
->
pager
[
'total'
]
=
$count_query
->
count
()
->
execute
();
$this
->
pager
[
'start'
]
=
$page
*
$this
->
pager
[
'limit'
];
pager_default_initialize
(
$this
->
pager
[
'total'
],
$this
->
pager
[
'limit'
],
$this
->
pager
[
'element'
]);
$this
->
range
(
$this
->
pager
[
'start'
],
$this
->
pager
[
'limit'
]);
}
}
/**
* Finishes the query.
*
...
...
includes/pager.inc
View file @
0c33e863
...
...
@@ -20,7 +20,7 @@ class PagerDefault extends SelectQueryExtender {
*
* @var int
*/
static
protected
$maxElement
=
0
;
static
$maxElement
=
0
;
/**
* The number of elements per page to allow.
...
...
modules/simpletest/tests/entity_query.test
View file @
0c33e863
...
...
@@ -1104,6 +1104,238 @@ class EntityFieldQueryTestCase extends DrupalWebTestCase {
$this
->
assertTrue
(
$pass
,
t
(
'Cannot query across field storage engines.'
));
}
/**
* 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.
*
...
...
modules/system/system.api.php
View file @
0c33e863
...
...
@@ -350,6 +350,13 @@ function hook_entity_delete($entity, $type) {
* engines. Also, the default implementation presumes entities are stored in
* SQL, but the execute callback could instead query any other entity storage,
* local or remote.
*
* Note the $query->altered attribute which is TRUE in case the query has
* already been altered once. This happens with cloned queries.
* If there is a pager, then such a cloned query will be executed to count
* all elements. This query can be detected by checking for
* ($query->pager && $query->count), allowing the driver to return 0 from
* the count query and disable the pager.
*/
function
hook_entity_query_alter
(
$query
)
{
$query
->
executeCallback
=
'my_module_query_callback'
;
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment