|
@@ -57,17 +57,22 @@ class TripalFieldQuery extends EntityFieldQuery {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- $this->relationshipConditions[$table_alias] = [
|
|
|
- 'field' => $field,
|
|
|
- 'value' => $value,
|
|
|
- 'op' => $op,
|
|
|
- ];
|
|
|
+ if ($table_alias) {
|
|
|
+ $this->relationshipConditions[$table_alias] = [
|
|
|
+ 'field' => $field,
|
|
|
+ 'value' => $value,
|
|
|
+ 'op' => $op,
|
|
|
+ ];
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
* Overrides the EntityFieldQuery::execute() function.
|
|
|
*/
|
|
|
public function execute() {
|
|
|
+ // Initialize the results array.
|
|
|
+ $results = array();
|
|
|
+
|
|
|
// Give a chance for other modules to alter the query.
|
|
|
drupal_alter('entity_query', $this);
|
|
|
$this->altered = TRUE;
|
|
@@ -85,51 +90,71 @@ class TripalFieldQuery extends EntityFieldQuery {
|
|
|
$this->field_storage[$field['storage']['type']] = $field['storage']['module'];
|
|
|
}
|
|
|
|
|
|
- // Initialize the results array.
|
|
|
- $results = array();
|
|
|
-
|
|
|
// Iterate through the field storage types and call each one.
|
|
|
foreach ($this->field_storage as $storage_type => $storage_module) {
|
|
|
- // Execute the query using the correct callback.
|
|
|
$callback = $this->queryStorageCallback($storage_module);
|
|
|
-
|
|
|
$st_results = call_user_func($callback, $this);
|
|
|
- // If this is the first storage type to be queries then save these
|
|
|
- // as the current results list.
|
|
|
- if (count($results) == 0) {
|
|
|
- $results = $st_results;
|
|
|
- }
|
|
|
- // If other results already exist then we want to find the intersection
|
|
|
- // of the two and only save those.
|
|
|
- else {
|
|
|
- $intersection = array(
|
|
|
- 'TripalEntity' => array(),
|
|
|
- );
|
|
|
- foreach ($st_results['TripalEntity'] as $entity_id => $stub) {
|
|
|
- if (array_key_exists($entity_id, $results['TripalEntity'])) {
|
|
|
- $intersection['TripalEntity'][$entity_id] = $stub;
|
|
|
- }
|
|
|
- }
|
|
|
- $results = $intersection;
|
|
|
- }
|
|
|
+ $results = $this->_intersectResults($results, $st_results);
|
|
|
}
|
|
|
}
|
|
|
- // If there are no fields then default to the original
|
|
|
- // EntityFieldQuery() functionality.
|
|
|
- else {
|
|
|
+
|
|
|
+ // If we have relationships, then handle those.
|
|
|
+ if (!empty($this->relationships)) {
|
|
|
+ $st_results = tripal_field_storage_query($this);
|
|
|
+ $results = $this->_intersectResults($results, $st_results);
|
|
|
+
|
|
|
+ // Are there any other callbacks that need running other than
|
|
|
+ // propertyQuery as we would have run those with the relationships.
|
|
|
$callback = $this->queryCallback();
|
|
|
- $results = call_user_func($callback, $this);
|
|
|
+ if ($callback != 'propertyQuery' and $callback != 'tripal_field_storage_query') {
|
|
|
+ $st_results = call_user_func($callback, $this);
|
|
|
+ $results = $this->_intersectResults($results, $st_results);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ // There are no fields or relationships so just use the default
|
|
|
+ // callback for the query.
|
|
|
+ else if (!$this->fields){
|
|
|
+ $callback = $this->queryCallback();
|
|
|
+ $st_results = call_user_func($callback, $this);
|
|
|
+ $results = $this->_intersectResults($results, $st_results);
|
|
|
}
|
|
|
|
|
|
// If this is a count query then it should return a numeric value.
|
|
|
- if ($results and $this->count) {
|
|
|
- if (!is_numeric($results)) {
|
|
|
- throw new Exception('Query callback function did not provide a numeric count value: ' . $this->queryCallback());
|
|
|
+ if ($this->count) {
|
|
|
+ if (!$results or !is_array($results)) {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+ return count($results['TripalEntity']);
|
|
|
+ }
|
|
|
+ return $results;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * Generates an intersection of results from different storage back-ends.
|
|
|
+ */
|
|
|
+ protected function _intersectResults($current_results, $new_results) {
|
|
|
+ if ($this->count) {
|
|
|
+ return $new_results;
|
|
|
+ }
|
|
|
+ // If we currently don't have any results then just allow all through.
|
|
|
+ // This is the first result set.
|
|
|
+ if (empty($current_results)) {
|
|
|
+ return $new_results;
|
|
|
+ }
|
|
|
+
|
|
|
+ // Iterate through all of the new results and only include those that
|
|
|
+ // exist in both the current and new.
|
|
|
+ $intersection = [];
|
|
|
+ foreach ($new_results['TripalEntity'] as $entity_id => $stub) {
|
|
|
+ if (array_key_exists($entity_id, $current_results['TripalEntity'])) {
|
|
|
+ $intersection[$entity_id] = $stub;
|
|
|
}
|
|
|
- return $results;
|
|
|
+ }
|
|
|
+ if (count($intersection) > 0) {
|
|
|
+ return ['TripalEntity' => $intersection];
|
|
|
}
|
|
|
else {
|
|
|
- return $results;
|
|
|
+ return [];
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -144,11 +169,6 @@ class TripalFieldQuery extends EntityFieldQuery {
|
|
|
return $this->executeCallback;
|
|
|
}
|
|
|
|
|
|
- // If we have relationships then we need to join on the tripal_entity
|
|
|
- // table and that always occurs using the tripal_field_storage_query.
|
|
|
- if (!empty($this->relationships)) {
|
|
|
- return 'tripal_field_storage_query';
|
|
|
- }
|
|
|
// If there are no field conditions and sorts, and no execute callback
|
|
|
// then we default to querying entity tables in SQL.
|
|
|
if (empty($this->fields)) {
|
|
@@ -200,12 +220,6 @@ class TripalFieldQuery extends EntityFieldQuery {
|
|
|
return $this->executeCallback;
|
|
|
}
|
|
|
|
|
|
- // If we have relationships then we need to join on the tripal_entity
|
|
|
- // table and that always occurs using the tripal_field_storage_query.
|
|
|
- if (!empty($this->relationships)) {
|
|
|
- return 'tripal_field_storage_query';
|
|
|
- }
|
|
|
-
|
|
|
// If there are no field conditions and sorts, and no execute callback
|
|
|
// then we default to querying entity tables in SQL.
|
|
|
if (empty($this->fields)) {
|