ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
MailBoxQuery.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
21 namespace ILIAS\Mail\Message;
22 
23 use ilDBInterface;
24 use ilDBConstants;
26 use DateTimeZone;
29 
31 {
32  private const MailBoxOrderColumn DEFAULT_ORDER_COLUMN = MailBoxOrderColumn::SEND_TIME;
33  private const string DEFAULT_ORDER_DIRECTION = Order::ASC;
34 
35  private ilDBInterface $db;
36  private ?int $folder_id = null;
37  private ?string $sender = null;
38  private ?string $recipients = null;
39  private ?string $subject = null;
40  private ?string $body = null;
41  private ?bool $is_unread = null;
42  private ?bool $is_system = null;
43  private ?bool $has_attachment = null;
47  private ?array $filtered_ids = null;
48  private int $limit = 999999;
49  private int $offset = 0;
50  private MailBoxOrderColumn $order_column = self::DEFAULT_ORDER_COLUMN;
51  private string $order_direction = self::DEFAULT_ORDER_DIRECTION;
52 
53  public function __construct(
54  private readonly int $user_id,
55  ) {
56  global $DIC;
57  $this->db = $DIC->database();
58  }
59 
60  public function withFolderId(?int $folder_id): MailBoxQuery
61  {
62  $clone = clone $this;
63  $clone->folder_id = $folder_id;
64 
65  return $clone;
66  }
67 
68  public function withSender(?string $sender): MailBoxQuery
69  {
70  $clone = clone $this;
71  $clone->sender = $sender;
72 
73  return $clone;
74  }
75 
76  public function withRecipients(?string $recipients): MailBoxQuery
77  {
78  $clone = clone $this;
79  $clone->recipients = $recipients;
80 
81  return $clone;
82  }
83 
84  public function withSubject(?string $subject): MailBoxQuery
85  {
86  $clone = clone $this;
87  $clone->subject = $subject;
88 
89  return $clone;
90  }
91 
92  public function withBody(?string $body): MailBoxQuery
93  {
94  $clone = clone $this;
95  $clone->body = $body;
96 
97  return $clone;
98  }
99 
100  public function withIsUnread(?bool $is_unread): MailBoxQuery
101  {
102  $clone = clone $this;
103  $clone->is_unread = $is_unread;
104 
105  return $clone;
106  }
107 
108  public function withIsSystem(?bool $is_system): MailBoxQuery
109  {
110  $clone = clone $this;
111  $clone->is_system = $is_system;
112 
113  return $clone;
114  }
115 
116  public function withHasAttachment(?bool $has_attachment): MailBoxQuery
117  {
118  $clone = clone $this;
119  $clone->has_attachment = $has_attachment;
120 
121  return $clone;
122  }
123 
124  public function withPeriodStart(?DateTimeImmutable $period_start): MailBoxQuery
125  {
126  $clone = clone $this;
127  $clone->period_start = $period_start;
128 
129  return $clone;
130  }
131 
132  public function withPeriodEnd(?DateTimeImmutable $period_end): MailBoxQuery
133  {
134  $clone = clone $this;
135  $clone->period_end = $period_end;
136 
137  return $clone;
138  }
139 
143  public function withFilteredIds(?array $filtered_ids): MailBoxQuery
144  {
145  $clone = clone $this;
146  $clone->filtered_ids = $filtered_ids;
147 
148  return $clone;
149  }
150 
151  public function withLimit(int $limit): MailBoxQuery
152  {
153  $clone = clone $this;
154  $clone->limit = $limit;
155 
156  return $clone;
157  }
158 
159  public function withOffset(int $offset): MailBoxQuery
160  {
161  $clone = clone $this;
162  $clone->offset = $offset;
163 
164  return $clone;
165  }
166 
167  public function withOrderColumn(?MailBoxOrderColumn $order_column): MailBoxQuery
168  {
169  $clone = clone $this;
170  if ($order_column !== null) {
171  $clone->order_column = $order_column;
172  } else {
173  $clone->order_column = self::DEFAULT_ORDER_COLUMN;
174  }
175 
176  return $clone;
177  }
178 
179  public function withOrderDirection(?string $order_direction): MailBoxQuery
180  {
181  $clone = clone $this;
182  if (\in_array($order_direction, [Order::ASC, Order::DESC], true)) {
183  $clone->order_direction = $order_direction;
184  } else {
185  $clone->order_direction = self::DEFAULT_ORDER_DIRECTION;
186  }
187 
188  return $clone;
189  }
190 
194  public function countUnread(): int
195  {
196  return $this->withIsUnread(true)->count();
197  }
198 
202  public function count(): int
203  {
204  if ($this->filtered_ids === []) {
205  return 0;
206  }
207 
208  $query = 'SELECT COUNT(m.mail_id) cnt '
209  . $this->getFrom()
210  . $this->getWhere();
211 
212  $res = $this->db->query($query);
213  if ($row = $this->db->fetchAssoc($res)) {
214  return (int) $row['cnt'];
215  }
216 
217  return 0;
218  }
219 
224  public function queryMailIds(): array
225  {
226  if ($this->filtered_ids === []) {
227  return [];
228  }
229 
230  $query = 'SELECT m.mail_id '
231  . $this->getFrom()
232  . $this->getWhere();
233 
234  $ids = [];
235  $res = $this->db->query($query);
236  while ($row = $this->db->fetchAssoc($res)) {
237  $ids[] = (int) $row['mail_id'];
238  }
239 
240  return $ids;
241  }
242 
248  public function query($short): array
249  {
250  if ($this->filtered_ids === []) {
251  return [];
252  }
253 
254  if ($short) {
255  $query = 'SELECT m.mail_id, m.user_id, m.folder_id, m.sender_id, m.send_time, '
256  . 'm.m_status, m.m_subject, m.import_name, m.rcp_to, m.attachments'
257  . $this->getFrom()
258  . $this->getWhere();
259  } else {
260  $query = 'SELECT m.*'
261  . $this->getFrom()
262  . $this->getWhere();
263  }
264 
265  if ($this->order_column === MailBoxOrderColumn::FROM) {
266  $query .= ' ORDER BY '
267  . ' u.firstname ' . $this->order_direction . ', '
268  . ' u.lastname ' . $this->order_direction . ', '
269  . ' u.login ' . $this->order_direction . ', '
270  . ' m.import_name ' . $this->order_direction;
271  } else {
272  $query .= ' ORDER BY ' . $this->order_column->value . ' ' . $this->order_direction;
273  }
274 
275  $this->db->setLimit($this->limit, $this->offset);
276  $res = $this->db->query($query);
277 
278  $set = [];
279  while ($row = $this->db->fetchAssoc($res)) {
280  $set[] = new MailRecordData(
281  isset($row['mail_id']) ? (int) $row['mail_id'] : 0,
282  isset($row['user_id']) ? (int) $row['user_id'] : 0,
283  isset($row['folder_id']) ? (int) $row['folder_id'] : 0,
284  isset($row['sender_id']) ? (int) $row['sender_id'] : null,
285  isset($row['send_time']) ? new DateTimeImmutable($row['send_time']) : null,
286  isset($row['m_status']) ? (string) $row['m_status'] : null,
287  isset($row['m_subject']) ? (string) $row['m_subject'] : null,
288  isset($row['import_name']) ? (string) $row['import_name'] : null,
289  isset($row['use_placeholders']) ? (bool) $row['use_placeholders'] : false,
290  isset($row['m_message']) ? (string) $row['m_message'] : null,
291  isset($row['rcp_to']) ? (string) $row['rcp_to'] : null,
292  isset($row['rcp_cc']) ? (string) $row['rcp_cc'] : null,
293  isset($row['rcp_bcc']) ? (string) $row['rcp_bcc'] : null,
294  isset($row['attachments']) ? (array) unserialize(
295  stripslashes($row['attachments']),
296  ['allowed_classes' => false]
297  ) : [],
298  isset($row['tpl_ctx_id']) ? (string) $row['tpl_ctx_id'] : null,
299  isset($row['tpl_ctx_params']) ? (string) $row['tpl_ctx_params'] : null
300  );
301  }
302 
303  return $set;
304  }
305 
306  private function getFrom()
307  {
308  return " FROM mail m
309  LEFT JOIN usr_data u ON u.usr_id = m.sender_id
310  LEFT JOIN usr_pref p ON p.usr_id = m.sender_id AND p.keyword = 'public_profile'";
311  }
312 
313  private function getWhere(): string
314  {
315  $parts = [];
316 
317  // minimum condition: only mailbox of the given user
318  $parts[] = 'm.user_id = ' . $this->db->quote($this->user_id, ilDBConstants::T_INTEGER);
319 
320  // sender conditions have to respect searchability and visibility of profile fields
321  $sender_conditions = [];
322  if (($this->sender ?? '') !== '') {
323  $sender_conditions[] = $this->db->like('u.login', ilDBConstants::T_TEXT, '%%' . $this->sender . '%%');
324 
325  if (ilUserSearchOptions::_isEnabled('firstname')) {
326  $sender_conditions[] = '(' .
327  $this->db->like('u.firstname', ilDBConstants::T_TEXT, '%%' . $this->sender . '%%')
328  . " AND p.value = 'y')";
329  }
330 
331  if (ilUserSearchOptions::_isEnabled('lastname')) {
332  $sender_conditions[] = '(' .
333  $this->db->like('u.lastname', ilDBConstants::T_TEXT, '%%' . $this->sender . '%%')
334  . " AND p.value = 'y')";
335  }
336  }
337  if (!empty($sender_conditions)) {
338  $parts[] = '(' . implode(' OR ', $sender_conditions) . ')';
339  }
340 
341  // other text conditions
342  $text_conditions = [
343  [$this->recipients, 'CONCAT(CONCAT(m.rcp_to, m.rcp_cc), m.rcp_bcc)'],
344  [$this->subject, 'm.m_subject'],
345  [$this->body, 'm.m_message'],
346  ];
347 
348  foreach ($text_conditions as $cond) {
349  if (($cond[0] ?? '') !== '') {
350  $parts[] = $this->db->like(
351  $cond[1],
353  '%%' . $cond[0] . '%%',
354  false
355  );
356  }
357  }
358 
359  if ($this->folder_id !== null) {
360  $parts[] = 'm.folder_id = ' . $this->db->quote($this->folder_id, ilDBConstants::T_INTEGER);
361  }
362 
363  if ($this->is_unread === true) {
364  $parts[] = 'm.m_status = ' . $this->db->quote('unread', 'text');
365  } elseif ($this->is_unread === false) {
366  $parts[] = 'm.m_status != ' . $this->db->quote('unread', 'text');
367  }
368 
369  if ($this->is_system === true) {
370  $parts[] = 'm.sender_id = ' . $this->db->quote(ANONYMOUS_USER_ID, ilDBConstants::T_INTEGER);
371  } elseif ($this->is_system === false) {
372  $parts[] = 'm.sender_id != ' . $this->db->quote(ANONYMOUS_USER_ID, ilDBConstants::T_INTEGER);
373  }
374 
375  if ($this->has_attachment === true) {
376  $parts[] = '(m.attachments != ' . $this->db->quote(serialize(null), ilDBConstants::T_TEXT)
377  . ' AND m.attachments != ' . $this->db->quote(serialize([]), ilDBConstants::T_TEXT) . ')';
378  } elseif ($this->has_attachment === false) {
379  $parts[] = '(m.attachments = ' . $this->db->quote(serialize(null), ilDBConstants::T_TEXT)
380  . ' OR m.attachments = ' . $this->db->quote(serialize([]), ilDBConstants::T_TEXT) . ')';
381  }
382 
383  if ($this->period_start !== null) {
384  $parts[] = 'm.send_time >= ' . $this->db->quote(
385  // convert to server time zone (set by ilias initialisation)
386  $this->period_start
387  ->setTimezone(new DateTimeZone(date_default_timezone_get()))
388  ->format('Y-m-d H:i:s'),
390  );
391  }
392 
393  if ($this->period_end !== null) {
394  $parts[] = 'm.send_time <= ' . $this->db->quote(
395  // convert to server time zone (set by ilias initialisation)
396  $this->period_end
397  ->setTimezone(new DateTimeZone(date_default_timezone_get()))
398  ->format('Y-m-d H:i:s'),
400  );
401  }
402 
403  if (!empty($this->filtered_ids)) {
404  $parts[] = $this->db->in(
405  'm.mail_id',
406  $this->filtered_ids,
407  false,
409  ) . ' ';
410  }
411 
412  if ($parts !== []) {
413  return ' WHERE ' . implode(' AND ', $parts);
414  }
415 
416  return '';
417  }
418 }
$res
Definition: ltiservices.php:66
const ANONYMOUS_USER_ID
Definition: constants.php:27
withHasAttachment(?bool $has_attachment)
const MailBoxOrderColumn DEFAULT_ORDER_COLUMN
if($clientAssertionType !='urn:ietf:params:oauth:client-assertion-type:jwt-bearer'|| $grantType !='client_credentials') $parts
Definition: ltitoken.php:61
withFilteredIds(?array $filtered_ids)
MailBoxOrderColumn $order_column
countUnread()
Count the number of unread mails with applied filter.
queryMailIds()
Get a list of mail ids.
DateTimeImmutable $period_start
withOrderColumn(?MailBoxOrderColumn $order_column)
__construct(private readonly int $user_id,)
withOrderDirection(?string $order_direction)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
global $DIC
Definition: shib_login.php:26
withPeriodEnd(?DateTimeImmutable $period_end)
count()
Count the number of all mails with applied filter.
withRecipients(?string $recipients)
withPeriodStart(?DateTimeImmutable $period_start)
const DESC
Definition: Order.php:31
query($short)
Query for mail data with applied filter.