Elgg  Version 3.0
LegacyQueryOptionsAdapter.php
Go to the documentation of this file.
1 <?php
2 
3 namespace Elgg\Database;
4 
6 use Elgg\Config;
20 use ElggEntity;
21 
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 
43 
44  $options = $this->normalizeGuidOptions($options);
45  $options = $this->normalizeTimeOptions($options);
46 
47  $options = $this->normalizeAccessOptions($options);
48 
49  $options = $this->normalizeTypeSubtypeOptions($options);
50 
51  $options = $this->normalizePrivateSettingOptions($options);
52  $options = $this->normalizeRelationshipOptions($options);
53  $options = $this->normalizeAnnotationOptions($options);
54  $options = $this->normalizeMetadataOptions($options);
55  $options = $this->normalizeMetadataSearchOptions($options);
56 
57  foreach (['selects', 'joins', 'wheres'] as $prop) {
58  if (empty($options[$prop])) {
59  $options[$prop] = [];
60  }
61 
62  if (!is_array($options[$prop])) {
63  if ($options[$prop]) {
64  $options[$prop] = [$options[$prop]];
65  }
66  }
67  }
68 
69  $options = $this->normalizeSelectClauses($options);
70  $options = $this->normalizeWhereClauses($options);
71  $options = $this->normalizeJoinClauses($options);
72  $options = $this->normalizeOrderByClauses($options);
73  $options = $this->normalizeGroupByClauses($options);
74 
75  return $options;
76  }
77 
82  protected function getDefaults() {
83  return [
84  'types' => null,
85  'subtypes' => null,
86  'type_subtype_pairs' => null,
87  'guids' => null,
88  'owner_guids' => null,
89  'container_guids' => null,
90  'access_ids' => null,
91 
92  'created_after' => null,
93  'created_before' => null,
94  'updated_after' => null,
95  'updated_before' => null,
96  'last_action_after' => null,
97  'last_action_before' => null,
98 
99  'sort_by' => [],
100  'order_by' => null,
101  'count' => false,
102  'limit' => elgg_get_config('default_limit'),
103  'offset' => 0,
104 
105  'selects' => [],
106  'wheres' => [],
107  'joins' => [],
108  'group_by' => null,
109 
110  'metadata_name_value_pairs' => null,
111  'metadata_name_value_pairs_operator' => 'AND',
112  'metadata_case_sensitive' => true,
113  'order_by_metadata' => null,
114  'metadata_ids' => null,
115  'metadata_created_time_lower' => null,
116  'metadata_created_time_upper' => null,
117  'metadata_calculation' => null,
118 
119  'search_name_value_pairs' => null,
120 
121  'annotation_names' => null,
122  'annotation_values' => null,
123  'annotation_name_value_pairs' => null,
124  'annotation_name_value_pairs_operator' => 'AND',
125  'annotation_case_sensitive' => true,
126  'order_by_annotation' => null,
127  'annotation_ids' => null,
128  'annotation_created_time_lower' => null,
129  'annotation_created_time_upper' => null,
130  'annotation_owner_guids' => null,
131  'annotation_calculation' => null,
132 
133  'relationship_pairs' => [],
134 
135  'relationship' => null,
136  'relationship_guid' => null,
137  'inverse_relationship' => false,
138  'relationship_join_on' => 'guid',
139  'relationship_created_time_lower' => null,
140  'relationship_created_time_upper' => null,
141 
142  'private_setting_names' => null,
143  'private_setting_values' => null,
144  'private_setting_name_value_pairs' => null,
145  'private_setting_name_value_pairs_operator' => 'AND',
146  'private_setting_name_prefix' => '',
147  'private_setting_case_sensitive' => false,
148 
149  'preload_owners' => false,
150  'preload_containers' => false,
151  'callback' => null,
152  'distinct' => true,
153 
154  'batch' => false,
155  'batch_inc_offset' => true,
156  'batch_size' => 25,
157 
158  '__ElggBatch' => null,
159  ];
160  }
161 
169  protected function normalizeAccessOptions(array $options = []) {
170 
171  $options = self::normalizePluralOptions($options, ['access_id']);
172 
173  return $options;
174  }
175 
184  protected function normalizeTypeSubtypeOptions(array $options = []) {
185 
186  $singulars = [
187  'type',
188  'subtype',
189  ];
190 
191  $options = self::normalizePluralOptions($options, $singulars);
192 
193  // can't use helper function with type_subtype_pair because
194  // it's already an array...just need to merge it
195  if (isset($options['type_subtype_pair']) && isset($options['type_subtype_pairs'])) {
196  $options['type_subtype_pairs'] = array_merge((array) $options['type_subtype_pairs'], (array) $options['type_subtype_pair']);
197  } else if (isset($options['type_subtype_pair'])) {
198  $options['type_subtype_pairs'] = (array) $options['type_subtype_pair'];
199  } else if (isset($options['type_subtype_pairs'])) {
200  $options['type_subtype_pairs'] = (array) $options['type_subtype_pairs'];
201  } else if (isset($options['types'])) {
202  $options['type_subtype_pairs'] = [];
203  if ($options['types']) {
204  foreach ((array) $options['types'] as $type) {
205  $options['type_subtype_pairs'][$type] = isset($options['subtypes']) ? (array) $options['subtypes'] : null;
206  }
207  }
208  }
209 
210  if (isset($options['type_subtype_pairs']) && is_array($options['type_subtype_pairs'])) {
211  foreach ($options['type_subtype_pairs'] as $type => $subtypes) {
212  if (!in_array($type, Config::getEntityTypes())) {
213  elgg_log("'$type' is not a valid entity type", 'WARNING');
214  }
215  if (!empty($subtypes) && !is_array($subtypes)) {
216  $options['type_subtype_pairs'][$type] = [$subtypes];
217  }
218  }
219  }
220 
221  unset($options['type_subtype_pair']);
222  unset($options['types']);
223  unset($options['subtypes']);
224 
225  return $options;
226  }
227 
235  protected function normalizeMetadataOptions(array $options = []) {
236  $singulars = [
237  'metadata_id',
238  'metadata_name',
239  'metadata_value',
240  'metadata_name_value_pair',
241  ];
242 
243  $options = self::normalizePluralOptions($options, $singulars);
244 
245  $options = $this->normalizePairedOptions('metadata', $options);
246 
247  if (isset($options['order_by_metadata'])) {
248  $name = elgg_extract('name', $options['order_by_metadata']);
249  $direction = strtoupper(elgg_extract('direction', $options['order_by_metadata'], 'asc'));
250  $as = elgg_extract('as', $options['order_by_metadata']);
251 
252  if ($name) {
253  $options['sort_by'][] = [
254  'property' => $name,
255  'direction' => in_array($direction, ['ASC', 'DESC']) ? $direction : null,
256  'signed' => $as === ELGG_VALUE_INTEGER,
257  'property_type' => 'metadata',
258  ];
259  }
260 
261  $options['order_by'] = null;
262  $options['order_by_metadata'] = null;
263  }
264 
265  $props = [
266  'metadata_ids',
267  'metadata_created_after',
268  'metadata_created_before',
269  ];
270 
271  foreach ($props as $prop) {
272  if (isset($options[$prop]) && empty($options['metadata_name_value_pairs'])) {
273  $options['metadata_name_value_pairs'][] = [
274  $prop => $options[$prop]
275  ];
276  }
277  }
278 
279  foreach ($options['metadata_name_value_pairs'] as $key => $pair) {
280  if ($pair instanceof Clause) {
281  continue;
282  }
283 
284  foreach ($props as $prop) {
285  if (!isset($pair[$prop])) {
286  $options['metadata_name_value_pairs'][$key][$prop] = elgg_extract($prop, $options);
287  }
288  }
289 
290  $options['metadata_name_value_pairs'][$key]['entity_guids'] = $options['guids'];
291  }
292 
293  $options['metadata_name_value_pairs'] = $this->removeKeyPrefix('metadata_', $options['metadata_name_value_pairs']);
294 
295  $defaults = [
296  'name' => null,
297  'value' => null,
298  'comparison' => '=',
299  'type' => ELGG_VALUE_STRING,
300  'case_sensitive' => true,
301  'entity_guids' => null,
302  'ids' => null,
303  'created_after' => null,
304  'created_before' => null,
305  ];
306 
307  foreach ($options['metadata_name_value_pairs'] as $key => $pair) {
308  if ($pair instanceof WhereClause) {
309  continue;
310  }
311 
312  $pair = array_merge($defaults, $pair);
313 
314  if (in_array(strtolower($pair['comparison']), ['in', 'eq', '=']) && is_string($pair['value'])) {
315  // Apparently this madness is supported
316  // \Elgg\Integration\ElggCoreGetEntitiesFromMetadataTest::testElggApiGettersEntityMetadataNVPValidNValidVOperandIn
317  $pair['value'] = array_map(function ($e) {
318  return trim($e, ' \"\'');
319  }, explode(',', $pair['value']));
320  }
321 
322  if (in_array($pair['name'], ElggEntity::$primary_attr_names)) {
323  $clause = new AttributeWhereClause();
324  } else {
325  $clause = new MetadataWhereClause();
326  $clause->ids = (array) $pair['ids'];
327  $clause->entity_guids = (array) $pair['entity_guids'];
328  $clause->created_after = $pair['created_after'];
329  $clause->created_before = $pair['created_before'];
330  }
331 
332  $clause->names = (array) $pair['name'];
333  $clause->values = (array) $pair['value'];
334  $clause->comparison = $pair['comparison'];
335  $clause->value_type = $pair['type'];
336  $clause->case_sensitive = $pair['case_sensitive'];
337 
338  $options['metadata_name_value_pairs'][$key] = $clause;
339  }
340 
341  return $options;
342  }
343 
352  protected function normalizeMetadataSearchOptions(array $options = []) {
353  $singulars = [
354  'search_name_value_pair',
355  ];
356 
357  $options = self::normalizePluralOptions($options, $singulars);
358 
359  $options = $this->normalizePairedOptions('search', $options);
360 
361  foreach ($options['search_name_value_pairs'] as $key => $pair) {
362  if ($pair instanceof Clause) {
363  continue;
364  }
365 
366  $options['search_name_value_pairs'][$key]['entity_guids'] = $options['guids'];
367  }
368 
369  $options['search_name_value_pairs'] = $this->removeKeyPrefix('metadata_', $options['search_name_value_pairs']);
370 
371  $defaults = [
372  'name' => null,
373  'value' => null,
374  'comparison' => '=',
375  'type' => ELGG_VALUE_STRING,
376  'case_sensitive' => true,
377  'entity_guids' => null,
378  'ids' => null,
379  'created_after' => null,
380  'created_before' => null,
381  ];
382 
383  foreach ($options['search_name_value_pairs'] as $key => $pair) {
384  if ($pair instanceof WhereClause) {
385  continue;
386  }
387 
388  $pair = array_merge($defaults, $pair);
389 
390  if (in_array(strtolower($pair['comparison']), ['in', 'eq', '=']) && is_string($pair['value'])) {
391  // Apparently this madness is supported
392  // \Elgg\Integration\ElggCoreGetEntitiesFromMetadataTest::testElggApiGettersEntityMetadataNVPValidNValidVOperandIn
393  $pair['value'] = array_map(function ($e) {
394  return trim($e, ' \"\'');
395  }, explode(',', $pair['value']));
396  }
397 
398  if (in_array($pair['name'], ElggEntity::$primary_attr_names)) {
399  $clause = new AttributeWhereClause();
400  } else {
401  $clause = new MetadataWhereClause();
402  $clause->ids = (array) $pair['ids'];
403  $clause->entity_guids = (array) $pair['entity_guids'];
404  $clause->created_after = $pair['created_after'];
405  $clause->created_before = $pair['created_before'];
406  }
407 
408  $clause->names = (array) $pair['name'];
409  $clause->values = (array) $pair['value'];
410  $clause->comparison = $pair['comparison'];
411  $clause->value_type = $pair['type'];
412  $clause->case_sensitive = $pair['case_sensitive'];
413 
414  $options['search_name_value_pairs'][$key] = $clause;
415  }
416 
417  return $options;
418  }
419 
427  protected function normalizeAnnotationOptions(array $options = []) {
428  $singulars = [
429  'annotation_id',
430  'annotation_name',
431  'annotation_value',
432  'annotation_name_value_pair',
433  ];
434 
435  $options = self::normalizePluralOptions($options, $singulars);
436 
437  $options = $this->normalizePairedOptions('annotation', $options);
438 
439  if (isset($options['order_by_annotation'])) {
440  $name = elgg_extract('name', $options['order_by_annotation']);
441  $direction = strtoupper(elgg_extract('direction', $options['order_by_annotation'], 'asc'));
442  $as = elgg_extract('as', $options['order_by_annotation']);
443 
444  if ($name) {
445  $options['sort_by'][] = [
446  'property' => $name,
447  'property_type' => 'annotation',
448  'direction' => in_array($direction, ['ASC', 'DESC']) ? $direction : null,
449  'signed' => $as === ELGG_VALUE_INTEGER,
450  ];
451  }
452 
453  $options['order_by'] = null;
454  $options['order_by_annotation'] = null;
455  }
456 
457  $props = [
458  'annotation_ids',
459  'annotation_owner_guids',
460  'annotation_created_after',
461  'annotation_created_before',
462  'annotation_sort_by_calculation',
463  ];
464 
465  foreach ($props as $prop) {
466  if (isset($options[$prop]) && empty($options['annotation_name_value_pairs'])) {
467  $options['annotation_name_value_pairs'][] = [
468  $prop => $options[$prop]
469  ];
470  }
471  }
472 
473  foreach ($options['annotation_name_value_pairs'] as $key => $pair) {
474  if ($pair instanceof WhereClause) {
475  continue;
476  }
477 
478  foreach ($props as $prop) {
479  if (!isset($pair[$prop])) {
480  $options['annotation_name_value_pairs'][$key][$prop] = elgg_extract($prop, $options);
481  }
482  }
483 
484  $options['annotation_name_value_pairs'][$key]['entity_guids'] = $options['guids'];
485  }
486 
487  $options['annotation_name_value_pairs'] = $this->removeKeyPrefix('annotation_', $options['annotation_name_value_pairs']);
488 
489  $defaults = [
490  'name' => null,
491  'value' => null,
492  'comparison' => '=',
493  'type' => ELGG_VALUE_STRING,
494  'case_sensitive' => true,
495  'entity_guids' => null,
496  'owner_guids' => null,
497  'ids' => null,
498  'enabled' => null,
499  'access_ids' => null,
500  'created_after' => null,
501  'created_before' => null,
502  'sort_by_calculation' => null,
503  ];
504 
505  foreach ($options['annotation_name_value_pairs'] as $key => $pair) {
506  if ($pair instanceof WhereClause) {
507  continue;
508  }
509 
510  $pair = array_merge($defaults, $pair);
511 
512  $clause = new AnnotationWhereClause();
513  $clause->ids = (array) $pair['ids'];
514  $clause->entity_guids = (array) $pair['entity_guids'];
515  $clause->owner_guids = (array) $pair['owner_guids'];
516  $clause->created_after = $pair['created_after'];
517  $clause->created_before = $pair['created_before'];
518  $clause->names = (array) $pair['name'];
519  $clause->values = (array) $pair['value'];
520  $clause->comparison = $pair['comparison'];
521  $clause->value_type = $pair['type'];
522  $clause->case_sensitive = $pair['case_sensitive'];
523  $clause->enabled = $pair['enabled'];
524  $clause->access_ids = (array) $pair['access_ids'];
525  $clause->sort_by_calculation = $pair['sort_by_calculation'];
526 
527  if ($clause->sort_by_calculation && empty($options['order_by'])) {
528  $clause->sort_by_direction = 'desc';
529  }
530 
531  $options['annotation_name_value_pairs'][$key] = $clause;
532  }
533 
534  return $options;
535  }
536 
544  protected function normalizePrivateSettingOptions(array $options = []) {
545 
546  $singulars = [
547  'private_setting_name',
548  'private_setting_value',
549  'private_setting_name_value_pair',
550  ];
551 
552  $options = self::normalizePluralOptions($options, $singulars);
553 
554  $options = $this->normalizePairedOptions('private_setting', $options);
555 
556  foreach ($options['private_setting_name_value_pairs'] as $key => $pair) {
557  if ($pair instanceof WhereClause) {
558  continue;
559  }
560 
561  $options['private_setting_name_value_pairs'][$key]['entity_guids'] = $options['guids'];
562  }
563 
564  $options['private_setting_name_value_pairs'] = $this->removeKeyPrefix('private_setting_', $options['private_setting_name_value_pairs']);
565 
566  $prefix = null;
567  if (isset($options['private_setting_name_prefix'])) {
568  $prefix = $options['private_setting_name_prefix'];
569  unset($options['private_setting_name_prefix']);
570  }
571 
572  $defaults = [
573  'name' => null,
574  'value' => null,
575  'comparison' => '=',
576  'type' => ELGG_VALUE_STRING,
577  'case_sensitive' => true,
578  'entity_guids' => null,
579  'ids' => null,
580  ];
581 
582  foreach ($options['private_setting_name_value_pairs'] as $key => $pair) {
583  if ($pair instanceof WhereClause) {
584  continue;
585  }
586 
587  $pair = array_merge($defaults, $pair);
588 
589  $names = (array) elgg_extract('name', $pair);
590  $names = array_map(function($name) use ($prefix) {
591  return $prefix ? "$prefix$name" : $name;
592  }, $names);
593 
594  $clause = new PrivateSettingWhereClause();
595  $clause->ids = (array) $pair['ids'];
596  $clause->entity_guids = (array) $pair['entity_guids'];
597  $clause->names = $names;
598  $clause->values = (array) $pair['value'];
599  $clause->comparison = $pair['comparison'];
600  $clause->value_type = $pair['type'];
601  $clause->case_sensitive = $pair['case_sensitive'];
602 
603  $options['private_setting_name_value_pairs'][$key] = $clause;
604  }
605 
606  return $options;
607  }
608 
617  protected function normalizePairedOptions($type = 'metadata', array $options = []) {
618  if (!is_array($options["{$type}_name_value_pairs"])) {
619  $options["{$type}_name_value_pairs"] = [];
620  }
621 
622  if (isset($options["{$type}_name_value_pairs"]['name'])) {
623  $options["{$type}_name_value_pairs"][] = [
624  'name' => $options["{$type}_name_value_pairs"]['name'],
625  'value' => elgg_extract('value', $options["{$type}_name_value_pairs"]),
626  'comparison' => elgg_extract('operand', $options["{$type}_name_value_pairs"], '='),
627  'case_sensitive' => elgg_extract('case_sensitive', $options["{$type}_name_value_pairs"], true)
628  ];
629  unset($options["{$type}_name_value_pairs"]['name']);
630  unset($options["{$type}_name_value_pairs"]['value']);
631  unset($options["{$type}_name_value_pairs"]['operand']);
632  unset($options["{$type}_name_value_pairs"]['case_sensitive']);
633  }
634 
635  foreach ($options["{$type}_name_value_pairs"] as $index => $pair) {
636  if (is_array($pair)) {
637  $keys = array_keys($pair);
638  if (sizeof($keys) === 1 && is_string($keys[0])) {
639  $options["{$type}_name_value_pairs"][$index] = [
640  'name' => $keys[0],
641  'value' => $pair[$keys[0]],
642  'comparison' => '=',
643  ];
644  }
645  }
646  }
647 
648  foreach ($options["{$type}_name_value_pairs"] as $index => $values) {
649  if ($values instanceof Clause) {
650  continue;
651  }
652 
653  if (is_array($values)) {
654  if (isset($values['name'])) {
655  continue;
656  }
657  }
658  $options["{$type}_name_value_pairs"][$index] = [
659  'name' => $index,
660  'value' => $values,
661  'comparison' => '=',
662  ];
663  }
664 
665  if (isset($options["{$type}_names"]) || isset($options["{$type}_values"])) {
666  $options["{$type}_name_value_pairs"][] = [
667  'name' => isset($options["{$type}_names"]) ? (array) $options["{$type}_names"] : null,
668  'value' => isset($options["{$type}_values"]) ? (array) $options["{$type}_values"] : null,
669  'comparison' => '=',
670  ];
671  }
672 
673  foreach ($options["{$type}_name_value_pairs"] as $key => $value) {
674  if ($value instanceof Clause) {
675  continue;
676  }
677 
678  if (!isset($value['case_sensitive'])) {
679  $value['case_sensitive'] = elgg_extract("{$type}_case_sensitive", $options, true);
680  }
681  if (!isset($value['type'])) {
682  if (is_bool($value['value'])) {
683  $value['value'] = (int) $value['value'];
684  }
685  if (is_int($value['value'])) {
686  $value['type'] = ELGG_VALUE_INTEGER;
687  } else {
688  $value['type'] = ELGG_VALUE_STRING;
689  }
690  }
691  if (!isset($value['comparison']) && isset($value['operand'])) {
692  $value['comparison'] = $value['operand'];
693  unset($value['operand']);
694  }
695 
696  $options["{$type}_name_value_pairs"][$key] = $value;
697  }
698 
699  unset($options["{$type}_names"]);
700  unset($options["{$type}_values"]);
701  unset($options["{$type}_case_sensitive"]);
702 
703  return $options;
704  }
705 
713  protected function normalizeRelationshipOptions(array $options = []) {
714 
715  $pair = [];
716 
717  $defaults = [
718  'relationship_ids' => null,
719  'relationship' => null,
720  'relationship_guid' => null,
721  'inverse_relationship' => false,
722  'relationship_join_on' => 'guid',
723  'relationship_created_after' => null,
724  'relationship_created_before' => null,
725  ];
726 
727  foreach (array_keys($defaults) as $prop) {
728  if (isset($options[$prop])) {
729  $pair[$prop] = $options[$prop];
730  }
731  unset($options[$prop]);
732  }
733 
734  $options['relationship_pairs'] = (array) $options['relationship_pairs'];
735  $options['relationship_pairs'][] = $pair;
736 
737  foreach ($options['relationship_pairs'] as $index => $relationship_pair) {
738  if ($relationship_pair instanceof WhereClause) {
739  continue;
740  }
741 
742  $options['relationship_pairs'][$index] = array_merge($defaults, $relationship_pair);
743  }
744 
745  $options['relationship_pairs'] = $this->removeKeyPrefix('relationship_', $options['relationship_pairs']);
746 
747  foreach ($options['relationship_pairs'] as $key => $pair) {
748  if ($pair instanceof WhereClause) {
749  continue;
750  }
751 
752  $pair = array_merge($defaults, $pair);
753 
754  if (!$pair['relationship'] && !$pair['relationship_guid']) {
755  unset($options['relationship_pairs'][$key]);
756  continue;
757  }
758 
759  $clause = new RelationshipWhereClause();
760  $clause->ids = (array) $pair['ids'];
761  $clause->names = (array) $pair['relationship'];
762 
763  $clause->join_on = $pair['join_on'];
764  $clause->inverse = $pair['inverse_relationship'];
765  if ($clause->inverse) {
766  $clause->object_guids = (array) $pair['guid'];
767  } else {
768  $clause->subject_guids = (array) $pair['guid'];
769  }
770  $clause->created_after = $pair['created_after'];
771  $clause->created_before = $pair['created_before'];
772 
773 
774  $options['relationship_pairs'][$key] = $clause;
775  }
776 
777  return $options;
778  }
779 
787  protected function normalizeGuidOptions(array $options = []) {
788 
789  $singulars = [
790  'guid',
791  'owner_guid',
792  'container_guid',
793  'annotation_owner_guid',
794  ];
795 
796  $options = self::normalizePluralOptions($options, $singulars);
797 
798  $names = [
799  'guids',
800  'owner_guids',
801  'container_guids',
802  'annotation_owner_guids',
803  'relationship_guid',
804  ];
805 
806  foreach ($names as $name) {
807  if (!isset($options[$name])) {
808  continue;
809  }
810 
811  if (!is_array($options[$name])) {
813  }
814 
815  foreach ($options[$name] as $key => $value) {
816  if ($value === false || $value === '') {
817  unset($options[$name][$key]);
818  continue;
819  }
820  }
821  }
822 
823  return $options;
824  }
825 
833  protected function normalizeTimeOptions(array $options = []) {
834 
835  $props = [
836  'modified',
837  'created',
838  'updated',
839  'metadata_created',
840  'annotation_created',
841  'relationship_created',
842  'last_action',
843  'posted',
844  ];
845 
846  $bounds = ['time_lower', 'time_upper', 'after', 'before'];
847 
848  foreach ($props as $prop) {
849  foreach ($bounds as $bound) {
850  $prop_name = "{$prop}_{$bound}";
851 
852  $new_prop_name = $prop_name;
853  $new_prop_name = str_replace('modified', 'updated', $new_prop_name);
854  $new_prop_name = str_replace('posted', 'created', $new_prop_name);
855  $new_prop_name = str_replace('time_lower', 'after', $new_prop_name);
856  $new_prop_name = str_replace('time_upper', 'before', $new_prop_name);
857 
858  if (!isset($options[$new_prop_name])) {
859  $options[$new_prop_name] = elgg_extract($prop_name, $options);
860  }
861  }
862  }
863 
864  return $options;
865  }
866 
875  protected function removeKeyPrefix($prefix, array $array = []) {
876  foreach ($array as $key => $value) {
877  $new_key = $key;
878  if (strpos($key, $prefix) === 0) {
879  $new_key = substr($key, strlen($prefix));
880  }
881  if (!isset($array[$new_key])) {
882  $array[$new_key] = $array[$key];
883  }
884  if ($new_key !== $key) {
885  unset($array[$key]);
886  }
887 
888  if (is_array($array[$new_key])) {
889  $array[$new_key] = $this->removeKeyPrefix($prefix, $array[$new_key]);
890  }
891  }
892 
893  return $array;
894  }
895 
903  protected function normalizeSelectClauses(array $options = []) {
904 
905  $options = self::normalizePluralOptions($options, ['select']);
906 
907  foreach ($options['selects'] as $key => $clause) {
908  if (empty($clause)) {
909  unset($options['selects'][$key]);
910  continue;
911  }
912 
913  if ($clause instanceof SelectClause) {
914  continue;
915  }
916 
917  $options['selects'][$key] = new SelectClause($clause);
918  }
919 
920  return $options;
921  }
922 
930  protected function normalizeWhereClauses(array $options = []) {
931 
932  $options = self::normalizePluralOptions($options, ['where']);
933 
934  foreach ($options['wheres'] as $key => $clause) {
935  if (empty($clause)) {
936  unset($options['wheres'][$key]);
937  continue;
938  }
939 
940  if ($clause instanceof WhereClause) {
941  continue;
942  }
943 
944  if (is_string($clause)) {
946  Using literal MySQL statements in 'wheres' options parameter is deprecated.
947  Instead use a closure that receives an instanceof of QueryBuilder
948  and returns a composite DBAL expression
949 
950  {{ $clause }}
951  ", '3.0');
952  }
953 
954  $options['wheres'][$key] = new WhereClause($clause);
955  }
956 
957  return $options;
958  }
959 
968  protected function normalizeJoinClauses(array $options = []) {
969 
970  $options = self::normalizePluralOptions($options, ['join']);
971 
972  foreach ($options['joins'] as $key => $join) {
973  if (empty($join)) {
974  unset($options['joins'][$key]);
975  continue;
976  }
977 
978  if ($join instanceof JoinClause) {
979  continue;
980  }
981 
982  if (is_string($join)) {
983  preg_match('/((LEFT|INNER|RIGHT)\s+)?JOIN\s+(.*?)\s+((as\s+)?(.*?)\s+)ON\s+(.*)$/im', $join, $parts);
984 
985  $type = !empty($parts[2]) ? strtolower($parts[2]) : 'inner';
986  $table = $parts[3];
987  $alias = $parts[6];
988  $condition = preg_replace('/\r|\n/', '', $parts[7]);
989 
990  $dbprefix = elgg_get_config('dbprefix');
991  if (strpos($table, $dbprefix) === 0) {
992  $table = substr($table, strlen($dbprefix));
993  }
994 
996  Using literal MySQL statements in 'joins' options parameter is deprecated.
997  Instead use a closure that receives an instanceof of QueryBuilder and returns an instanceof of JoinClause,
998  also consider using one of the built-in methods in QueryBuilder.
999 
1000  {{ $join }}
1001  ", '3.0');
1002 
1003  $clause = new JoinClause($table, $alias, $condition, $type);
1004  $options['joins'][$key] = $clause;
1005  }
1006  }
1007 
1008  return $options;
1009  }
1010 
1018  protected function normalizeOrderByClauses(array $options = []) {
1019 
1020  $order_by = $options['order_by'];
1021  $options['order_by'] = [];
1022 
1023  if (!empty($order_by)) {
1024  if (is_string($order_by)) {
1025  $orders = explode(',', $order_by);
1026  } else if (is_array($order_by)) {
1027  $orders = $order_by;
1028  } else {
1029  $orders = [$order_by];
1030  }
1031 
1032  foreach ($orders as $order) {
1033  if ($order instanceof OrderByClause) {
1034  $options['order_by'][] = $order;
1035  continue;
1036  }
1037 
1038  $order = trim($order);
1039  if (preg_match('/(.*)(?=\s+(asc|desc))/i', $order, $parts)) {
1040  $column = $parts[1];
1041  $direction = $parts[2];
1042  } else {
1043  $column = $order;
1044  $direction = 'ASC';
1045  }
1046 
1047  $direction = in_array(strtoupper($direction), [
1048  'ASC',
1049  'DESC'
1050  ]) ? strtoupper($direction) : 'ASC';
1051 
1052  $options['order_by'][] = new OrderByClause($column, $direction);
1053  }
1054  }
1055 
1056  foreach ($options['sort_by'] as $key => $value) {
1057  $clause = new EntitySortByClause();
1058  $clause->property = elgg_extract('property', $value);
1059  $clause->property_type = elgg_extract('property_type', $value);
1060  $clause->join_type = elgg_extract('join_type', $value, 'inner');
1061  $clause->direction = elgg_extract('direction', $value);
1062  $clause->signed = elgg_extract('signed', $value);
1063 
1064  $options['order_by'][] = $clause;
1065  }
1066 
1067  return $options;
1068  }
1069 
1077  protected function normalizeGroupByClauses(array $options = []) {
1078 
1079  if (!isset($options['having'])) {
1080  $options['having'] = [];
1081  } else {
1082  if (!is_array($options['having'])) {
1083  $options['having'] = [$options['having']];
1084  }
1085 
1086  foreach ($options['having'] as $key => $expr) {
1087  if ($expr instanceof HavingClause) {
1088  continue;
1089  }
1090 
1091  $options['having'][$key] = new HavingClause($expr);
1092  }
1093  }
1094 
1095  if (empty($options['group_by'])) {
1096  $options['group_by'] = [];
1097  }
1098 
1099  if (is_string($options['group_by'])) {
1100  $clause = $options['group_by'];
1101 
1102  $options['group_by'] = explode(',', $options['group_by']);
1103 
1104  if (count($options['group_by']) > 1) {
1106  Using literal MySQL statements in 'group_by' options parameter is deprecated.
1107  Instead use a closure that receives an instanceof of QueryBuilder
1108  and returns a prepared clause.
1109 
1110  {{ $clause }}
1111  ", '3.0');
1112  }
1113  }
1114 
1115  foreach ($options['group_by'] as $key => $expr) {
1116  if ($expr instanceof GroupByClause) {
1117  continue;
1118  }
1119 
1120  if (is_string($expr)) {
1121  $expr = trim($expr);
1122  }
1123 
1124  $options['group_by'][$key] = new GroupByClause($expr);
1125  }
1126 
1127  return $options;
1128  }
1129 
1137  public static function normalizeMetastringOptions(array $options = []) {
1138 
1139  // support either metastrings_type or metastring_type
1140  // because I've made this mistake many times and hunting it down is a pain...
1141  $type = elgg_extract('metastring_type', $options, null);
1142  $type = elgg_extract('metastrings_type', $options, $type);
1143 
1144  $options['metastring_type'] = $type;
1145 
1146  // support annotation_ and annotations_ because they're way too easy to confuse
1147  $prefixes = ['metadata_', 'annotation_', 'annotations_'];
1148 
1149  // map the metadata_* options to metastring_* options
1150  $map = [
1151  'names' => 'metastring_names',
1152  'values' => 'metastring_values',
1153  'case_sensitive' => 'metastring_case_sensitive',
1154  'owner_guids' => 'metastring_owner_guids',
1155  'created_time_lower' => 'metastring_created_time_lower',
1156  'created_time_upper' => 'metastring_created_time_upper',
1157  'calculation' => 'metastring_calculation',
1158  'ids' => 'metastring_ids',
1159  ];
1160 
1161  foreach ($prefixes as $prefix) {
1162  $singulars = ["{$prefix}name", "{$prefix}value", "{$prefix}owner_guid", "{$prefix}id"];
1163  $options = self::normalizePluralOptions($options, $singulars);
1164 
1165  foreach ($map as $specific => $normalized) {
1166  $key = $prefix . $specific;
1167  if (isset($options[$key])) {
1168  $options[$normalized] = $options[$key];
1169  }
1170  }
1171  }
1172 
1173  return $options;
1174  }
1175 
1188  public static function normalizePluralOptions($options, $singulars) {
1189  foreach ($singulars as $singular) {
1190  $plural = $singular . 's';
1191 
1192  if (array_key_exists($singular, $options)) {
1193  if ($options[$singular] === ELGG_ENTITIES_ANY_VALUE) {
1194  $options[$plural] = $options[$singular];
1195  } else {
1196  // Test for array refs #2641
1197  if (!is_array($options[$singular])) {
1198  $options[$plural] = [$options[$singular]];
1199  } else {
1200  $options[$plural] = $options[$singular];
1201  }
1202  }
1203  }
1204 
1205  unset($options[$singular]);
1206  }
1207 
1208  return $options;
1209  }
1210 }
if(!$user||!$user->canDelete()) $name
Definition: delete.php:22
static getEntityTypes()
Get the core entity types.
Definition: Config.php:562
$defaults
const ELGG_VALUE_INTEGER
Value types.
Definition: constants.php:138
$column
Definition: add.php:10
$type
Definition: delete.php:21
$keys
Definition: access.php:34
$options
Elgg admin footer.
Definition: footer.php:6
static $primary_attr_names
Definition: ElggEntity.php:49
elgg_log($message, $level=\Psr\Log\LogLevel::NOTICE)
Log a message.
Definition: elgglib.php:786
elgg_deprecated_notice($msg, $dep_version, $backtrace_level=1)
Log a notice about deprecated use of a function, view, etc.
Definition: elgglib.php:841
const ELGG_ENTITIES_ANY_VALUE
Definition: constants.php:24
elgg_extract($key, $array, $default=null, $strict=true)
Checks for $array[$key] and returns its value if it exists, else returns $default.
Definition: elgglib.php:1131
if($container instanceof ElggGroup &&$container->guid!=elgg_get_page_owner_guid()) $key
Definition: summary.php:55
$value
Definition: debugging.php:7
_elgg_check_unsupported_site_guid(array $options=[])
Checks options for the existing of site_guid or site_guids contents and reports a warning if found...
Definition: entities.php:820
const ELGG_VALUE_STRING
Definition: constants.php:139
$subtypes
$table
Definition: cron.php:57
$index
Definition: gallery.php:47
elgg ElggEntity
Definition: ElggEntity.js:15
elgg_get_config($name, $default=null)
Get an Elgg configuration value.