ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilMailFormGUI.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
23use ILIAS\Refinery\Factory as Refinery;
27
32{
33 final public const string MAIL_FORM_TYPE_ATTACH = 'attach';
34 final public const string MAIL_FORM_TYPE_SEARCH_RESULT = 'search_res';
35 final public const string MAIL_FORM_TYPE_NEW = 'new';
36 final public const string MAIL_FORM_TYPE_ROLE = 'role';
37 final public const string MAIL_FORM_TYPE_REPLY = 'reply';
38 final public const string MAIL_FORM_TYPE_ADDRESS = 'address';
39 final public const string MAIL_FORM_TYPE_FORWARD = 'forward';
40 final public const string MAIL_FORM_TYPE_DRAFT = 'draft';
41
43 private readonly ilCtrlInterface $ctrl;
44 private readonly ilLanguage $lng;
45 private readonly ilObjUser $user;
46 private readonly ilTabsGUI $tabs;
47 private readonly ilToolbarGUI $toolbar;
48 private readonly ilFormatMail $umail;
49 private readonly ilMailbox $mbox;
50 private readonly ilFileDataMail $mfile;
51 private readonly GlobalHttpState $http;
52 private readonly Refinery $refinery;
53 private ?array $request_attachments = null;
55 private readonly ilMailBodyPurifier $purifier;
56 private string $mail_form_type = '';
57 private readonly Factory $ui_factory;
58
59 public function __construct(
61 ?ilMailBodyPurifier $body_purifier = null
62 ) {
63 global $DIC;
64
65 $this->template_service = $template_service ?? $DIC->mail()->textTemplates();
66 $this->tpl = $DIC->ui()->mainTemplate();
67 $this->ctrl = $DIC->ctrl();
68 $this->lng = $DIC->language();
69 $this->user = $DIC->user();
70 $this->tabs = $DIC->tabs();
71 $this->toolbar = $DIC->toolbar();
72 $this->http = $DIC->http();
73 $this->refinery = $DIC->refinery();
74 $this->umail = new ilFormatMail($this->user->getId());
75 $this->mfile = new ilFileDataMail($this->user->getId());
76 $this->mbox = new ilMailbox($this->user->getId());
77 $this->purifier = $body_purifier ?? new ilMailBodyPurifier();
78 $this->ui_factory = $DIC->ui()->factory();
79
80 $mail_obj_id = $this->getBodyParam(
81 'mobj_id',
82 $this->refinery->kindlyTo()->int(),
83 $this->getQueryParam(
84 'mobj_id',
85 $this->refinery->kindlyTo()->int(),
86 0
87 )
88 );
89
90 if ($mail_obj_id === 0) {
91 $mail_obj_id = $this->mbox->getInboxFolder();
92 }
93
94 $this->ctrl->setParameter($this, 'mobj_id', $mail_obj_id);
95 }
96
97 private function getQueryParam(string $name, Transformation $trafo, $default = null)
98 {
99 if ($this->http->wrapper()->query()->has($name)) {
100 return $this->http->wrapper()->query()->retrieve(
101 $name,
102 $trafo
103 );
104 }
105
106 return $default;
107 }
108
109 private function getBodyParam(string $name, Transformation $trafo, $default = null)
110 {
111 if ($this->http->wrapper()->post()->has($name)) {
112 return $this->http->wrapper()->post()->retrieve(
113 $name,
114 $trafo
115 );
116 }
117
118 return $default;
119 }
120
121 public function executeCommand(): void
122 {
123 $forward_class = $this->ctrl->getNextClass($this) ?? '';
124 switch (strtolower($forward_class)) {
125 case strtolower(ilMailAttachmentGUI::class):
126 $this->ctrl->setReturn($this, 'returnFromAttachments');
127 $gui = new ilMailAttachmentGUI();
128 $gui->consume();
129 $this->ctrl->forwardCommand($gui);
130 break;
131
132 case strtolower(ilMailSearchGUI::class):
133 $this->ctrl->setReturn($this, 'searchResults');
134 $this->ctrl->forwardCommand(new ilMailSearchGUI());
135 break;
136
137 case strtolower(ilMailSearchCoursesGUI::class):
138 $this->ctrl->setReturn($this, 'searchResults');
139 $this->ctrl->forwardCommand(new ilMailSearchCoursesGUI());
140 break;
141
142 case strtolower(ilMailingListsGUI::class):
143 $this->ctrl->setReturn($this, 'searchResults');
144 $this->ctrl->forwardCommand(new ilMailingListsGUI());
145 break;
146
147 case strtolower(ilMailSearchGroupsGUI::class):
148 $this->ctrl->setReturn($this, 'searchResults');
149 $this->ctrl->forwardCommand(new ilMailSearchGroupsGUI());
150 break;
151
152 default:
153 if (!($cmd = $this->ctrl->getCmd())) {
154 $cmd = 'showForm';
155 }
156
157 $this->$cmd();
158 break;
159 }
160 }
161
166 protected function decodeAttachmentFiles(array $files): array
167 {
168 $decoded_files = [];
169 foreach ($files as $value) {
170 if (is_file($this->mfile->getMailPath() . '/' . $this->user->getId() . '_' . urldecode($value))) {
171 $decoded_files[] = urldecode($value);
172 }
173 }
174
175 return $decoded_files;
176 }
177
178 public function sendMessage(): void
179 {
180 $message = $this->getBodyParam('m_message', $this->refinery->kindlyTo()->string(), '');
181
182 $mail_body = new ilMailBody($message, $this->purifier);
183
184 $sanitized_message = $mail_body->getContent();
185
186 $attachments = $this->getBodyParam(
187 'attachments',
188 $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->string()),
189 []
190 );
191 $files = $this->decodeAttachmentFiles($attachments);
192
193 $mailer = $this->umail
194 ->withContextId(ilMailFormCall::getContextId() ?: '')
195 ->withContextParameters(ilMailFormCall::getContextParameters());
196
197 $mailer->setSaveInSentbox(true);
198
199 $mailer->autoresponder()->enableAutoresponder();
200
201 if ($errors = $mailer->enqueue(
202 ilUtil::securePlainString($this->getBodyParam('rcp_to', $this->refinery->kindlyTo()->string(), '')),
203 ilUtil::securePlainString($this->getBodyParam('rcp_cc', $this->refinery->kindlyTo()->string(), '')),
204 ilUtil::securePlainString($this->getBodyParam('rcp_bcc', $this->refinery->kindlyTo()->string(), '')),
205 ilUtil::securePlainString($this->getBodyParam('m_subject', $this->refinery->kindlyTo()->string(), '')),
206 $sanitized_message,
207 $files,
208 $this->getBodyParam('use_placeholders', $this->refinery->kindlyTo()->bool(), false)
209 )) {
210 $this->request_attachments = $files;
211 $this->showSubmissionErrors($errors);
212 } else {
213 $mailer->autoresponder()->disableAutoresponder();
214
215 $mailer->persistToStage(
216 $this->user->getId(),
217 [],
218 '',
219 '',
220 '',
221 '',
222 ''
223 );
224
225 $this->ctrl->setParameterByClass(ilMailGUI::class, 'type', 'message_sent');
226
228 $this->tpl->setOnScreenMessage('success', $this->lng->txt('mail_message_send'), true);
229 $this->ctrl->redirectToURL(ilMailFormCall::getRefererRedirectUrl());
230 } else {
231 $this->ctrl->redirectByClass(ilMailGUI::class);
232 }
233 }
234 $mailer->autoresponder()->disableAutoresponder();
235
236 $this->showForm();
237 }
238
239 public function saveDraft(): void
240 {
241 $draft_folder_id = $this->mbox->getDraftsFolder();
242
243 $files = $this->decodeAttachmentFiles($this->getBodyParam(
244 'attachments',
245 $this->refinery->kindlyTo()->listOf(
246 $this->refinery->custom()->transformation($this->refinery->kindlyTo()->string())
247 ),
248 []
249 ));
250
251 $rcp_to = ilUtil::securePlainString($this->getBodyParam('rcp_to', $this->refinery->kindlyTo()->string(), ''));
252 $rcp_cc = ilUtil::securePlainString($this->getBodyParam('rcp_cc', $this->refinery->kindlyTo()->string(), ''));
253 $rcp_bcc = ilUtil::securePlainString($this->getBodyParam('rcp_bcc', $this->refinery->kindlyTo()->string(), ''));
254
255 if ($errors = $this->umail->validateRecipients(
256 $rcp_to,
257 $rcp_cc,
258 $rcp_bcc,
259 )) {
260 $this->request_attachments = $files;
261 $this->showSubmissionErrors($errors);
262 $this->showForm();
263 return;
264 }
265
266 if (ilSession::get('draft')) {
267 $draft_id = (int) ilSession::get('draft');
268 ilSession::clear('draft');
269 } else {
270 $draft_id = $this->umail->getNewDraftId($draft_folder_id);
271 }
272
273 $this->umail->updateDraft(
274 $draft_folder_id,
275 $files,
276 $rcp_to,
277 $rcp_cc,
278 $rcp_bcc,
280 $this->getBodyParam('m_subject', $this->refinery->kindlyTo()->string(), '')
281 ) ?: 'No Subject',
282 ilUtil::securePlainString($this->getBodyParam('m_message', $this->refinery->kindlyTo()->string(), '')),
283 $draft_id,
284 $this->getBodyParam('use_placeholders', $this->refinery->kindlyTo()->bool(), false),
287 );
288
289 $this->tpl->setOnScreenMessage('info', $this->lng->txt('mail_saved'), true);
290
293 } else {
294 $this->ctrl->redirectByClass([ilMailGUI::class, ilMailFolderGUI::class]);
295 }
296
297 $this->showForm();
298 }
299
300 public function searchUsers(bool $save = true): void
301 {
302 $this->tpl->setTitle($this->lng->txt('mail'));
303
304 if ($save) {
305 $files = $this->getBodyParam(
306 'attachments',
307 $this->refinery->kindlyTo()->listOf(
308 $this->refinery->custom()->transformation(function ($elm): string {
309 $attachment = $this->refinery->kindlyTo()->string()->transform($elm);
310
311 return urldecode($attachment);
312 })
313 ),
314 []
315 );
316
317 // Note: For security reasons, ILIAS only allows Plain text strings in E-Mails.
318 $this->umail->persistToStage(
319 $this->user->getId(),
320 $files,
321 ilUtil::securePlainString($this->getBodyParam('rcp_to', $this->refinery->kindlyTo()->string(), '')),
322 ilUtil::securePlainString($this->getBodyParam('rcp_cc', $this->refinery->kindlyTo()->string(), '')),
323 ilUtil::securePlainString($this->getBodyParam('rcp_bcc', $this->refinery->kindlyTo()->string(), '')),
324 ilUtil::securePlainString($this->getBodyParam('m_subject', $this->refinery->kindlyTo()->string(), '')),
325 ilUtil::securePlainString($this->getBodyParam('m_message', $this->refinery->kindlyTo()->string(), '')),
326 $this->getBodyParam('use_placeholders', $this->refinery->kindlyTo()->bool(), false),
329 );
330 }
331
332 $form = new ilPropertyFormGUI();
333 $form->setId('search_rcp');
334 $form->setTitle($this->lng->txt('search_recipients'));
335 $form->setFormAction($this->ctrl->getFormAction($this, 'search'));
336
337 $inp = new ilTextInputGUI($this->lng->txt('search_for'), 'search');
338 $inp->setSize(30);
339 $data_source_url = $this->ctrl->getLinkTarget($this, 'lookupRecipientAsync', '', true);
340 $inp->setDataSource($data_source_url);
341
342 $search_query = trim((string) ilSession::get('mail_search_search'));
343 if ($search_query !== '') {
344 $inp->setValue(ilLegacyFormElementsUtil::prepareFormOutput($search_query, true));
345 }
346 $form->addItem($inp);
347
348 $form->addCommandButton('search', $this->lng->txt('search'));
349 $form->addCommandButton('cancelSearch', $this->lng->txt('cancel'));
350
351 $this->tpl->setContent($form->getHTML());
352 $this->tpl->printToStdout();
353 }
354
355 public function searchCoursesTo(): void
356 {
357 $this->saveMailBeforeSearch();
358
359 if (ilSession::get('search_crs')) {
360 $this->ctrl->setParameterByClass('ilmailsearchcoursesgui', 'cmd', 'showMembers');
361 }
362
363 $this->ctrl->setParameterByClass(ilMailSearchCoursesGUI::class, 'ref', 'mail');
364 $this->ctrl->redirectByClass(ilMailSearchCoursesGUI::class);
365 }
366
367 public function searchGroupsTo(): void
368 {
369 $this->saveMailBeforeSearch();
370
371 $this->ctrl->setParameterByClass(ilMailSearchGroupsGUI::class, 'ref', 'mail');
372 $this->ctrl->redirectByClass(ilMailSearchGroupsGUI::class);
373 }
374
375 public function search(): void
376 {
378 'mail_search_search',
379 ilUtil::securePlainString($this->getBodyParam('search', $this->refinery->kindlyTo()->string(), ''))
380 );
381
382 if (trim(ilSession::get('mail_search_search') ?? '') === '') {
383 $this->tpl->setOnScreenMessage('info', $this->lng->txt('mail_insert_query'));
384 $this->searchUsers(false);
385 } elseif (strlen(trim(ilSession::get('mail_search_search') ?? '')) < 3) {
386 $this->lng->loadLanguageModule('search');
387 $this->tpl->setOnScreenMessage('info', $this->lng->txt('search_minimum_three'));
388 $this->searchUsers(false);
389 } else {
390 $this->ctrl->setParameterByClass(
391 ilMailSearchGUI::class,
392 'search',
393 urlencode(ilSession::get('mail_search_search') ?? '')
394 );
395 $this->ctrl->redirectByClass(ilMailSearchGUI::class);
396 }
397 }
398
399 public function cancelSearch(): void
400 {
401 ilSession::clear('mail_search');
402 $this->searchResults();
403 }
404
405 public function editAttachments(): void
406 {
407 $files = $this->getBodyParam(
408 'attachments',
409 $this->refinery->kindlyTo()->listOf(
410 $this->refinery->custom()->transformation(function ($elm): string {
411 $attachment = $this->refinery->kindlyTo()->string()->transform($elm);
412
413 return urldecode($attachment);
414 })
415 ),
416 []
417 );
418
419 // Note: For security reasons, ILIAS only allows Plain text strings in E-Mails.
420 $this->umail->persistToStage(
421 $this->user->getId(),
422 $files,
423 ilUtil::securePlainString($this->getBodyParam('rcp_to', $this->refinery->kindlyTo()->string(), '')),
424 ilUtil::securePlainString($this->getBodyParam('rcp_cc', $this->refinery->kindlyTo()->string(), '')),
425 ilUtil::securePlainString($this->getBodyParam('rcp_bcc', $this->refinery->kindlyTo()->string(), '')),
426 ilUtil::securePlainString($this->getBodyParam('m_subject', $this->refinery->kindlyTo()->string(), '')),
427 ilUtil::securePlainString($this->getBodyParam('m_message', $this->refinery->kindlyTo()->string(), '')),
428 $this->getBodyParam('use_placeholders', $this->refinery->kindlyTo()->bool(), false),
431 );
432
433 $this->ctrl->redirectByClass(ilMailAttachmentGUI::class);
434 }
435
436 public function returnFromAttachments(): void
437 {
438 $this->mail_form_type = self::MAIL_FORM_TYPE_ATTACH;
439 $this->showForm();
440 }
441
442 public function searchResults(): void
443 {
444 $this->mail_form_type = self::MAIL_FORM_TYPE_SEARCH_RESULT;
445 $this->showForm();
446 }
447
448 public function mailUser(): void
449 {
450 $this->mail_form_type = self::MAIL_FORM_TYPE_NEW;
451 $this->showForm();
452 }
453
454 public function mailRole(): void
455 {
456 $this->mail_form_type = self::MAIL_FORM_TYPE_ROLE;
457 $this->showForm();
458 }
459
460 public function replyMail(): void
461 {
462 $this->mail_form_type = self::MAIL_FORM_TYPE_REPLY;
463 $this->showForm();
464 }
465
466 public function mailAttachment(): void
467 {
468 $this->mail_form_type = self::MAIL_FORM_TYPE_ATTACH;
469 $this->showForm();
470 }
471
472 protected function getTemplateDataById(): void
473 {
474 if (!$this->http->wrapper()->query()->has('template_id')) {
475 $this->http->close();
476 }
477
478 try {
479 $template = $this->template_service->loadTemplateForId(
480 $this->http->wrapper()->query()->retrieve('template_id', $this->refinery->kindlyTo()->int())
481 );
483
484 $this->http->saveResponse(
485 $this->http->response()
486 ->withHeader(ResponseHeader::CONTENT_TYPE, 'application/json')
487 ->withBody(Streams::ofString(json_encode([
488 'm_subject' => $template->getSubject(),
489 'm_message' => $this->umail->appendSignature($template->getMessage()),
490 ], JSON_THROW_ON_ERROR)))
491 );
492 } catch (Exception) {
493 }
494
495 $this->http->sendResponse();
496 $this->http->close();
497 }
498
499 public function showForm(): void
500 {
501 $this->tpl->addBlockFile(
502 'ADM_CONTENT',
503 'adm_content',
504 'tpl.mail_new.html',
505 'components/ILIAS/Mail'
506 );
507 $this->tpl->setTitle($this->lng->txt('mail'));
508
509 $this->lng->loadLanguageModule('crs');
510
512 $this->tabs->setBackTarget(
513 $this->lng->txt('back'),
514 $this->ctrl->getLinkTarget($this, 'cancelMail')
515 );
516 }
517
518 $mail_data = [];
519 $mail_data['rcp_to'] = '';
520 $mail_data['rcp_cc'] = '';
521 $mail_data['rcp_bcc'] = '';
522 $mail_data['attachments'] = [];
523
524 $mail_id = $this->getQueryParam('mail_id', $this->refinery->kindlyTo()->int(), 0);
525 $type = $this->getQueryParam('type', $this->refinery->kindlyTo()->string(), '');
526 if ($this->mail_form_type !== '') {
527 $type = $this->mail_form_type;
528 }
529
530 switch ($type) {
532 $mail_data = $this->umail->getMail($mail_id);
533
534 $mail_data['m_subject'] = $this->umail->formatReplySubject($mail_data['m_subject'] ?? '');
535 $mail_data['m_message'] = $this->umail->prependSignature(
536 $this->umail->formatReplyMessage($mail_data['m_message'] ?? '')
537 );
538 $mail_data['attachments'] = [];
539 $mail_data['rcp_cc'] = '';
540 $mail_data['rcp_to'] = $this->umail->formatReplyRecipient();
541 break;
542
544 $mail_data = $this->umail->retrieveFromStage();
545
546 if (ilSession::get('mail_search_results_to')) {
547 $mail_data = $this->umail->appendSearchResult(
548 $this->refinery->kindlyTo()->listOf(
549 $this->refinery->kindlyTo()->string()
550 )->transform(ilSession::get('mail_search_results_to')),
551 'to'
552 );
553 }
554 if (ilSession::get('mail_search_results_cc')) {
555 $mail_data = $this->umail->appendSearchResult(
556 $this->refinery->kindlyTo()->listOf(
557 $this->refinery->kindlyTo()->string()
558 )->transform(ilSession::get('mail_search_results_cc')),
559 'cc'
560 );
561 }
562 if (ilSession::get('mail_search_results_bcc')) {
563 $mail_data = $this->umail->appendSearchResult(
564 $this->refinery->kindlyTo()->listOf(
565 $this->refinery->kindlyTo()->string()
566 )->transform(ilSession::get('mail_search_results_bcc')),
567 'bc'
568 );
569 }
570
571 ilSession::clear('mail_search_results_to');
572 ilSession::clear('mail_search_results_cc');
573 ilSession::clear('mail_search_results_bcc');
574 break;
575
577 $mail_data = $this->umail->retrieveFromStage();
578 break;
579
581 ilSession::set('draft', $mail_id);
582 $mail_data = $this->umail->getMail($mail_id);
583 ilMailFormCall::setContextId($mail_data['tpl_ctx_id']);
584 ilMailFormCall::setContextParameters($mail_data['tpl_ctx_params']);
585 break;
586
588 $mail_data = $this->umail->getMail($mail_id);
589 $mail_data['rcp_to'] = $mail_data['rcp_cc'] = $mail_data['rcp_bcc'] = '';
590 $mail_data['m_subject'] = $this->umail->formatForwardSubject($mail_data['m_subject'] ?? '');
591 $mail_data['m_message'] = $this->umail->prependSignature($mail_data['m_message'] ?? '');
592 if (is_array($mail_data['attachments']) && count($mail_data['attachments']) && $error = $this->mfile->adoptAttachments(
593 $mail_data['attachments'],
594 $mail_id
595 )) {
596 $this->tpl->setOnScreenMessage('info', $error);
597 }
598 break;
599
601 // Note: For security reasons, ILIAS only allows Plain text strings in E-Mails.
602 $to = ilUtil::securePlainString($this->getQueryParam('rcp_to', $this->refinery->kindlyTo()->string(), ''));
603 if ($to === '' && ilSession::get('rcp_to')) {
604 $to = ilSession::get('rcp_to');
605 }
606 $mail_data['rcp_to'] = $to;
607
608 $cc = ilUtil::securePlainString($this->getQueryParam('rcp_cc', $this->refinery->kindlyTo()->string(), ''));
609 if ($cc === '' && ilSession::get('rcp_cc')) {
610 $cc = ilSession::get('rcp_cc');
611 }
612 $mail_data['rcp_cc'] = $cc;
613
614 $bcc = ilUtil::securePlainString($this->getQueryParam('rcp_bcc', $this->refinery->kindlyTo()->string(), ''));
615 if ($bcc === '' && ilSession::get('rcp_bcc')) {
616 $bcc = ilSession::get('rcp_bcc');
617 }
618 $mail_data['rcp_bcc'] = $bcc;
619
620 $mail_data['m_message'] = '';
621 if (($sig = ilMailFormCall::getSignature()) !== '') {
622 $mail_data['m_message'] = $sig;
623 $mail_data['m_message'] .= chr(13)
624 . chr(10)
625 . chr(13)
626 . chr(10);
627 }
628 $mail_data['m_message'] .= $this->umail->appendSignature('');
629
630 ilSession::set('rcp_to', '');
631 ilSession::set('rcp_cc', '');
632 ilSession::set('rcp_bcc', '');
633 break;
634
636 $roles = [];
637 if ($this->http->wrapper()->post()->has('roles')) {
638 $roles = $this->http->wrapper()->post()->retrieve(
639 'roles',
640 $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->string())
641 );
642 } elseif (is_array(ilSession::get('mail_roles'))) {
643 $roles = $this->refinery->kindlyTo()->listOf(
644 $this->refinery->kindlyTo()->string()
645 )->transform(ilSession::get('mail_roles'));
646 }
647
648 // Note: For security reasons, ILIAS only allows Plain text strings in E-Mails.
649 $mail_data['rcp_to'] = ilUtil::securePlainString(
650 implode(',', $roles)
651 );
652
653 $mail_data['m_message'] = '';
654 if (($sig = ilMailFormCall::getSignature()) !== '') {
655 $mail_data['m_message'] = $sig;
656 $mail_data['m_message'] .= chr(13)
657 . chr(10)
658 . chr(13)
659 . chr(10);
660 }
661
662 $additional_msg_text = '';
663 if ($this->http->wrapper()->post()->has('additional_message_text')) {
664 $additional_msg_text = ilUtil::securePlainString($this->http->wrapper()->post()->retrieve(
665 'additional_message_text',
666 $this->refinery->kindlyTo()->string()
667 ));
668 }
669
670 $mail_data['m_message'] .= $additional_msg_text
671 . chr(13)
672 . chr(10)
673 . $this->umail->appendSignature('');
674 ilSession::set('mail_roles', []);
675 break;
676
678 $rcp = '';
679 if ($this->http->wrapper()->query()->has('rcp')) {
680 $rcp = $this->http->wrapper()->query()->retrieve('rcp', $this->refinery->kindlyTo()->string());
681 }
682 $mail_data['rcp_to'] = urldecode((string) $rcp);
683 break;
684
685 default:
686 $mail_data = $this->http->request()->getParsedBody();
687 foreach ($mail_data as $key => $value) {
688 if (is_string($value)) {
689 // Note: For security reasons, ILIAS only allows Plain text strings in E-Mails.
690 $mail_data[$key] = ilUtil::securePlainString($value);
691 }
692 }
693
694 if ($this->request_attachments) {
695 $mail_data['attachments'] = $this->request_attachments;
696 }
697 break;
698 }
699
700 $form_gui = new ilPropertyFormGUI();
701 $form_gui->setTitle($this->lng->txt('compose'));
702 $form_gui->setId('mail_compose_form');
703 $form_gui->setName('mail_compose_form');
704 $form_gui->setFormAction($this->ctrl->getFormAction($this, 'sendMessage'));
705
706 $this->tpl->setVariable('FORM_ID', $form_gui->getId());
707
708 $mail_form = 'form_' . $form_gui->getName();
709
710 $btn = $this->ui_factory->button()
711 ->standard($this->lng->txt('search_recipients'), '#')
712 ->withOnLoadCode(static fn($id): string => "
713 document.getElementById('$id').addEventListener('click', function() {
714 const frm = document.getElementById('$mail_form'),
715 action = new URL(frm.action),
716 action_params = new URLSearchParams(action.search);
717
718 action_params.delete('cmd');
719 action_params.append('cmd', 'searchUsers');
720
721 action.search = action_params.toString();
722
723 frm.action = action.href;
724 frm.submit();
725 return false;
726 });
727 ");
728 $this->toolbar->addStickyItem($btn);
729
730 $btn = $this->ui_factory->button()
731 ->standard($this->lng->txt('mail_my_courses'), '#')
732 ->withOnLoadCode(static fn($id): string => "
733 document.getElementById('$id').addEventListener('click', function() {
734 const frm = document.getElementById('$mail_form'),
735 action = new URL(frm.action),
736 action_params = new URLSearchParams(action.search);
737
738 action_params.delete('cmd');
739 action_params.append('cmd', 'searchCoursesTo');
740
741 action.search = action_params.toString();
742
743 frm.action = action.href;
744 frm.submit();
745 return false;
746 });
747 ");
748 $this->toolbar->addComponent($btn);
749
750 $btn = $this->ui_factory->button()
751 ->standard($this->lng->txt('mail_my_groups'), '#')
752 ->withOnLoadCode(static fn($id): string => "
753 document.getElementById('$id').addEventListener('click', function() {
754 const frm = document.getElementById('$mail_form'),
755 action = new URL(frm.action),
756 action_params = new URLSearchParams(action.search);
757
758 action_params.delete('cmd');
759 action_params.append('cmd', 'searchGroupsTo');
760
761 action.search = action_params.toString();
762
763 frm.action = action.href;
764 frm.submit();
765 return false;
766 });
767 ");
768 $this->toolbar->addComponent($btn);
769
770 if (count(ilBuddyList::getInstanceByGlobalUser()->getLinkedRelations()) > 0) {
771 $btn = $this->ui_factory->button()
772 ->standard($this->lng->txt('mail_my_mailing_lists'), '#')
773 ->withOnLoadCode(static fn($id): string => "
774 document.getElementById('$id').addEventListener('click', function() {
775 const frm = document.getElementById('$mail_form'),
776 action = new URL(frm.action),
777 action_params = new URLSearchParams(action.search);
778
779 action_params.delete('cmd');
780 action_params.append('cmd', 'searchMailingListsTo');
781
782 action.search = action_params.toString();
783
784 frm.action = action.href;
785 frm.submit();
786 return false;
787 });
788 ");
789 $this->toolbar->addComponent($btn);
790 }
791
792 $data_source_url = $this->ctrl->getLinkTarget($this, 'lookupRecipientAsync', '', true);
793
794 $inp = new ilTextInputGUI($this->lng->txt('mail_to'), 'rcp_to');
795 $inp->setMaxLength(null);
796 $inp->setRequired(true);
797 $inp->setSize(50);
798 $inp->setValue((string) ($mail_data['rcp_to'] ?? ''));
799 $inp->setDataSource($data_source_url, ',');
800 $form_gui->addItem($inp);
801
802 $inp = new ilTextInputGUI($this->lng->txt('mail_cc'), 'rcp_cc');
803 $inp->setMaxLength(null);
804 $inp->setSize(50);
805 $inp->setValue((string) ($mail_data['rcp_cc'] ?? ''));
806 $inp->setDataSource($data_source_url, ',');
807 $form_gui->addItem($inp);
808
809 $inp = new ilTextInputGUI($this->lng->txt('mail_bcc'), 'rcp_bcc');
810 $inp->setMaxLength(null);
811 $inp->setSize(50);
812 $inp->setValue($mail_data['rcp_bcc'] ?? '');
813 $inp->setDataSource($data_source_url, ',');
814 $form_gui->addItem($inp);
815
816 $inp = new ilTextInputGUI($this->lng->txt('subject'), 'm_subject');
817 $inp->setSize(50);
818 $inp->setRequired(true);
819 $inp->setValue((string) ($mail_data['m_subject'] ?? ''));
820 $form_gui->addItem($inp);
821
823 $this->lng->txt(
824 isset($mail_data['attachments']) && is_array($mail_data['attachments']) ?
825 'edit' :
826 'add'
827 ),
828 'm_attachment'
829 );
830 if (isset($mail_data['attachments']) && is_array($mail_data['attachments'])) {
831 foreach ($mail_data['attachments'] as $data) {
832 if (is_file($this->mfile->getMailPath() . '/' . $this->user->getId() . '_' . $data)) {
833 $hidden = new ilHiddenInputGUI('attachments[]');
834 $form_gui->addItem($hidden);
835 $size = filesize($this->mfile->getMailPath() . '/' . $this->user->getId() . '_' . $data);
836 $label = $data . ' [' . ilUtil::formatSize($size) . ']';
837 $att->addItem($label);
838 $hidden->setValue(urlencode((string) $data));
839 }
840 }
841 }
842 $form_gui->addItem($att);
843
846 $context_id = ilMailFormCall::getContextId();
847
848 $mail_data['use_placeholders'] = true;
849
850 try {
852
853 $templates = $this->template_service->loadTemplatesForContextId($context->getId());
854 if ($templates !== []) {
855 $options = [];
856
857 $template_chb = new ilMailTemplateSelectInputGUI(
858 $this->lng->txt('mail_template_client'),
859 'template_id',
860 $this->ctrl->getLinkTarget($this, 'getTemplateDataById', '', true),
861 ['m_subject' => false, 'm_message' => true]
862 );
863
864 foreach ($templates as $template) {
865 $options[$template->getTplId()] = $template->getTitle();
866
867 if (!isset($mail_data['template_id']) && $template->isDefault()) {
868 $template_chb->setValue((string) $template->getTplId());
869 $form_gui->getItemByPostVar('m_subject')->setValue($template->getSubject());
870 $mail_data['m_message'] = $template->getMessage() . $this->umail->appendSignature(
871 $mail_data['m_message']
872 );
873 }
874 }
875 if (isset($mail_data['template_id'])) {
876 $template_chb->setValue((string) ((int) $mail_data['template_id']));
877 }
878 asort($options);
879
880 $template_chb->setInfo($this->lng->txt('mail_template_client_info'));
881 $template_chb->setOptions(['' => $this->lng->txt('please_choose')] + $options);
882 $form_gui->addItem($template_chb);
883 }
884 } catch (Exception) {
885 ilLoggerFactory::getLogger('mail')->error(sprintf(
886 '%s has been called with invalid context id: %s.',
887 __METHOD__,
888 $context_id
889 ));
890 }
891 }
892
893 $inp = new ilTextAreaInputGUI($this->lng->txt('message_content'), 'm_message');
894 $inp->setValue((string) ($mail_data['m_message'] ?? ''));
895 $inp->setRequired(false);
896 $inp->setCols(60);
897 $inp->setRows(10);
898 $form_gui->addItem($inp);
899
900 $chb = new ilCheckboxInputGUI(
901 $this->lng->txt('mail_serial_letter_placeholders'),
902 'use_placeholders'
903 );
904 $chb->setValue('1');
905 $chb->setChecked(isset($mail_data['use_placeholders']) && $mail_data['use_placeholders']);
906
907 $placeholders = new ilManualPlaceholderInputGUI(
908 $this->lng->txt('mail_form_placeholders_label'),
909 'm_placeholders',
910 'm_message'
911 );
912 $placeholders->setInstructionText($this->lng->txt('mail_nacc_use_placeholder'));
913 try {
914 $placeholders->setAdviseText(sprintf($this->lng->txt('placeholders_advise'), '<br />'));
915 } catch (Throwable) {
916 $placeholders->setAdviseText($this->lng->txt('placeholders_advise'));
917 }
918 foreach ($context->getPlaceholders() as $key => $value) {
919 $placeholders->addPlaceholder($value['placeholder'], $value['label']);
920 }
921 $chb->addSubItem($placeholders);
922 $form_gui->addItem($chb);
923
924 $form_gui->addCommandButton('sendMessage', $this->lng->txt('send_mail'));
925 $form_gui->addCommandButton('saveDraft', $this->lng->txt('save_message'));
927 $form_gui->addCommandButton('cancelMail', $this->lng->txt('cancel'));
928 }
929
930 $this->tpl->parseCurrentBlock();
931
932 $this->tpl->setVariable('FORM', $form_gui->getHTML());
933
934 $this->tpl->addJavaScript('assets/js/ilMailComposeFunctions.js');
935 $this->tpl->printToStdout();
936 }
937
938 public function lookupRecipientAsync(): void
939 {
940 $search = trim((string) $this->getBodyParam(
941 'term',
942 $this->refinery->kindlyTo()->string(),
943 $this->getQueryParam(
944 'term',
945 $this->refinery->kindlyTo()->string(),
946 ''
947 )
948 ));
949
950 $result = [];
951
952 if (ilStr::strLen($search) < 3) {
953 $this->http->saveResponse(
954 $this->http->response()
955 ->withHeader(ResponseHeader::CONTENT_TYPE, 'application/json')
956 ->withBody(Streams::ofString(json_encode($result, JSON_THROW_ON_ERROR)))
957 );
958
959 $this->http->sendResponse();
960 $this->http->close();
961 }
962
963 // #14768
964 $quoted = ilUtil::stripSlashes($search);
965 $quoted = str_replace(['%', '_'], ['\%', '\_'], $quoted);
966
967 $form = new ilMailForm();
968 $result = $form->getRecipientAsync('%' . $quoted . '%', ilUtil::stripSlashes($search));
969
970 $this->http->saveResponse(
971 $this->http->response()
972 ->withHeader(ResponseHeader::CONTENT_TYPE, 'application/json')
973 ->withBody(Streams::ofString(json_encode($result, JSON_THROW_ON_ERROR)))
974 );
975 $this->http->sendResponse();
976 $this->http->close();
977 }
978
979 public function cancelMail(): void
980 {
983 }
984
985 $this->showForm();
986 }
987
988 protected function saveMailBeforeSearch(): void
989 {
990 $files = $this->getBodyParam(
991 'attachments',
992 $this->refinery->kindlyTo()->listOf(
993 $this->refinery->custom()->transformation(function ($elm): string {
994 $attachment = $this->refinery->kindlyTo()->string()->transform($elm);
995
996 return urldecode($attachment);
997 })
998 ),
999 []
1000 );
1001
1002 $this->umail->persistToStage(
1003 $this->user->getId(),
1004 $files,
1005 ilUtil::securePlainString($this->getBodyParam('rcp_to', $this->refinery->kindlyTo()->string(), '')),
1006 ilUtil::securePlainString($this->getBodyParam('rcp_cc', $this->refinery->kindlyTo()->string(), '')),
1007 ilUtil::securePlainString($this->getBodyParam('rcp_bcc', $this->refinery->kindlyTo()->string(), '')),
1008 ilUtil::securePlainString($this->getBodyParam('m_subject', $this->refinery->kindlyTo()->string(), '')),
1009 ilUtil::securePlainString($this->getBodyParam('m_message', $this->refinery->kindlyTo()->string(), '')),
1010 $this->getBodyParam('use_placeholders', $this->refinery->kindlyTo()->bool(), false),
1013 );
1014 }
1015
1016 public function searchMailingListsTo(): void
1017 {
1018 $this->saveMailBeforeSearch();
1019
1020 $this->ctrl->setParameterByClass(ilMailingListsGUI::class, 'ref', 'mail');
1021 $this->ctrl->redirectByClass(ilMailingListsGUI::class);
1022 }
1023
1027 protected function showSubmissionErrors(array $errors): void
1028 {
1029 $formatter = new ilMailErrorFormatter($this->lng);
1030 $formatted_errors = $formatter->format($errors);
1031
1032 if ($formatted_errors !== '') {
1033 $this->tpl->setOnScreenMessage('failure', $formatted_errors);
1034 }
1035 }
1036}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
Builds a Color from either hex- or rgb values.
Definition: Factory.php:31
Builds data types.
Definition: Factory.php:36
Stream factory which enables the user to create streams without the knowledge of the concrete class.
Definition: Streams.php:32
static getInstanceByGlobalUser(?ilObjUser $user=null)
This class represents a checkbox property in a property form.
This class represents a hidden form property in a property form.
language handling
static prepareFormOutput($a_str, bool $a_strip=false)
static getLogger(string $a_component_id)
Get component logger.
static setContextId(?string $id)
static setContextParameters(array $parameters)
@ilCtrl_Calls ilMailFormGUI: ilMailAttachmentGUI, ilMailSearchGUI, ilMailSearchCoursesGUI,...
final const string MAIL_FORM_TYPE_DRAFT
final const string MAIL_FORM_TYPE_NEW
readonly ilFormatMail $umail
readonly ilFileDataMail $mfile
final const string MAIL_FORM_TYPE_ATTACH
readonly ilObjUser $user
final const string MAIL_FORM_TYPE_ADDRESS
final const string MAIL_FORM_TYPE_FORWARD
__construct(?ilMailTemplateService $template_service=null, ?ilMailBodyPurifier $body_purifier=null)
final const string MAIL_FORM_TYPE_SEARCH_RESULT
showSubmissionErrors(array $errors)
ilMailTemplateService $template_service
readonly ilMailbox $mbox
getQueryParam(string $name, Transformation $trafo, $default=null)
readonly GlobalHttpState $http
final const string MAIL_FORM_TYPE_REPLY
searchUsers(bool $save=true)
readonly ilCtrlInterface $ctrl
readonly ilMailBodyPurifier $purifier
readonly Refinery $refinery
readonly ilTabsGUI $tabs
decodeAttachmentFiles(array $files)
getBodyParam(string $name, Transformation $trafo, $default=null)
readonly ilGlobalTemplateInterface $tpl
final const string MAIL_FORM_TYPE_ROLE
readonly ilToolbarGUI $toolbar
readonly Factory $ui_factory
readonly ilLanguage $lng
User class.
This class represents a property form user interface.
static get(string $a_var)
static clear(string $a_var)
static set(string $a_var, $a_val)
Set a value.
static strLen(string $a_string)
Definition: class.ilStr.php:60
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This class represents a text area property in a property form.
This class represents a text property in a property form.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static formatSize(int $size, string $a_mode='short', ?ilLanguage $a_lng=null)
Returns the specified file size value in a human friendly form.
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
static securePlainString(string $a_str)
static redirect(string $a_script)
Interface GlobalHttpState.
Interface ResponseHeader.
A transformation is a function from one datatype to another.
This is how the factory for UI elements looks.
Definition: Factory.php:38
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static http()
Fetches the global http state from ILIAS.
global $DIC
Definition: shib_login.php:26
$context
Definition: webdav.php:31
$message
Definition: xapiexit.php:31