34 public function normalizeOptions(array
$options = []) {
36 if (!isset(
$options[
'__original_options'])) {
54 foreach ([
'selects',
'joins',
'wheres'] as $prop) {
70 return $this->normalizeGroupByClauses(
$options);
77 protected function getDefaults() {
81 'type_subtype_pairs' => null,
83 'owner_guids' => null,
84 'container_guids' => null,
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,
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,
113 'search_name_value_pairs' => null,
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,
126 'relationship_pairs' => [],
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,
135 'preload_owners' =>
false,
136 'preload_containers' =>
false,
141 'batch_inc_offset' =>
true,
144 '__ElggBatch' => null,
155 protected function normalizeAccessOptions(array
$options = []) {
156 return self::normalizePluralOptions(
$options, [
'access_id']);
167 protected function normalizeTypeSubtypeOptions(array
$options = []) {
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'])) {
182 }
else if (isset(
$options[
'type_subtype_pairs'])) {
184 }
else if (isset(
$options[
'types'])) {
185 $options[
'type_subtype_pairs'] = [];
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.');
195 if (isset(
$options[
'type_subtype_pairs']) && is_array(
$options[
'type_subtype_pairs'])) {
198 elgg_log(
"'$type' is not a valid entity type",
'WARNING');
207 unset(
$options[
'type_subtype_pair']);
221 protected function normalizeMetadataOptions(array
$options = []) {
226 'metadata_name_value_pair',
235 'metadata_created_after',
236 'metadata_created_before',
239 foreach ($props as $prop) {
240 if (isset(
$options[$prop]) && empty(
$options[
'metadata_name_value_pairs'])) {
241 $options[
'metadata_name_value_pairs'][] = [
247 foreach (
$options[
'metadata_name_value_pairs'] as
$key => $pair) {
248 if ($pair instanceof
Clause) {
252 foreach ($props as $prop) {
253 if (!isset($pair[$prop])) {
261 $options[
'metadata_name_value_pairs'] = $this->removeKeyPrefix(
'metadata_',
$options[
'metadata_name_value_pairs']);
268 'case_sensitive' =>
true,
269 'entity_guids' => null,
271 'created_after' => null,
272 'created_before' => null,
275 foreach (
$options[
'metadata_name_value_pairs'] as
$key => $pair) {
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'];
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'];
312 protected function normalizeMetadataSearchOptions(array
$options = []) {
314 'search_name_value_pair',
321 foreach (
$options[
'search_name_value_pairs'] as
$key => $pair) {
322 if ($pair instanceof Clause) {
329 $options[
'search_name_value_pairs'] = $this->removeKeyPrefix(
'metadata_',
$options[
'search_name_value_pairs']);
336 'case_sensitive' =>
true,
337 'entity_guids' => null,
339 'created_after' => null,
340 'created_before' => null,
343 foreach (
$options[
'search_name_value_pairs'] as
$key => $pair) {
344 if ($pair instanceof WhereClause) {
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'];
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'];
379 protected function normalizeAnnotationOptions(array
$options = []) {
384 'annotation_name_value_pair',
393 'annotation_owner_guids',
394 'annotation_created_after',
395 'annotation_created_before',
396 'annotation_sort_by_calculation',
399 foreach ($props as $prop) {
400 if (isset(
$options[$prop]) && empty(
$options[
'annotation_name_value_pairs'])) {
401 $options[
'annotation_name_value_pairs'][] = [
407 foreach (
$options[
'annotation_name_value_pairs'] as
$key => $pair) {
408 if ($pair instanceof WhereClause) {
412 foreach ($props as $prop) {
413 if (!isset($pair[$prop])) {
421 $options[
'annotation_name_value_pairs'] = $this->removeKeyPrefix(
'annotation_',
$options[
'annotation_name_value_pairs']);
428 'case_sensitive' =>
true,
429 'entity_guids' => null,
430 'owner_guids' => null,
433 'access_ids' => null,
434 'created_after' => null,
435 'created_before' => null,
436 'sort_by_calculation' => null,
439 foreach (
$options[
'annotation_name_value_pairs'] as
$key => $pair) {
440 if ($pair instanceof WhereClause) {
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'];
461 if ($clause->sort_by_calculation && empty(
$options[
'order_by'])) {
462 $clause->sort_by_direction =
'desc';
465 $options[
'annotation_name_value_pairs'][
$key] = $clause;
479 protected function normalizePairedOptions(
$type =
'metadata', array
$options = []) {
480 if (!is_array(
$options[
"{$type}_name_value_pairs"])) {
481 $options[
"{$type}_name_value_pairs"] = [];
494 if (isset(
$options[
"{$type}_name_value_pairs"][
'name'])) {
495 $options[
"{$type}_name_value_pairs"][] = [
496 'name' =>
$options[
"{$type}_name_value_pairs"][
'name'],
499 'case_sensitive' =>
elgg_extract(
'case_sensitive',
$options[
"{$type}_name_value_pairs"], $case_sensitive_default)
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']);
518 foreach (
$options[
"{$type}_name_value_pairs"] as
$index => $pair) {
519 if (is_array($pair)) {
520 $keys = array_keys($pair);
524 'value' => $pair[
$keys[0]],
538 foreach (
$options[
"{$type}_name_value_pairs"] as
$index => $values) {
539 if ($values instanceof Clause) {
543 if (is_array($values)) {
544 if (isset($values[
'name']) || isset($values[
'value'])) {
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,
565 if (
$value instanceof Clause) {
569 if (!isset(
$value[
'case_sensitive'])) {
570 $value[
'case_sensitive'] = $case_sensitive_default;
573 if (!isset(
$value[
'type'])) {
574 if (isset(
$value[
'value']) && is_bool(
$value[
'value'])) {
578 if (isset(
$value[
'value']) && is_int(
$value[
'value'])) {
585 if (!isset(
$value[
'comparison']) && isset(
$value[
'operand'])) {
595 unset(
$options[
"{$type}_case_sensitive"]);
607 protected function normalizeRelationshipOptions(array
$options = []) {
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,
621 foreach (array_keys(
$defaults) as $prop) {
630 $options[
'relationship_pairs'][] = $pair;
632 foreach (
$options[
'relationship_pairs'] as
$index => $relationship_pair) {
633 if ($relationship_pair instanceof WhereClause) {
640 $options[
'relationship_pairs'] = $this->removeKeyPrefix(
'relationship_',
$options[
'relationship_pairs']);
642 foreach (
$options[
'relationship_pairs'] as
$key => $pair) {
643 if ($pair instanceof WhereClause) {
647 if (!$pair[
'relationship'] && !$pair[
'guid'] && !$pair[
'ids']) {
653 $clause->ids = (array) $pair[
'ids'];
654 $clause->names = (array) $pair[
'relationship'];
656 $clause->join_on = $pair[
'join_on'];
657 $clause->inverse = $pair[
'inverse_relationship'];
658 if ($clause->inverse) {
659 $clause->object_guids = (array) $pair[
'guid'];
661 $clause->subject_guids = (array) $pair[
'guid'];
664 $clause->created_after = $pair[
'created_after'];
665 $clause->created_before = $pair[
'created_before'];
681 protected function normalizeGuidOptions(array
$options = []) {
687 'annotation_owner_guid',
696 'annotation_owner_guids',
700 foreach ($names as
$name) {
726 protected function normalizeTimeOptions(array
$options = []) {
733 'annotation_created',
734 'relationship_created',
739 $bounds = [
'time_lower',
'time_upper',
'after',
'before'];
741 foreach ($props as $prop) {
742 foreach ($bounds as $bound) {
743 $prop_name =
"{$prop}_{$bound}";
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);
751 if (!isset(
$options[$new_prop_name])) {
768 protected function removeKeyPrefix($prefix, array $array = []) {
771 if (str_starts_with(
$key, $prefix)) {
775 if (!isset($array[$new_key])) {
776 $array[$new_key] =
$value;
779 if ($new_key !==
$key) {
783 if (is_array($array[$new_key])) {
784 $array[$new_key] = $this->removeKeyPrefix($prefix, $array[$new_key]);
798 protected function normalizeSelectClauses(array
$options = []) {
803 if (empty($clause)) {
825 protected function normalizeWhereClauses(array
$options = []) {
830 if (empty($clause)) {
835 if ($clause instanceof WhereClause) {
852 protected function normalizeJoinClauses(array
$options = []) {
866 if (is_string($join)) {
867 preg_match(
'/((LEFT|INNER|RIGHT)\s+)?JOIN\s+(.*?)\s+((as\s+)?(.*?)\s+)ON\s+(.*)$/im', $join, $parts);
869 $type = !empty($parts[2]) ? strtolower($parts[2]) :
'inner';
872 $condition = preg_replace(
'/\r|\n/',
'', $parts[7]);
879 $clause =
new JoinClause(
$table, $alias, $condition,
$type);
894 protected function normalizeOrderByClauses(array
$options = []) {
899 if (!empty($order_by)) {
900 if (is_string($order_by)) {
901 $orders = explode(
',', $order_by);
902 }
else if (is_array($order_by)) {
905 $orders = [$order_by];
908 foreach ($orders as $order) {
914 $order =
trim($order);
916 if (
preg_match(
'/(.*)(?=\s+(asc|desc))/i', $order, $parts)) {
918 $direction = $parts[2];
924 $direction =
strtoupper($direction) ===
'DESC' ?
'DESC' :
'ASC';
931 if (isset($sort_by[
'property'])) {
936 foreach (
$options[
'sort_by'] as $sort_spec) {
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);
943 $clause->inverse_relationship =
elgg_extract(
'inverse_relationship', $sort_spec);
944 $clause->relationship_guid =
elgg_extract(
'relationship_guid', $sort_spec);
959 protected function normalizeGroupByClauses(array
$options = []) {
964 if (!is_array(
$options[
'having'])) {
981 if (is_string(
$options[
'group_by'])) {
1003 public static function normalizeMetastringOptions(array
$options = []) {
1013 $prefixes = [
'metadata_',
'annotation_',
'annotations_'];
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',
1027 foreach ($prefixes as $prefix) {
1028 $singulars = [
"{$prefix}name",
"{$prefix}value",
"{$prefix}owner_guid",
"{$prefix}id"];
1031 foreach ($map as $specific => $normalized) {
1032 $key = $prefix . $specific;
1054 public static function normalizePluralOptions(
$options, $singulars) {
1055 foreach ($singulars as $singular) {
1056 $plural = $singular .
's';
1058 if (array_key_exists($singular,
$options)) {
1063 if (!is_array(
$options[$singular])) {
Exception thrown if an argument is not of the expected type.
elgg_get_config(string $name, $default=null)
Get an Elgg configuration value.
if(!$user||!$user->canDelete()) $name
Interface that allows resolving statements and/or extending query builder.
const ELGG_VALUE_INTEGER
Value types.
Builds quereis for matching entities by their attributes.
Extends QueryBuilder with JOIN clauses.
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.
Builds queries for matching annotations against their properties.
Extends QueryBuilder with GROUP BY statements.
elgg_extract($key, $array, $default=null, bool $strict=true)
Checks for $array[$key] and returns its value if it exists, else returns $default.
Extends QueryBuilder with HAVING clauses.
elgg_log($message, $level=\Psr\Log\LogLevel::NOTICE)
Log a message.
const ELGG_ENTITIES_ANY_VALUE
Constant to request the value of a parameter be ignored in elgg_get_*() functions.
Extends QueryBuilder with ORDER BY clauses.
if($container instanceof ElggGroup &&$container->guid!=elgg_get_page_owner_guid()) $key
Builds a clause from closure or composite expression.