TripalFieldQuery.inc 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. <?php
  2. /**
  3. * Extends the EntityFieldQuery to support queries from multiple storage types.
  4. */
  5. class TripalFieldQuery extends EntityFieldQuery {
  6. protected $field_storage = array();
  7. public function execute() {
  8. // Give a chance for other modules to alter the query.
  9. drupal_alter('entity_query', $this);
  10. $this->altered = TRUE;
  11. // Initialize the pager.
  12. $this->initializePager();
  13. // If there are fields then we need to support multiple backends, call
  14. // the function for each one and merge the results.
  15. if ($this->fields) {
  16. // Build the list of all of the different field storage types used
  17. // for this query.
  18. foreach ($this->fields as $field) {
  19. $this->field_storage[$field['storage']['type']] = $field['storage']['module'];
  20. }
  21. // Initialize the results array.
  22. $results = array();
  23. // Iterate through the field storage types and call each one.
  24. foreach ($this->field_storage as $storage_type => $storage_module) {
  25. // Execute the query using the correct callback.
  26. $callback = $this->queryStorageCallback($storage_module);
  27. $st_results = call_user_func($callback, $this);
  28. // If this is the first storage type to be queries then save these
  29. // as the current results list.
  30. if (count($results) == 0) {
  31. $results = $st_results;
  32. }
  33. // If other results already exist then we want to find the intersection
  34. // of the two and only save those.
  35. else {
  36. $intersection = array(
  37. 'TripalEntity' => array(),
  38. );
  39. foreach ($st_results['TripalEntity'] as $entity_id => $stub) {
  40. if (array_key_exists($entity_id, $results['TripalEntity'])) {
  41. $intersection['TripalEntity'][$entity_id] = $stub;
  42. }
  43. }
  44. $results = $intersection;
  45. }
  46. }
  47. }
  48. // If there are no fields then default to the original
  49. // EntityFieldQuery() functionality.
  50. else {
  51. $results = call_user_func($this->queryCallback(), $this);
  52. }
  53. if ($results and $this->count) {
  54. return $results;
  55. }
  56. else {
  57. return $results;
  58. }
  59. }
  60. /**
  61. * Determines the query callback to use for this entity query.
  62. *
  63. * This function is a replacement for queryCallback() from the
  64. * parent EntityFieldQuery class because that class only allows a single
  65. * storage type per query.
  66. *
  67. * @param $storage
  68. * The storage module
  69. *
  70. * @throws EntityFieldQueryException
  71. * @return
  72. * A callback that can be used with call_user_func().
  73. *
  74. */
  75. public function queryStorageCallback($storage) {
  76. // Use the override from $this->executeCallback. It can be set either
  77. // while building the query, or using hook_entity_query_alter().
  78. if (function_exists($this->executeCallback)) {
  79. return $this->executeCallback;
  80. }
  81. // If there are no field conditions and sorts, and no execute callback
  82. // then we default to querying entity tables in SQL.
  83. if (empty($this->fields)) {
  84. return array($this, 'propertyQuery');
  85. }
  86. if ($storage) {
  87. // Use hook_field_storage_query() from the field storage.
  88. return $storage . '_field_storage_query';
  89. }
  90. else {
  91. throw new EntityFieldQueryException(t("Field storage engine not found."));
  92. }
  93. }
  94. }