Commit 72df65d1 authored by Dries's avatar Dries

- Patch #731426 by fago: recursed entity loading didn't work.

parent d058394c
......@@ -55,7 +55,6 @@ class DrupalDefaultEntityController implements DrupalEntityControllerInterface {
protected $idKey;
protected $revisionKey;
protected $revisionTable;
protected $query;
/**
* Constructor. Set basic variables.
......@@ -85,19 +84,16 @@ public function resetCache() {
}
public function load($ids = array(), $conditions = array()) {
$this->ids = $ids;
$this->conditions = $conditions;
$entities = array();
// Revisions are not statically cached, and require a different query to
// other conditions, so separate the revision id into its own variable.
if ($this->revisionKey && isset($this->conditions[$this->revisionKey])) {
$this->revisionId = $this->conditions[$this->revisionKey];
unset($this->conditions[$this->revisionKey]);
if ($this->revisionKey && isset($conditions[$this->revisionKey])) {
$revision_id = $conditions[$this->revisionKey];
unset($conditions[$this->revisionKey]);
}
else {
$this->revisionId = FALSE;
$revision_id = FALSE;
}
// Create a new variable which is either a prepared version of the $ids
......@@ -105,24 +101,24 @@ public function load($ids = array(), $conditions = array()) {
// were passed. The $ids array is reduced as items are loaded from cache,
// and we need to know if it's empty for this reason to avoid querying the
// database when all requested entities are loaded from cache.
$passed_ids = !empty($this->ids) ? array_flip($this->ids) : FALSE;
$passed_ids = !empty($ids) ? array_flip($ids) : FALSE;
// Try to load entities from the static cache, if the entity type supports
// static caching.
if ($this->cache) {
$entities += $this->cacheGet($this->ids, $this->conditions);
if ($this->cache && !$revision_id) {
$entities += $this->cacheGet($ids, $conditions);
// If any entities were loaded, remove them from the ids still to load.
if ($passed_ids) {
$this->ids = array_keys(array_diff_key($passed_ids, $entities));
$ids = array_keys(array_diff_key($passed_ids, $entities));
}
}
// Load any remaining entities from the database. This is the case if $ids
// is set to FALSE (so we load all entities), if there are any ids left to
// load, if loading a revision, or if $conditions was passed without $ids.
if ($this->ids === FALSE || $this->ids || $this->revisionId || ($this->conditions && !$passed_ids)) {
if ($ids === FALSE || $ids || $revision_id || ($conditions && !$passed_ids)) {
// Build the query.
$this->buildQuery();
$queried_entities = $this->query
$query = $this->buildQuery($ids, $conditions, $revision_id);
$queried_entities = $query
->execute()
->fetchAllAssoc($this->idKey);
}
......@@ -131,13 +127,13 @@ public function load($ids = array(), $conditions = array()) {
// which attaches fields (if supported by the entity type) and calls the
// entity type specific load callback, for example hook_node_load().
if (!empty($queried_entities)) {
$this->attachLoad($queried_entities);
$this->attachLoad($queried_entities, $revision_id);
$entities += $queried_entities;
}
if ($this->cache) {
// Add entities to the cache if we are not loading a revision.
if (!empty($queried_entities) && !$this->revisionId) {
if (!empty($queried_entities) && !$revision_id) {
$this->cacheSet($queried_entities);
}
}
......@@ -165,19 +161,19 @@ public function load($ids = array(), $conditions = array()) {
* being loaded needs to be augmented with additional data from another
* table, such as loading node type into comments or vocabulary machine name
* into terms, however it can also support $conditions on different tables.
* See NodeController::buildQuery() or TaxonomyTermController::buildQuery()
* See CommentController::buildQuery() or TaxonomyTermController::buildQuery()
* for examples.
*/
protected function buildQuery() {
$this->query = db_select($this->entityInfo['base table'], 'base');
protected function buildQuery($ids, $conditions = array(), $revision_id = FALSE) {
$query = db_select($this->entityInfo['base table'], 'base');
$this->query->addTag($this->entityType . '_load_multiple');
$query->addTag($this->entityType . '_load_multiple');
if ($this->revisionId) {
$this->query->join($this->revisionTable, 'revision', "revision.{$this->idKey} = base.{$this->idKey} AND revision.{$this->revisionKey} = :revisionId", array(':revisionId' => $this->revisionId));
if ($revision_id) {
$query->join($this->revisionTable, 'revision', "revision.{$this->idKey} = base.{$this->idKey} AND revision.{$this->revisionKey} = :revisionId", array(':revisionId' => $revision_id));
}
elseif ($this->revisionKey) {
$this->query->join($this->revisionTable, 'revision', "revision.{$this->revisionKey} = base.{$this->revisionKey}");
$query->join($this->revisionTable, 'revision', "revision.{$this->revisionKey} = base.{$this->revisionKey}");
}
// Add fields from the {entity} table.
......@@ -193,9 +189,9 @@ protected function buildQuery() {
// revision_uid before adding them to the query.
// TODO: This is node specific and has to be moved into NodeController.
unset($entity_revision_fields['timestamp']);
$this->query->addField('revision', 'timestamp', 'revision_timestamp');
$query->addField('revision', 'timestamp', 'revision_timestamp');
unset($entity_revision_fields['uid']);
$this->query->addField('revision', 'uid', 'revision_uid');
$query->addField('revision', 'uid', 'revision_uid');
// Remove all fields from the base table that are also fields by the same
// name in the revision table.
......@@ -205,19 +201,20 @@ protected function buildQuery() {
unset($entity_fields[$entity_field_keys[$name]]);
}
}
$this->query->fields('revision', $entity_revision_fields);
$query->fields('revision', $entity_revision_fields);
}
$this->query->fields('base', $entity_fields);
$query->fields('base', $entity_fields);
if ($this->ids) {
$this->query->condition("base.{$this->idKey}", $this->ids, 'IN');
if ($ids) {
$query->condition("base.{$this->idKey}", $ids, 'IN');
}
if ($this->conditions) {
foreach ($this->conditions as $field => $value) {
$this->query->condition('base.' . $field, $value);
if ($conditions) {
foreach ($conditions as $field => $value) {
$query->condition('base.' . $field, $value);
}
}
return $query;
}
/**
......@@ -231,10 +228,10 @@ protected function buildQuery() {
* $this->hookLoadArguments prior to calling the method.
* See NodeController::attachLoad() for an example.
*/
protected function attachLoad(&$queried_entities) {
protected function attachLoad(&$queried_entities, $revision_id = FALSE) {
// Attach fields.
if ($this->entityInfo['fieldable']) {
if ($this->revisionId) {
if ($revision_id) {
field_attach_load_revision($this->entityType, $queried_entities);
}
else {
......@@ -267,7 +264,7 @@ protected function attachLoad(&$queried_entities) {
protected function cacheGet($ids, $conditions = array()) {
$entities = array();
// Load any available entities from the internal cache.
if (!empty($this->entityCache) && !$this->revisionId) {
if (!empty($this->entityCache)) {
if ($ids) {
$entities += array_intersect_key($this->entityCache, array_flip($ids));
}
......
......@@ -1602,17 +1602,19 @@ function comment_load($cid) {
* special handling for comment objects.
*/
class CommentController extends DrupalDefaultEntityController {
protected function buildQuery() {
parent::buildQuery();
protected function buildQuery($ids, $conditions = array(), $revision_id = FALSE) {
$query = parent::buildQuery($ids, $conditions, $revision_id);
// Specify additional fields from the user and node tables.
$this->query->innerJoin('node', 'n', 'base.nid = n.nid');
$this->query->addField('n', 'type', 'node_type');
$this->query->innerJoin('users', 'u', 'base.uid = u.uid');
$this->query->addField('u', 'name', 'registered_name');
$this->query->fields('u', array('uid', 'signature', 'picture', 'data'));
$query->innerJoin('node', 'n', 'base.nid = n.nid');
$query->addField('n', 'type', 'node_type');
$query->innerJoin('users', 'u', 'base.uid = u.uid');
$query->addField('u', 'name', 'registered_name');
$query->fields('u', array('uid', 'signature', 'picture', 'data'));
return $query;
}
protected function attachLoad(&$comments) {
protected function attachLoad(&$comments, $revision_id = FALSE) {
// Setup standard comment properties.
foreach ($comments as $key => $comment) {
$comment = drupal_unpack($comment);
......@@ -1621,7 +1623,7 @@ protected function attachLoad(&$comments) {
$comment->node_type = 'comment_node_' . $comment->node_type;
$comments[$key] = $comment;
}
parent::attachLoad($comments);
parent::attachLoad($comments, $revision_id);
}
}
......
......@@ -3586,7 +3586,8 @@ function node_modules_enabled($modules) {
* special handling for node objects.
*/
class NodeController extends DrupalDefaultEntityController {
protected function attachLoad(&$nodes) {
protected function attachLoad(&$nodes, $revision_id = FALSE) {
// Create an array of nodes for each content type and pass this to the
// object type specific callback.
$typed_nodes = array();
......@@ -3602,6 +3603,6 @@ protected function attachLoad(&$nodes) {
}
}
$this->hookLoadArguments[] = array_keys($typed_nodes);
parent::attachLoad($nodes);
parent::attachLoad($nodes, $revision_id);
}
}
......@@ -865,32 +865,25 @@ function taxonomy_get_term_by_name($name) {
* that we match the condition on term name case-independently.
*/
class TaxonomyTermController extends DrupalDefaultEntityController {
protected $type;
public function load($ids = array(), $conditions = array()) {
if (isset($conditions['type'])) {
$this->type = $conditions['type'];
unset($conditions['type']);
}
return parent::load($ids, $conditions);
}
protected function buildQuery() {
parent::buildQuery();
$this->query->addTag('translatable');
$this->query->addTag('term_access');
protected function buildQuery($ids, $conditions = array(), $revision_id = FALSE) {
$query = parent::buildQuery($ids, $conditions, $revision_id);
$query->addTag('translatable');
$query->addTag('term_access');
// When name is passed as a condition use LIKE.
if (isset($this->conditions['name'])) {
$conditions = &$this->query->conditions();
foreach ($conditions as $key => $condition) {
if (isset($conditions['name'])) {
$query_conditions = &$query->conditions();
foreach ($query_conditions as $key => $condition) {
if ($condition['field'] == 'base.name') {
$conditions[$key]['operator'] = 'LIKE';
$conditions[$key]['value'] = db_like($conditions[$key]['value']);
$query_conditions[$key]['operator'] = 'LIKE';
$query_conditions[$key]['value'] = db_like($query_conditions[$key]['value']);
}
}
}
// Add the machine name field from the {taxonomy_vocabulary} table.
$this->query->innerJoin('taxonomy_vocabulary', 'v', 'base.vid = v.vid');
$this->query->addField('v', 'machine_name', 'vocabulary_machine_name');
$query->innerJoin('taxonomy_vocabulary', 'v', 'base.vid = v.vid');
$query->addField('v', 'machine_name', 'vocabulary_machine_name');
return $query;
}
protected function cacheGet($ids, $conditions = array()) {
......@@ -899,7 +892,7 @@ protected function cacheGet($ids, $conditions = array()) {
// LOWER() and drupal_strtolower() may return different results.
foreach ($terms as $term) {
$term_values = (array) $term;
if (isset($this->conditions['name']) && drupal_strtolower($this->conditions['name'] != drupal_strtolower($term_values['name']))) {
if (isset($conditions['name']) && drupal_strtolower($conditions['name'] != drupal_strtolower($term_values['name']))) {
unset($terms[$term->tid]);
}
}
......@@ -914,21 +907,13 @@ protected function cacheGet($ids, $conditions = array()) {
* special handling for taxonomy vocabulary objects.
*/
class TaxonomyVocabularyController extends DrupalDefaultEntityController {
protected function buildQuery() {
parent::buildQuery();
$this->query->addTag('translatable');
$this->query->orderBy('base.weight');
$this->query->orderBy('base.name');
}
protected function attachLoad(&$records) {
foreach ($records as $record) {
// If no node types are associated with a vocabulary, the LEFT JOIN will
// return a NULL value for type.
$queried_vocabularies[$record->vid] = $record;
}
$records = $queried_vocabularies;
parent::attachLoad($records);
protected function buildQuery($ids, $conditions = array(), $revision_id = FALSE) {
$query = parent::buildQuery($ids, $conditions, $revision_id);
$query->addTag('translatable');
$query->orderBy('base.weight');
$query->orderBy('base.name');
return $query;
}
}
......
......@@ -228,7 +228,8 @@ function user_load_multiple($uids = array(), $conditions = array(), $reset = FAL
* special handling for user objects.
*/
class UserController extends DrupalDefaultEntityController {
function attachLoad(&$queried_users) {
function attachLoad(&$queried_users, $revision_id = FALSE) {
// Build an array of user picture IDs so that these can be fetched later.
$picture_fids = array();
foreach ($queried_users as $key => $record) {
......@@ -263,7 +264,7 @@ function attachLoad(&$queried_users) {
}
// Call the default attachLoad() method. This will add fields and call
// hook_user_load().
parent::attachLoad($queried_users);
parent::attachLoad($queried_users, $revision_id);
}
}
......
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