ILIAS  trunk Revision v12.0_alpha-1227-g7ff6d300864
DataQuery.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
21namespace ILIAS\User\Profile;
22
24
26{
27 private const string ARRAY_SEPARATOR = '##!:!##';
28 private const string RECORDS_QUERY_INIT = 'SELECT ';
29
30 private string $cnt_query_init;
31
32 private array $multi_fields = [];
33 private array $select_fields;
34 private array $udf_fields = [];
35 private array $join = [];
36 private array $where = [];
37 private string $order = '';
38 private bool $multi_data_table_joined = false;
39 private bool $additional_fields_processed = false;
40
41 public function __construct(
42 private readonly \ilDBInterface $db,
43 private readonly string $user_base_table_name,
44 private readonly string $user_values_table_name,
45 array $select_fields
46 ) {
47 $this->cnt_query_init = 'SELECT COUNT(DISTINCT ' . $this->user_base_table_name
48 . '.usr_id) cnt FROM ' . $this->user_base_table_name;
49 $this->select_fields = array_map(
50 fn(string $v): string => $this->user_base_table_name . '.' . $v,
52 );
53 }
54
55 public function withAdditionalAdditionalTableSelectField(string $field_name): self
56 {
57 $clone = clone $this;
58 $clone->select_fields[] = $field_name;
59 return $clone;
60 }
61
62 public function withAdditionalDefaultTableSelectField(string $field_name): self
63 {
64 $clone = clone $this;
65 $clone->select_fields[] = $this->user_base_table_name . '.' . $field_name;
66 return $clone;
67 }
68
69 public function withAdditionalUdfField(Field $field): self
70 {
71 $clone = clone $this;
72 $clone->udf_fields[] = $field;
73 return $clone;
74 }
75
76 public function withAdditionalMultiField(string $field_name): self
77 {
78 $clone = clone $this;
79 $clone->multi_fields[] = $field_name;
80 return $clone;
81 }
82
83 public function withAdditionalJoin(string $join): self
84 {
85 $clone = clone $this;
86 $clone->join[] = $join;
87 return $clone;
88 }
89
90 public function withAdditionalWhere(string $where): self
91 {
92 $clone = clone $this;
93 $clone->where[] = $where;
94 return $clone;
95 }
96
97 public function withAdditionalMultiDataWhere(string $identifier, string|array $value): self
98 {
99 if (is_array($value)) {
100 $value_query = $this->db->in($this->user_values_table_name . '.value', $value, false, \ilDBConstants::T_TEXT);
101 } else {
102 $value_query = $this->db->like($this->user_values_table_name . '.value', \ilDBConstants::T_TEXT, "%{$value}%");
103 }
104 $clone = clone $this;
105 $clone->where[] = $this->user_values_table_name . ".field_id = '{$identifier}' AND {$value_query}";
106 return $clone;
107 }
108
109 public function withAdditionalTableOrder(string $order): self
110 {
111 $clone = clone $this;
112 $clone->order = $order;
113 return $clone;
114 }
115
116 public function withMultiDataTableOrder(string $order_field, string $direction): self
117 {
118 $clone = clone $this;
119 $clone->order = "ORDER BY `{$order_field}` {$direction}";
120 return $clone;
121 }
122
123 public function withDefaultTableOrderFields(array $order_fields, string $direction): self
124 {
125 $clone = clone $this;
126 $clone->order = 'ORDER BY ' . implode(', ', array_reduce(
127 $order_fields,
128 function (array $c, string $v) use ($direction): array {
129 $c[] = $this->user_base_table_name . ".`{$v}` {$direction}";
130 return $c;
131 },
132 []
133 ));
134 return $clone;
135 }
136
137 public function withLimitedUsers(array $users): self
138 {
139 if ($users === []) {
140 return $this;
141 }
142 $clone = clone $this;
143 $clone->where[] = $this->db->in('usr_data.usr_id', $users, false, \ilDBConstants::T_INTEGER);
144 return $clone;
145 }
146
147 public function withJoinedMultiDataTable(): self
148 {
149 $clone = clone $this;
150 $clone->join[] = $this->buildJoinForMultiDataTable();
151 $clone->multi_data_table_joined = true;
152 return $clone;
153 }
154
155 public function buildRecordsQueryString(): string
156 {
157 return self::RECORDS_QUERY_INIT . implode(', ', $this->select_fields) . PHP_EOL
158 . 'FROM usr_data' . PHP_EOL
159 . implode(PHP_EOL, $this->join) . PHP_EOL
160 . 'WHERE usr_data.usr_id <> ' . $this->db->quote(ANONYMOUS_USER_ID, \ilDBConstants::T_INTEGER) . PHP_EOL
161 . $this->buildWhere()
162 . 'GROUP BY ' . $this->user_base_table_name . '.usr_id' . PHP_EOL
163 . $this->order;
164 }
165
166 public function buildCntQueryString(): string
167 {
168 return $this->cnt_query_init . PHP_EOL
169 . implode(PHP_EOL, $this->join) . PHP_EOL
170 . 'WHERE usr_data.usr_id <> ' . $this->db->quote(ANONYMOUS_USER_ID, \ilDBConstants::T_INTEGER) . PHP_EOL
171 . $this->buildWhere();
172 }
173
175 {
176 if ($this->additional_fields_processed
177 || $this->multi_fields === [] && $this->udf_fields === []) {
178 return $this;
179 }
180
181 $clone = clone $this;
182 if (!$this->multi_data_table_joined) {
183 $clone->join[] = $this->buildJoinForMultiDataTable();
184 $clone->multi_data_table_joined = true;
185 }
186
187 foreach ($this->multi_fields as $field) {
188 $clone->select_fields[] = 'GROUP_CONCAT(DISTINCT IF(' . $this->user_values_table_name
189 . ".field_id = {$this->db->quote($field, \ilDBConstants::T_TEXT)}, "
190 . $this->user_values_table_name . '.value, NULL) '
191 . "SEPARATOR '" . self::ARRAY_SEPARATOR . "') `{$field}`";
192 }
193
194 foreach ($this->udf_fields as $field) {
195 $clone->select_fields[] = 'GROUP_CONCAT(DISTINCT IF(' . $this->user_values_table_name
196 . ".field_id = {$this->db->quote($field->getIdentifier(), \ilDBConstants::T_TEXT)}, "
197 . $this->user_values_table_name . '.value, NULL) '
198 . "SEPARATOR '" . self::ARRAY_SEPARATOR . "') `udf_{$field->getIdentifier()}`";
199 }
200
201 $clone->additional_fields_processed = true;
202 return $clone;
203 }
204
205 public function explodeArrayValues(array $row): array
206 {
207 return array_map(
208 static function (mixed $v): mixed {
209 if (!is_string($v) || mb_stristr($v, self::ARRAY_SEPARATOR) === false) {
210 return $v;
211 }
212
213 return explode(self::ARRAY_SEPARATOR, $v);
214 },
215 $row
216 );
217 }
218
219 private function buildWhere(): string
220 {
221 if ($this->where === []) {
222 return '';
223 }
224 return 'AND ' . implode(PHP_EOL . 'AND ', $this->where) . PHP_EOL;
225 }
226
227 private function buildJoinForMultiDataTable(): string
228 {
229 return 'LEFT JOIN ' . $this->user_values_table_name . ' ON '
230 . $this->user_values_table_name . '.usr_id = ' . $this->user_base_table_name . '.usr_id';
231 }
232}
withAdditionalSelectAndJoinForUdfAndMultiValueFields()
Definition: DataQuery.php:174
__construct(private readonly \ilDBInterface $db, private readonly string $user_base_table_name, private readonly string $user_values_table_name, array $select_fields)
Definition: DataQuery.php:41
const string ARRAY_SEPARATOR
Definition: DataQuery.php:27
withAdditionalDefaultTableSelectField(string $field_name)
Definition: DataQuery.php:62
withMultiDataTableOrder(string $order_field, string $direction)
Definition: DataQuery.php:116
withDefaultTableOrderFields(array $order_fields, string $direction)
Definition: DataQuery.php:123
withAdditionalWhere(string $where)
Definition: DataQuery.php:90
withAdditionalMultiField(string $field_name)
Definition: DataQuery.php:76
const string RECORDS_QUERY_INIT
Definition: DataQuery.php:28
withLimitedUsers(array $users)
Definition: DataQuery.php:137
withAdditionalUdfField(Field $field)
Definition: DataQuery.php:69
withAdditionalJoin(string $join)
Definition: DataQuery.php:83
withAdditionalMultiDataWhere(string $identifier, string|array $value)
Definition: DataQuery.php:97
withAdditionalTableOrder(string $order)
Definition: DataQuery.php:109
withAdditionalAdditionalTableSelectField(string $field_name)
Definition: DataQuery.php:55
const ANONYMOUS_USER_ID
Definition: constants.php:27
$c
Definition: deliver.php:25
Interface ilDBInterface.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...