Elgg  Version 5.0
LegacyQueryOptionsAdapter.php
Go to the documentation of this file.
1 <?php
2 
4 
5 use Elgg\Config;
19 
26 
34  public function normalizeOptions(array $options = []) {
35 
36  if (!isset($options['__original_options'])) {
37  $options['__original_options'] = $options;
38  }
39 
40  $options = array_merge($this->getDefaults(), $options);
41 
42  $options = $this->normalizeGuidOptions($options);
43  $options = $this->normalizeTimeOptions($options);
44 
45  $options = $this->normalizeAccessOptions($options);
46 
47  $options = $this->normalizeTypeSubtypeOptions($options);
48 
49  $options = $this->normalizeRelationshipOptions($options);
50  $options = $this->normalizeAnnotationOptions($options);
51  $options = $this->normalizeMetadataOptions($options);
52  $options = $this->normalizeMetadataSearchOptions($options);
53 
54  foreach (['selects', 'joins', 'wheres'] as $prop) {
55  if (empty($options[$prop])) {
56  $options[$prop] = [];
57  }
58 
59  if (!is_array($options[$prop])) {
60  if ($options[$prop]) {
61  $options[$prop] = [$options[$prop]];
62  }
63  }
64  }
65 
66  $options = $this->normalizeSelectClauses($options);
67  $options = $this->normalizeWhereClauses($options);
68  $options = $this->normalizeJoinClauses($options);
69  $options = $this->normalizeOrderByClauses($options);
70  return $this->normalizeGroupByClauses($options);
71  }
72 
77  protected function getDefaults() {
78  return [
79  'types' => null,
80  'subtypes' => null,
81  'type_subtype_pairs' => null,
82  'guids' => null,
83  'owner_guids' => null,
84  'container_guids' => null,
85  'access_ids' => null,
86 
87  'created_after' => null,
88  'created_before' => null,
89  'updated_after' => null,
90  'updated_before' => null,
91  'last_action_after' => null,
92  'last_action_before' => null,
93 
94  'sort_by' => [],
95  'order_by' => null,
96  'count' => false,
97  'limit' => elgg_get_config('default_limit'),
98  'offset' => 0,
99 
100  'selects' => [],
101  'wheres' => [],
102  'joins' => [],
103  'group_by' => null,
104 
105  'metadata_name_value_pairs' => null,
106  'metadata_name_value_pairs_operator' => 'AND',
107  'metadata_case_sensitive' => true,
108  'metadata_ids' => null,
109  'metadata_created_time_lower' => null,
110  'metadata_created_time_upper' => null,
111  'metadata_calculation' => null,
112 
113  'search_name_value_pairs' => null,
114 
115  'annotation_names' => null,
116  'annotation_values' => null,
117  'annotation_name_value_pairs' => null,
118  'annotation_name_value_pairs_operator' => 'AND',
119  'annotation_case_sensitive' => true,
120  'annotation_ids' => null,
121  'annotation_created_time_lower' => null,
122  'annotation_created_time_upper' => null,
123  'annotation_owner_guids' => null,
124  'annotation_calculation' => null,
125 
126  'relationship_pairs' => [],
127 
128  'relationship' => null,
129  'relationship_guid' => null,
130  'inverse_relationship' => false,
131  'relationship_join_on' => 'guid',
132  'relationship_created_time_lower' => null,
133  'relationship_created_time_upper' => null,
134 
135  'preload_owners' => false,
136  'preload_containers' => false,
137  'callback' => null,
138  'distinct' => true,
139 
140  'batch' => false,
141  'batch_inc_offset' => true,
142  'batch_size' => 25,
143 
144  '__ElggBatch' => null,
145  ];
146  }
147 
155  protected function normalizeAccessOptions(array $options = []) {
156  return self::normalizePluralOptions($options, ['access_id']);
157  }
158 
167  protected function normalizeTypeSubtypeOptions(array $options = []) {
168 
169  $singulars = [
170  'type',
171  'subtype',
172  ];
173 
174  $options = self::normalizePluralOptions($options, $singulars);
175 
176  // can't use helper function with type_subtype_pair because
177  // it's already an array...just need to merge it
178  if (isset($options['type_subtype_pair']) && isset($options['type_subtype_pairs'])) {
179  $options['type_subtype_pairs'] = array_merge((array) $options['type_subtype_pairs'], (array) $options['type_subtype_pair']);
180  } else if (isset($options['type_subtype_pair'])) {
181  $options['type_subtype_pairs'] = (array) $options['type_subtype_pair'];
182  } else if (isset($options['type_subtype_pairs'])) {
183  $options['type_subtype_pairs'] = (array) $options['type_subtype_pairs'];
184  } else if (isset($options['types'])) {
185  $options['type_subtype_pairs'] = [];
186  if ($options['types']) {
187  foreach ((array) $options['types'] as $type) {
188  $options['type_subtype_pairs'][$type] = isset($options['subtypes']) ? (array) $options['subtypes'] : null;
189  }
190  }
191  } else if (isset($options['subtypes'])) {
192  throw new InvalidArgumentException('If filtering for entity subtypes it is required to provide one or more entity types.');
193  }
194 
195  if (isset($options['type_subtype_pairs']) && is_array($options['type_subtype_pairs'])) {
196  foreach ($options['type_subtype_pairs'] as $type => $subtypes) {
197  if (!in_array($type, Config::ENTITY_TYPES)) {
198  elgg_log("'$type' is not a valid entity type", 'WARNING');
199  }
200 
201  if (!empty($subtypes) && !is_array($subtypes)) {
202  $options['type_subtype_pairs'][$type] = [$subtypes];
203  }
204  }
205  }
206 
207  unset($options['type_subtype_pair']);
208  unset($options['types']);
209  unset($options['subtypes']);
210 
211  return $options;
212  }
213 
221  protected function normalizeMetadataOptions(array $options = []) {
222  $singulars = [
223  'metadata_id',
224  'metadata_name',
225  'metadata_value',
226  'metadata_name_value_pair',
227  ];
228 
229  $options = self::normalizePluralOptions($options, $singulars);
230 
231  $options = $this->normalizePairedOptions('metadata', $options);
232 
233  $props = [
234  'metadata_ids',
235  'metadata_created_after',
236  'metadata_created_before',
237  ];
238 
239  foreach ($props as $prop) {
240  if (isset($options[$prop]) && empty($options['metadata_name_value_pairs'])) {
241  $options['metadata_name_value_pairs'][] = [
242  $prop => $options[$prop]
243  ];
244  }
245  }
246 
247  foreach ($options['metadata_name_value_pairs'] as $key => $pair) {
248  if ($pair instanceof Clause) {
249  continue;
250  }
251 
252  foreach ($props as $prop) {
253  if (!isset($pair[$prop])) {
254  $options['metadata_name_value_pairs'][$key][$prop] = elgg_extract($prop, $options);
255  }
256  }
257 
258  $options['metadata_name_value_pairs'][$key]['entity_guids'] = $options['guids'];
259  }
260 
261  $options['metadata_name_value_pairs'] = $this->removeKeyPrefix('metadata_', $options['metadata_name_value_pairs']);
262 
263  $defaults = [
264  'name' => null,
265  'value' => null,
266  'comparison' => '=',
267  'type' => ELGG_VALUE_STRING,
268  'case_sensitive' => true,
269  'entity_guids' => null,
270  'ids' => null,
271  'created_after' => null,
272  'created_before' => null,
273  ];
274 
275  foreach ($options['metadata_name_value_pairs'] as $key => $pair) {
276  if ($pair instanceof WhereClause) {
277  continue;
278  }
279 
280  $pair = array_merge($defaults, $pair);
281 
282  if (in_array($pair['name'], \ElggEntity::PRIMARY_ATTR_NAMES)) {
283  $clause = new AttributeWhereClause();
284  } else {
285  $clause = new MetadataWhereClause();
286  $clause->ids = (array) $pair['ids'];
287  $clause->entity_guids = (array) $pair['entity_guids'];
288  $clause->created_after = $pair['created_after'];
289  $clause->created_before = $pair['created_before'];
290  }
291 
292  $clause->names = (array) $pair['name'];
293  $clause->values = (array) $pair['value'];
294  $clause->comparison = $pair['comparison'];
295  $clause->value_type = $pair['type'];
296  $clause->case_sensitive = $pair['case_sensitive'];
297 
298  $options['metadata_name_value_pairs'][$key] = $clause;
299  }
300 
301  return $options;
302  }
303 
312  protected function normalizeMetadataSearchOptions(array $options = []) {
313  $singulars = [
314  'search_name_value_pair',
315  ];
316 
317  $options = self::normalizePluralOptions($options, $singulars);
318 
319  $options = $this->normalizePairedOptions('search', $options);
320 
321  foreach ($options['search_name_value_pairs'] as $key => $pair) {
322  if ($pair instanceof Clause) {
323  continue;
324  }
325 
326  $options['search_name_value_pairs'][$key]['entity_guids'] = $options['guids'];
327  }
328 
329  $options['search_name_value_pairs'] = $this->removeKeyPrefix('metadata_', $options['search_name_value_pairs']);
330 
331  $defaults = [
332  'name' => null,
333  'value' => null,
334  'comparison' => '=',
335  'type' => ELGG_VALUE_STRING,
336  'case_sensitive' => true,
337  'entity_guids' => null,
338  'ids' => null,
339  'created_after' => null,
340  'created_before' => null,
341  ];
342 
343  foreach ($options['search_name_value_pairs'] as $key => $pair) {
344  if ($pair instanceof WhereClause) {
345  continue;
346  }
347 
348  $pair = array_merge($defaults, $pair);
349 
350  if (in_array($pair['name'], \ElggEntity::PRIMARY_ATTR_NAMES)) {
351  $clause = new AttributeWhereClause();
352  } else {
353  $clause = new MetadataWhereClause();
354  $clause->ids = (array) $pair['ids'];
355  $clause->entity_guids = (array) $pair['entity_guids'];
356  $clause->created_after = $pair['created_after'];
357  $clause->created_before = $pair['created_before'];
358  }
359 
360  $clause->names = (array) $pair['name'];
361  $clause->values = (array) $pair['value'];
362  $clause->comparison = $pair['comparison'];
363  $clause->value_type = $pair['type'];
364  $clause->case_sensitive = $pair['case_sensitive'];
365 
366  $options['search_name_value_pairs'][$key] = $clause;
367  }
368 
369  return $options;
370  }
371 
379  protected function normalizeAnnotationOptions(array $options = []) {
380  $singulars = [
381  'annotation_id',
382  'annotation_name',
383  'annotation_value',
384  'annotation_name_value_pair',
385  ];
386 
387  $options = self::normalizePluralOptions($options, $singulars);
388 
389  $options = $this->normalizePairedOptions('annotation', $options);
390 
391  $props = [
392  'annotation_ids',
393  'annotation_owner_guids',
394  'annotation_created_after',
395  'annotation_created_before',
396  'annotation_sort_by_calculation',
397  ];
398 
399  foreach ($props as $prop) {
400  if (isset($options[$prop]) && empty($options['annotation_name_value_pairs'])) {
401  $options['annotation_name_value_pairs'][] = [
402  $prop => $options[$prop]
403  ];
404  }
405  }
406 
407  foreach ($options['annotation_name_value_pairs'] as $key => $pair) {
408  if ($pair instanceof WhereClause) {
409  continue;
410  }
411 
412  foreach ($props as $prop) {
413  if (!isset($pair[$prop])) {
414  $options['annotation_name_value_pairs'][$key][$prop] = elgg_extract($prop, $options);
415  }
416  }
417 
418  $options['annotation_name_value_pairs'][$key]['entity_guids'] = $options['guids'];
419  }
420 
421  $options['annotation_name_value_pairs'] = $this->removeKeyPrefix('annotation_', $options['annotation_name_value_pairs']);
422 
423  $defaults = [
424  'name' => null,
425  'value' => null,
426  'comparison' => '=',
427  'type' => ELGG_VALUE_STRING,
428  'case_sensitive' => true,
429  'entity_guids' => null,
430  'owner_guids' => null,
431  'ids' => null,
432  'enabled' => null,
433  'access_ids' => null,
434  'created_after' => null,
435  'created_before' => null,
436  'sort_by_calculation' => null,
437  ];
438 
439  foreach ($options['annotation_name_value_pairs'] as $key => $pair) {
440  if ($pair instanceof WhereClause) {
441  continue;
442  }
443 
444  $pair = array_merge($defaults, $pair);
445 
446  $clause = new AnnotationWhereClause();
447  $clause->ids = (array) $pair['ids'];
448  $clause->entity_guids = (array) $pair['entity_guids'];
449  $clause->owner_guids = (array) $pair['owner_guids'];
450  $clause->created_after = $pair['created_after'];
451  $clause->created_before = $pair['created_before'];
452  $clause->names = (array) $pair['name'];
453  $clause->values = (array) $pair['value'];
454  $clause->comparison = $pair['comparison'];
455  $clause->value_type = $pair['type'];
456  $clause->case_sensitive = $pair['case_sensitive'];
457  $clause->enabled = $pair['enabled'];
458  $clause->access_ids = (array) $pair['access_ids'];
459  $clause->sort_by_calculation = $pair['sort_by_calculation'];
460 
461  if ($clause->sort_by_calculation && empty($options['order_by'])) {
462  $clause->sort_by_direction = 'desc';
463  }
464 
465  $options['annotation_name_value_pairs'][$key] = $clause;
466  }
467 
468  return $options;
469  }
470 
479  protected function normalizePairedOptions($type = 'metadata', array $options = []) {
480  if (!is_array($options["{$type}_name_value_pairs"])) {
481  $options["{$type}_name_value_pairs"] = [];
482  }
483 
484  $case_sensitive_default = elgg_extract("{$type}_case_sensitive", $options, true);
485 
494  if (isset($options["{$type}_name_value_pairs"]['name'])) {
495  $options["{$type}_name_value_pairs"][] = [
496  'name' => $options["{$type}_name_value_pairs"]['name'],
497  'value' => elgg_extract('value', $options["{$type}_name_value_pairs"]),
498  'comparison' => elgg_extract('operand', $options["{$type}_name_value_pairs"], '='),
499  'case_sensitive' => elgg_extract('case_sensitive', $options["{$type}_name_value_pairs"], $case_sensitive_default)
500  ];
501  unset($options["{$type}_name_value_pairs"]['name']);
502  unset($options["{$type}_name_value_pairs"]['value']);
503  unset($options["{$type}_name_value_pairs"]['operand']);
504  unset($options["{$type}_name_value_pairs"]['case_sensitive']);
505  }
506 
518  foreach ($options["{$type}_name_value_pairs"] as $index => $pair) {
519  if (is_array($pair)) {
520  $keys = array_keys($pair);
521  if (count($keys) === 1 && is_string($keys[0]) && $keys[0] !== 'name' && $keys[0] !== 'value') {
522  $options["{$type}_name_value_pairs"][$index] = [
523  'name' => $keys[0],
524  'value' => $pair[$keys[0]],
525  'comparison' => '=',
526  ];
527  }
528  }
529  }
530 
538  foreach ($options["{$type}_name_value_pairs"] as $index => $values) {
539  if ($values instanceof Clause) {
540  continue;
541  }
542 
543  if (is_array($values)) {
544  if (isset($values['name']) || isset($values['value'])) {
545  continue;
546  }
547  }
548 
549  $options["{$type}_name_value_pairs"][$index] = [
550  'name' => $index,
551  'value' => $values,
552  'comparison' => '=',
553  ];
554  }
555 
556  if (isset($options["{$type}_names"]) || isset($options["{$type}_values"])) {
557  $options["{$type}_name_value_pairs"][] = [
558  'name' => isset($options["{$type}_names"]) ? (array) $options["{$type}_names"] : null,
559  'value' => isset($options["{$type}_values"]) ? (array) $options["{$type}_values"] : null,
560  'comparison' => '=',
561  ];
562  }
563 
564  foreach ($options["{$type}_name_value_pairs"] as $key => $value) {
565  if ($value instanceof Clause) {
566  continue;
567  }
568 
569  if (!isset($value['case_sensitive'])) {
570  $value['case_sensitive'] = $case_sensitive_default;
571  }
572 
573  if (!isset($value['type'])) {
574  if (isset($value['value']) && is_bool($value['value'])) {
575  $value['value'] = (int) $value['value'];
576  }
577 
578  if (isset($value['value']) && is_int($value['value'])) {
579  $value['type'] = ELGG_VALUE_INTEGER;
580  } else {
581  $value['type'] = ELGG_VALUE_STRING;
582  }
583  }
584 
585  if (!isset($value['comparison']) && isset($value['operand'])) {
586  $value['comparison'] = $value['operand'];
587  unset($value['operand']);
588  }
589 
590  $options["{$type}_name_value_pairs"][$key] = $value;
591  }
592 
593  unset($options["{$type}_names"]);
594  unset($options["{$type}_values"]);
595  unset($options["{$type}_case_sensitive"]);
596 
597  return $options;
598  }
599 
607  protected function normalizeRelationshipOptions(array $options = []) {
608 
609  $pair = [];
610 
611  $defaults = [
612  'relationship_ids' => null,
613  'relationship' => null,
614  'relationship_guid' => null,
615  'inverse_relationship' => false,
616  'relationship_join_on' => 'guid',
617  'relationship_created_after' => null,
618  'relationship_created_before' => null,
619  ];
620 
621  foreach (array_keys($defaults) as $prop) {
622  if (isset($options[$prop])) {
623  $pair[$prop] = $options[$prop];
624  }
625 
626  unset($options[$prop]);
627  }
628 
629  $options['relationship_pairs'] = (array) $options['relationship_pairs'];
630  $options['relationship_pairs'][] = $pair;
631 
632  foreach ($options['relationship_pairs'] as $index => $relationship_pair) {
633  if ($relationship_pair instanceof WhereClause) {
634  continue;
635  }
636 
637  $options['relationship_pairs'][$index] = array_merge($defaults, $relationship_pair);
638  }
639 
640  $options['relationship_pairs'] = $this->removeKeyPrefix('relationship_', $options['relationship_pairs']);
641 
642  foreach ($options['relationship_pairs'] as $key => $pair) {
643  if ($pair instanceof WhereClause) {
644  continue;
645  }
646 
647  if (!$pair['relationship'] && !$pair['guid'] && !$pair['ids']) {
648  unset($options['relationship_pairs'][$key]);
649  continue;
650  }
651 
652  $clause = new RelationshipWhereClause();
653  $clause->ids = (array) $pair['ids'];
654  $clause->names = (array) $pair['relationship'];
655 
656  $clause->join_on = $pair['join_on'];
657  $clause->inverse = $pair['inverse_relationship'];
658  if ($clause->inverse) {
659  $clause->object_guids = (array) $pair['guid'];
660  } else {
661  $clause->subject_guids = (array) $pair['guid'];
662  }
663 
664  $clause->created_after = $pair['created_after'];
665  $clause->created_before = $pair['created_before'];
666 
667 
668  $options['relationship_pairs'][$key] = $clause;
669  }
670 
671  return $options;
672  }
673 
681  protected function normalizeGuidOptions(array $options = []) {
682 
683  $singulars = [
684  'guid',
685  'owner_guid',
686  'container_guid',
687  'annotation_owner_guid',
688  ];
689 
690  $options = self::normalizePluralOptions($options, $singulars);
691 
692  $names = [
693  'guids',
694  'owner_guids',
695  'container_guids',
696  'annotation_owner_guids',
697  'relationship_guid',
698  ];
699 
700  foreach ($names as $name) {
701  if (!isset($options[$name])) {
702  continue;
703  }
704 
705  if (!is_array($options[$name])) {
707  }
708 
709  foreach ($options[$name] as $key => $value) {
710  if ($value === false || $value === '') {
711  unset($options[$name][$key]);
712  }
713  }
714  }
715 
716  return $options;
717  }
718 
726  protected function normalizeTimeOptions(array $options = []) {
727 
728  $props = [
729  'modified',
730  'created',
731  'updated',
732  'metadata_created',
733  'annotation_created',
734  'relationship_created',
735  'last_action',
736  'posted',
737  ];
738 
739  $bounds = ['time_lower', 'time_upper', 'after', 'before'];
740 
741  foreach ($props as $prop) {
742  foreach ($bounds as $bound) {
743  $prop_name = "{$prop}_{$bound}";
744 
745  $new_prop_name = $prop_name;
746  $new_prop_name = str_replace('modified', 'updated', $new_prop_name);
747  $new_prop_name = str_replace('posted', 'created', $new_prop_name);
748  $new_prop_name = str_replace('time_lower', 'after', $new_prop_name);
749  $new_prop_name = str_replace('time_upper', 'before', $new_prop_name);
750 
751  if (!isset($options[$new_prop_name])) {
752  $options[$new_prop_name] = elgg_extract($prop_name, $options);
753  }
754  }
755  }
756 
757  return $options;
758  }
759 
768  protected function removeKeyPrefix($prefix, array $array = []) {
769  foreach ($array as $key => $value) {
770  $new_key = $key;
771  if (str_starts_with($key, $prefix)) {
772  $new_key = substr($key, strlen($prefix));
773  }
774 
775  if (!isset($array[$new_key])) {
776  $array[$new_key] = $value;
777  }
778 
779  if ($new_key !== $key) {
780  unset($array[$key]);
781  }
782 
783  if (is_array($array[$new_key])) {
784  $array[$new_key] = $this->removeKeyPrefix($prefix, $array[$new_key]);
785  }
786  }
787 
788  return $array;
789  }
790 
798  protected function normalizeSelectClauses(array $options = []) {
799 
800  $options = self::normalizePluralOptions($options, ['select']);
801 
802  foreach ($options['selects'] as $key => $clause) {
803  if (empty($clause)) {
804  unset($options['selects'][$key]);
805  continue;
806  }
807 
808  if ($clause instanceof SelectClause) {
809  continue;
810  }
811 
812  $options['selects'][$key] = new SelectClause($clause);
813  }
814 
815  return $options;
816  }
817 
825  protected function normalizeWhereClauses(array $options = []) {
826 
827  $options = self::normalizePluralOptions($options, ['where']);
828 
829  foreach ($options['wheres'] as $key => $clause) {
830  if (empty($clause)) {
831  unset($options['wheres'][$key]);
832  continue;
833  }
834 
835  if ($clause instanceof WhereClause) {
836  continue;
837  }
838 
839  $options['wheres'][$key] = new WhereClause($clause);
840  }
841 
842  return $options;
843  }
844 
852  protected function normalizeJoinClauses(array $options = []) {
853 
854  $options = self::normalizePluralOptions($options, ['join']);
855 
856  foreach ($options['joins'] as $key => $join) {
857  if (empty($join)) {
858  unset($options['joins'][$key]);
859  continue;
860  }
861 
862  if ($join instanceof JoinClause) {
863  continue;
864  }
865 
866  if (is_string($join)) {
867  preg_match('/((LEFT|INNER|RIGHT)\s+)?JOIN\s+(.*?)\s+((as\s+)?(.*?)\s+)ON\s+(.*)$/im', $join, $parts);
868 
869  $type = !empty($parts[2]) ? strtolower($parts[2]) : 'inner';
870  $table = $parts[3];
871  $alias = $parts[6];
872  $condition = preg_replace('/\r|\n/', '', $parts[7]);
873 
874  $dbprefix = elgg_get_config('dbprefix');
875  if (!elgg_is_empty($dbprefix) && str_starts_with($table, $dbprefix)) {
876  $table = substr($table, strlen($dbprefix));
877  }
878 
879  $clause = new JoinClause($table, $alias, $condition, $type);
880  $options['joins'][$key] = $clause;
881  }
882  }
883 
884  return $options;
885  }
886 
894  protected function normalizeOrderByClauses(array $options = []) {
895 
896  $order_by = $options['order_by'];
897  $options['order_by'] = [];
898 
899  if (!empty($order_by)) {
900  if (is_string($order_by)) {
901  $orders = explode(',', $order_by);
902  } else if (is_array($order_by)) {
903  $orders = $order_by;
904  } else {
905  $orders = [$order_by];
906  }
907 
908  foreach ($orders as $order) {
909  if ($order instanceof OrderByClause) {
910  $options['order_by'][] = $order;
911  continue;
912  }
913 
914  $order = trim($order);
915  $parts = [];
916  if (preg_match('/(.*)(?=\s+(asc|desc))/i', $order, $parts)) {
917  $column = $parts[1];
918  $direction = $parts[2];
919  } else {
920  $column = $order;
921  $direction = 'ASC';
922  }
923 
924  $direction = strtoupper($direction) === 'DESC' ? 'DESC' : 'ASC';
925 
926  $options['order_by'][] = new OrderByClause($column, $direction);
927  }
928  }
929 
930  $sort_by = $options['sort_by'];
931  if (isset($sort_by['property'])) {
932  // single array variant, convert to an array of sort_by specs
933  $options['sort_by'] = [$sort_by];
934  }
935 
936  foreach ($options['sort_by'] as $sort_spec) {
937  $clause = new EntitySortByClause();
938  $clause->property = elgg_extract('property', $sort_spec);
939  $clause->property_type = elgg_extract('property_type', $sort_spec);
940  $clause->join_type = elgg_extract('join_type', $sort_spec, 'inner');
941  $clause->direction = elgg_extract('direction', $sort_spec);
942  $clause->signed = elgg_extract('signed', $sort_spec);
943  $clause->inverse_relationship = elgg_extract('inverse_relationship', $sort_spec);
944  $clause->relationship_guid = elgg_extract('relationship_guid', $sort_spec);
945 
946  $options['order_by'][] = $clause;
947  }
948 
949  return $options;
950  }
951 
959  protected function normalizeGroupByClauses(array $options = []) {
960 
961  if (!isset($options['having'])) {
962  $options['having'] = [];
963  } else {
964  if (!is_array($options['having'])) {
965  $options['having'] = [$options['having']];
966  }
967 
968  foreach ($options['having'] as $key => $expr) {
969  if ($expr instanceof HavingClause) {
970  continue;
971  }
972 
973  $options['having'][$key] = new HavingClause($expr);
974  }
975  }
976 
977  if (empty($options['group_by'])) {
978  $options['group_by'] = [];
979  }
980 
981  if (is_string($options['group_by'])) {
982  $options['group_by'] = (array) trim($options['group_by']);
983  }
984 
985  foreach ($options['group_by'] as $key => $expr) {
986  if ($expr instanceof GroupByClause) {
987  continue;
988  }
989 
990  $options['group_by'][$key] = new GroupByClause($expr);
991  }
992 
993  return $options;
994  }
995 
1003  public static function normalizeMetastringOptions(array $options = []) {
1004 
1005  // support either metastrings_type or metastring_type
1006  // because I've made this mistake many times and hunting it down is a pain...
1007  $type = elgg_extract('metastring_type', $options, null);
1008  $type = elgg_extract('metastrings_type', $options, $type);
1009 
1010  $options['metastring_type'] = $type;
1011 
1012  // support annotation_ and annotations_ because they're way too easy to confuse
1013  $prefixes = ['metadata_', 'annotation_', 'annotations_'];
1014 
1015  // map the metadata_* options to metastring_* options
1016  $map = [
1017  'names' => 'metastring_names',
1018  'values' => 'metastring_values',
1019  'case_sensitive' => 'metastring_case_sensitive',
1020  'owner_guids' => 'metastring_owner_guids',
1021  'created_time_lower' => 'metastring_created_time_lower',
1022  'created_time_upper' => 'metastring_created_time_upper',
1023  'calculation' => 'metastring_calculation',
1024  'ids' => 'metastring_ids',
1025  ];
1026 
1027  foreach ($prefixes as $prefix) {
1028  $singulars = ["{$prefix}name", "{$prefix}value", "{$prefix}owner_guid", "{$prefix}id"];
1029  $options = self::normalizePluralOptions($options, $singulars);
1030 
1031  foreach ($map as $specific => $normalized) {
1032  $key = $prefix . $specific;
1033  if (isset($options[$key])) {
1034  $options[$normalized] = $options[$key];
1035  }
1036  }
1037  }
1038 
1039  return $options;
1040  }
1041 
1054  public static function normalizePluralOptions($options, $singulars) {
1055  foreach ($singulars as $singular) {
1056  $plural = $singular . 's';
1057 
1058  if (array_key_exists($singular, $options)) {
1059  if ($options[$singular] === ELGG_ENTITIES_ANY_VALUE) {
1060  $options[$plural] = $options[$singular];
1061  } else {
1062  // Test for array refs #2641
1063  if (!is_array($options[$singular])) {
1064  $options[$plural] = [$options[$singular]];
1065  } else {
1066  $options[$plural] = $options[$singular];
1067  }
1068  }
1069  }
1070 
1071  unset($options[$singular]);
1072  }
1073 
1074  return $options;
1075  }
1076 }
Exception thrown if an argument is not of the expected type.
elgg_get_config(string $name, $default=null)
Get an Elgg configuration value.
$defaults
Generic entity header upload helper.
Definition: header.php:6
const PRIMARY_ATTR_NAMES
Definition: ElggEntity.php:50
if(!$user||!$user->canDelete()) $name
Definition: delete.php:22
Interface that allows resolving statements and/or extending query builder.
Definition: Clause.php:14
const ENTITY_TYPES
Definition: Config.php:251
const ELGG_VALUE_INTEGER
Value types.
Definition: constants.php:111
Builds quereis for matching entities by their attributes.
$column
Definition: add.php:10
Extends QueryBuilder with JOIN clauses.
Definition: JoinClause.php:12
Builds clauses for filtering entities by their properties in entity_relationships table...
Extends QueryBuilder with SELECT clauses.
Extends QueryBuilder with clauses necesary to sort entity lists by entity properties.
$type
Definition: delete.php:22
Builds queries for matching annotations against their properties.
Extends QueryBuilder with GROUP BY statements.
$keys
Definition: access.php:31
$options
Elgg admin footer.
Definition: footer.php:6
$value
Definition: generic.php:51
elgg_is_empty($value)
Check if a value isn&#39;t empty, but allow 0 and &#39;0&#39;.
Definition: input.php:176
elgg_extract($key, $array, $default=null, bool $strict=true)
Checks for $array[$key] and returns its value if it exists, else returns $default.
Definition: elgglib.php:254
Extends QueryBuilder with HAVING clauses.
elgg_log($message, $level=\Psr\Log\LogLevel::NOTICE)
Log a message.
Definition: elgglib.php:86
const ELGG_ENTITIES_ANY_VALUE
Constant to request the value of a parameter be ignored in elgg_get_*() functions.
Definition: constants.php:21
Extends QueryBuilder with ORDER BY clauses.
if($container instanceof ElggGroup &&$container->guid!=elgg_get_page_owner_guid()) $key
Definition: summary.php:44
Builds a clause from closure or composite expression.
Definition: WhereClause.php:12
const ELGG_VALUE_STRING
Definition: constants.php:112
$subtypes
$index
Definition: gallery.php:40
Builds clauses for filtering entities by properties in metadata table.
$table
Definition: cron.php:64