|
@@ -331,5 +331,239 @@ class TripalEntityController extends EntityAPIController {
|
|
|
return FALSE;
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Override the load function.
|
|
|
+ *
|
|
|
+ * A TripalEntity may have a large number of fields attached which may
|
|
|
+ * slow down the loading of pages and web services. Therefore, we only
|
|
|
+ * want to attach fields that are needed.
|
|
|
+ *
|
|
|
+ * @param $ids
|
|
|
+ * The list of entity IDs to load.
|
|
|
+ * @param $conditions
|
|
|
+ * The list of key/value filters for querying the entity.
|
|
|
+ * @param $field_ids
|
|
|
+ * The list of numeric field IDs for fields that should be included.
|
|
|
+ */
|
|
|
+ public function load($ids = array(), $conditions = array(), $field_ids = array()) {
|
|
|
+
|
|
|
+ $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($conditions[$this->revisionKey])) {
|
|
|
+ $revision_id = $conditions[$this->revisionKey];
|
|
|
+ unset($conditions[$this->revisionKey]);
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $revision_id = FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Create a new variable which is either a prepared version of the $ids
|
|
|
+ // array for later comparison with the entity cache, or FALSE if no $ids
|
|
|
+ // 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($ids) ? array_flip($ids) : FALSE;
|
|
|
+
|
|
|
+ // Try to load entities from the static cache.
|
|
|
+ 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) {
|
|
|
+ $ids = array_keys(array_diff_key($passed_ids, $entities));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Support the entitycache module if activated.
|
|
|
+ if (!empty($this->entityInfo['entity cache']) && !$revision_id && $ids && !$conditions) {
|
|
|
+ $cached_entities = EntityCacheControllerHelper::entityCacheGet($this, $ids, $conditions);
|
|
|
+ // If any entities were loaded, remove them from the ids still to load.
|
|
|
+ $ids = array_diff($ids, array_keys($cached_entities));
|
|
|
+ $entities += $cached_entities;
|
|
|
+
|
|
|
+ // Add loaded entities to the static cache if we are not loading a
|
|
|
+ // revision.
|
|
|
+ if ($this->cache && !empty($cached_entities) && !$revision_id) {
|
|
|
+ $this->cacheSet($cached_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 or if loading a revision.
|
|
|
+ if (!($this->cacheComplete && $ids === FALSE && !$conditions) && ($ids === FALSE || $ids || $revision_id)) {
|
|
|
+ $queried_entities = array();
|
|
|
+ foreach ($this->query($ids, $conditions, $revision_id) as $record) {
|
|
|
+ // Skip entities already retrieved from cache.
|
|
|
+ if (isset($entities[$record->{$this->idKey}])) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ // For DB-based entities take care of serialized columns.
|
|
|
+ if (!empty($this->entityInfo['base table'])) {
|
|
|
+ $schema = drupal_get_schema($this->entityInfo['base table']);
|
|
|
+
|
|
|
+ foreach ($schema['fields'] as $field => $info) {
|
|
|
+ if (!empty($info['serialize']) && isset($record->$field)) {
|
|
|
+ $record->$field = unserialize($record->$field);
|
|
|
+ // Support automatic merging of 'data' fields into the entity.
|
|
|
+ if (!empty($info['merge']) && is_array($record->$field)) {
|
|
|
+ foreach ($record->$field as $key => $value) {
|
|
|
+ $record->$key = $value;
|
|
|
+ }
|
|
|
+ unset($record->$field);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ $queried_entities[$record->{$this->idKey}] = $record;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Pass all entities loaded from the database through $this->attachLoad(),
|
|
|
+ // 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, $revision_id, $field_ids);
|
|
|
+ $entities += $queried_entities;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Entitycache module support: Add entities to the entity cache if we are
|
|
|
+ // not loading a revision.
|
|
|
+ if (!empty($this->entityInfo['entity cache']) && !empty($queried_entities) && !$revision_id) {
|
|
|
+ EntityCacheControllerHelper::entityCacheSet($this, $queried_entities);
|
|
|
+ }
|
|
|
+
|
|
|
+ if ($this->cache) {
|
|
|
+ // Add entities to the cache if we are not loading a revision.
|
|
|
+ if (!empty($queried_entities) && !$revision_id) {
|
|
|
+ $this->cacheSet($queried_entities);
|
|
|
+
|
|
|
+ // Remember if we have cached all entities now.
|
|
|
+ if (!$conditions && $ids === FALSE) {
|
|
|
+ $this->cacheComplete = TRUE;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // Ensure that the returned array is ordered the same as the original
|
|
|
+ // $ids array if this was passed in and remove any invalid ids.
|
|
|
+ if ($passed_ids && $passed_ids = array_intersect_key($passed_ids, $entities)) {
|
|
|
+ foreach ($passed_ids as $id => $value) {
|
|
|
+ $passed_ids[$id] = $entities[$id];
|
|
|
+ }
|
|
|
+ $entities = $passed_ids;
|
|
|
+ }
|
|
|
+ return $entities;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Override the attachLoad function.
|
|
|
+ *
|
|
|
+ * A TripalEntity may have a large number of fields attached which may
|
|
|
+ * slow down the loading of pages and web services. Therefore, we only
|
|
|
+ * want to attach fields that are needed.
|
|
|
+ *
|
|
|
+ *
|
|
|
+ *
|
|
|
+ * @param $queried_entities
|
|
|
+ * The list of queried
|
|
|
+ * @param $revision_id
|
|
|
+ * @param $field_ids
|
|
|
+ */
|
|
|
+ protected function attachLoad(&$queried_entities, $revision_id = FALSE,
|
|
|
+ $field_ids = array()) {
|
|
|
+
|
|
|
+ // Get the list of fields for later user.
|
|
|
+ $fields = field_info_fields();
|
|
|
+ // A temporary holding place for field instances (so we don't have
|
|
|
+ // to keep looking them up in our loop below).
|
|
|
+ $instances = array();
|
|
|
+
|
|
|
+ // Add in the content_type field by default. It should always be
|
|
|
+ // attached.
|
|
|
+ $ids = array();
|
|
|
+ $ct = field_info_field('content_type');
|
|
|
+ $ids[] = $ct['id'];
|
|
|
+ $field_ids += $ids;
|
|
|
+
|
|
|
+
|
|
|
+ // Attach fields.
|
|
|
+ if ($this->entityInfo['fieldable']) {
|
|
|
+ if ($revision_id) {
|
|
|
+ $function = 'field_attach_load_revision';
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $function = 'field_attach_load';
|
|
|
+ }
|
|
|
+ foreach ($queried_entities as $entity) {
|
|
|
+ $entity_ids = array();
|
|
|
+ $entity_ids += $field_ids;
|
|
|
+ // Iterate through the fields and find those that are set to
|
|
|
+ // 'auto_attach' and which are attached to this bundle.
|
|
|
+ foreach ($fields as $field) {
|
|
|
+ $field_name = $field['field_name'];
|
|
|
+ if (array_key_exists('TripalEntity', $field['bundles'])) {
|
|
|
+ foreach ($field['bundles']['TripalEntity'] as $bundle_name) {
|
|
|
+ if ($bundle_name == $entity->bundle) {
|
|
|
+ // Get the instance of this field for this bundle.
|
|
|
+ if (!array_key_exists($field_name . '-' . $bundle_name, $instances)) {
|
|
|
+ $instance = field_info_instance('TripalEntity', $field['field_name'], $bundle_name);
|
|
|
+ $instances[$field_name . '-' . $bundle_name] = $instance;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ $instance = $instances[$field_name . '-' . $bundle_name];
|
|
|
+ }
|
|
|
+ // If the 'auto_attach' is set then add this field id to our
|
|
|
+ // list.
|
|
|
+ if (array_key_exists('settings', $instance) and
|
|
|
+ array_key_exists('auto_attach', $instance['settings']) and
|
|
|
+ $instance['settings']['auto_attach'] === TRUE) {
|
|
|
+ $entity_ids[] = $field['id'];
|
|
|
+ }
|
|
|
+ // If the field is not auto attached then we want to add an
|
|
|
+ // empty default valuea nd add an 'unattached' key to
|
|
|
+ // clue in other things that there may be data, it's just
|
|
|
+ // not attached.
|
|
|
+ else {
|
|
|
+ $value = array(
|
|
|
+ 'und' => array(
|
|
|
+ 0 => array(
|
|
|
+ 'value' => '',
|
|
|
+ '#unattached' => TRUE,
|
|
|
+ ),
|
|
|
+ ),
|
|
|
+ );
|
|
|
+ $entity->$field_name = $value;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Iterate through each field that should be added and attach it.
|
|
|
+ foreach ($entity_ids as $field_id) {
|
|
|
+ $options = array();
|
|
|
+ $options['field_id'] = $field_id;
|
|
|
+ $function($this->entityType, array($entity->id => $entity), FIELD_LOAD_CURRENT, $options);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // Call hook_entity_load().
|
|
|
+ foreach (module_implements('entity_load') as $module) {
|
|
|
+ $function = $module . '_entity_load';
|
|
|
+ $function($queried_entities, $this->entityType);
|
|
|
+ }
|
|
|
+ // Call hook_TYPE_load(). The first argument for hook_TYPE_load() are
|
|
|
+ // always the queried entities, followed by additional arguments set in
|
|
|
+ // $this->hookLoadArguments.
|
|
|
+ $args = array_merge(array($queried_entities), $this->hookLoadArguments);
|
|
|
+ foreach (module_implements($this->entityInfo['load hook']) as $module) {
|
|
|
+ call_user_func_array($module . '_' . $this->entityInfo['load hook'], $args);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|