1<?php declare(strict_types=1);
2
3/* Copyright (c) 1998-2010 ILIAS open source, Extended GPL, see docs/LICENSE */
4
5use Psr\Http\Message\ServerRequestInterface;
6
7/**
8 * @author       Jens Conze
9 * @version      $Id$
10 * @ingroup      ServicesMail
11 * @ilCtrl_Calls ilMailFolderGUI: ilMailOptionsGUI, ilMailAttachmentGUI, ilMailSearchGUI
12 * @ilCtrl_Calls ilMailFolderGUI: ilPublicUserProfileGUI
13 */
14class ilMailFolderGUI
15{
16    /** @var bool */
17    private $confirmTrashDeletion = false;
18
19    /** @var bool */
20    private $errorDelete = false;
21
22    /** @var ilGlobalTemplate */
23    private $tpl;
24
25    /** @var ilCtrl */
26    private $ctrl;
27
28    /** @var ilLanguage */
29    private $lng;
30
31    /** @var ilToolbarGUI */
32    private $toolbar;
33
34    /** @var ilTabsGUI */
35    private $tabs;
36
37    /** @var ilObjUser */
38    private $user;
39
40    /** @var ilMail */
41    public $umail;
42
43    /** @var ilMailBox */
44    public $mbox;
45
46    /** @var ServerRequestInterface */
47    private $httpRequest;
48
49    /** @var int */
50    private $currentFolderId = 0;
51
52    /**
53     * ilMailFolderGUI constructor.
54     */
55    public function __construct()
56    {
57        global $DIC;
58
59        $this->tpl = $DIC->ui()->mainTemplate();
60        $this->ctrl = $DIC->ctrl();
61        $this->lng = $DIC->language();
62        $this->toolbar = $DIC->toolbar();
63        $this->user = $DIC->user();
64        $this->tabs = $DIC->tabs();
65        $this->httpRequest = $DIC->http()->request();
66
67        $this->umail = new ilMail($this->user->getId());
68        $this->mbox = new ilMailbox($this->user->getId());
69
70        $this->initFolder();
71    }
72
73    /**
74     *
75     */
76    protected function initFolder() : void
77    {
78        $folderId = (int) ($this->httpRequest->getParsedBody()['mobj_id'] ?? 0);
79        if (0 === $folderId) {
80            $folderId = (int) ($this->httpRequest->getQueryParams()['mobj_id'] ?? 0);
81        }
82
83        if (0 === $folderId || !$this->mbox->isOwnedFolder($folderId)) {
84            $folderId = $this->mbox->getInboxFolder();
85        }
86
87        $this->currentFolderId = (int) $folderId;
88    }
89
90    /**
91     * @param string $originalCommand
92     * @return string
93     */
94    protected function parseCommand(string $originalCommand) : string
95    {
96        $matches = [];
97        if (preg_match('/^([a-zA-Z0-9]+?)_(\d+?)$/', $originalCommand, $matches) && 3 === count($matches)) {
98            $originalCommand = $matches[1];
99        }
100
101        return $originalCommand;
102    }
103
104    /**
105     * @param string $command
106     * @return int
107     * @throws InvalidArgumentException
108     */
109    protected function parseFolderIdFromCommand(string $command) : int
110    {
111        $matches = [];
112        if (
113            preg_match('/^([a-zA-Z0-9]+?)_(\d+?)$/', $command, $matches) &&
114            3 === count($matches) && is_numeric($matches[2])
115        ) {
116            return (int) $matches[2];
117        }
118
119        throw new InvalidArgumentException("Cannot parse a numeric folder id from command string!");
120    }
121
122    /**
123     *
124     */
125    public function executeCommand() : void
126    {
127        $cmd = $this->parseCommand(
128            $this->ctrl->getCmd()
129        );
130
131        $nextClass = $this->ctrl->getNextClass($this);
132        switch ($nextClass) {
133            case 'ilcontactgui':
134                $this->ctrl->forwardCommand(new ilContactGUI());
135                break;
136
137            case 'ilmailoptionsgui':
138                $this->tpl->setTitle($this->lng->txt('mail'));
139                $this->ctrl->forwardCommand(new ilMailOptionsGUI());
140                break;
141
142            case 'ilpublicuserprofilegui':
143                $this->tpl->setTitle($this->lng->txt('mail'));
144                $profileGui = new ilPublicUserProfileGUI((int) ($this->httpRequest->getQueryParams()['user'] ?? 0));
145
146                $this->ctrl->setParameter($this, 'mobj_id', $this->currentFolderId);
147                $profileGui->setBackUrl($this->ctrl->getLinkTarget($this, 'showMail'));
148                $this->ctrl->clearParameters($this);
149
150                $ret = $this->ctrl->forwardCommand($profileGui);
151                if ($ret != '') {
152                    $this->tpl->setContent($ret);
153                }
154                $this->tpl->printToStdout();
155                break;
156
157            default:
158                if (!method_exists($this, $cmd)) {
159                    $cmd = 'showFolder';
160                }
161                $this->{$cmd}();
162                break;
163        }
164    }
165
166    /**
167     * Called if the deletion of all messages in trash was confirmed by the acting user
168     */
169    protected function performEmptyTrash() : void
170    {
171        $this->umail->deleteMailsOfFolder($this->currentFolderId);
172
173        ilUtil::sendSuccess($this->lng->txt('mail_deleted'), true);
174        $this->ctrl->setParameter($this, 'mobj_id', $this->currentFolderId);
175        $this->ctrl->redirect($this, 'showFolder');
176    }
177
178    /**
179     * Called if the deletion of messages in trash should be confirmed by the acting user
180     */
181    protected function confirmEmptyTrash() : void
182    {
183        if ($this->umail->countMailsOfFolder($this->currentFolderId)) {
184            $this->confirmTrashDeletion = true;
185        }
186
187        $this->showFolder();
188    }
189
190    /**
191     * @throws ilCtrlException
192     */
193    protected function showUser() : void
194    {
195        $this->tpl->setVariable('TBL_TITLE', implode(' ', [
196            $this->lng->txt('profile_of'),
197            ilObjUser::_lookupLogin((int) ($this->httpRequest->getQueryParams()['user'] ?? 0))
198        ]));
199        $this->tpl->setVariable('TBL_TITLE_IMG', ilUtil::getImagePath('icon_usr.svg'));
200        $this->tpl->setVariable('TBL_TITLE_IMG_ALT', $this->lng->txt('public_profile'));
201
202        $profile_gui = new ilPublicUserProfileGUI((int) ($this->httpRequest->getQueryParams()['user'] ?? 0));
203
204        $this->ctrl->setParameter($this, 'mail_id', (int) $this->httpRequest->getQueryParams()['mail_id']);
205        $this->ctrl->setParameter($this, 'mobj_id', $this->currentFolderId);
206        $profile_gui->setBackUrl($this->ctrl->getLinkTarget($this, 'showMail'));
207        $this->ctrl->clearParameters($this);
208
209        $this->tpl->setTitle($this->lng->txt('mail'));
210        $this->tpl->setContent($this->ctrl->getHTML($profile_gui));
211        $this->tpl->printToStdout();
212    }
213
214    /**
215     * @param bool $isUserSubFolder
216     */
217    protected function addSubFolderCommands(bool $isUserSubFolder = false) : void
218    {
219        $this->ctrl->setParameter($this, 'mobj_id', $this->currentFolderId);
220        $this->toolbar->addButton(
221            $this->lng->txt('mail_add_subfolder'),
222            $this->ctrl->getLinkTarget($this, 'addSubFolder')
223        );
224
225        if ($isUserSubFolder) {
226            $this->toolbar->addButton($this->lng->txt('rename'), $this->ctrl->getLinkTarget($this, 'renameSubFolder'));
227            $this->toolbar->addButton($this->lng->txt('delete'), $this->ctrl->getLinkTarget($this, 'deleteSubFolder'));
228        }
229        $this->ctrl->clearParameters($this);
230    }
231
232    /**
233     * Shows current folder. Current Folder is determined by $_GET["mobj_id"]
234     * @param bool $oneConfirmationDialogueRendered
235     */
236    protected function showFolder(bool $oneConfirmationDialogueRendered = false) : void
237    {
238        $this->tpl->addBlockFile('ADM_CONTENT', 'adm_content', 'tpl.mail.html', 'Services/Mail');
239        $this->tpl->setTitle($this->lng->txt('mail'));
240
241        $isTrashFolder = $this->currentFolderId == $this->mbox->getTrashFolder();
242
243        if ($isTrashFolder && 'deleteMails' === $this->parseCommand($this->ctrl->getCmd()) && !$this->errorDelete) {
244            $confirmationGui = new ilConfirmationGUI();
245            $confirmationGui->setHeaderText($this->lng->txt('mail_sure_delete'));
246            foreach ($this->getMailIdsFromRequest() as $mailId) {
247                $confirmationGui->addHiddenItem('mail_id[]', $mailId);
248            }
249            $this->ctrl->setParameter($this, 'mobj_id', $this->currentFolderId);
250            $confirmationGui->setFormAction($this->ctrl->getFormAction($this, 'showFolder'));
251            $this->ctrl->clearParameters($this);
252            $confirmationGui->setConfirm($this->lng->txt('confirm'), 'confirmDeleteMails');
253            $confirmationGui->setCancel($this->lng->txt('cancel'), 'showFolder');
254            $this->tpl->setVariable('CONFIRMATION', $confirmationGui->getHTML());
255            $oneConfirmationDialogueRendered = true;
256        }
257
258        $folders = $this->mbox->getSubFolders();
259        $mtree = new ilTree($this->user->getId());
260        $mtree->setTableNames('mail_tree', 'mail_obj_data');
261
262        $isUserSubFolder = false;
263        $isUserRootFolder = false;
264
265        $folder_d = $mtree->getNodeData($this->currentFolderId);
266        if ($folder_d['m_type'] === 'user_folder') {
267            $isUserSubFolder = true;
268        } elseif ($folder_d['m_type'] === 'local') {
269            $isUserRootFolder = true;
270        }
271
272        $mailtable = $this->getMailFolderTable();
273        $mailtable->setSelectedItems($this->getMailIdsFromRequest(true));
274
275        try {
276            $mailtable->prepareHTML();
277        } catch (Exception $e) {
278            ilUtil::sendFailure(
279                $this->lng->txt($e->getMessage()) != '-' . $e->getMessage() . '-' ?
280                    $this->lng->txt($e->getMessage()) :
281                    $e->getMessage()
282            );
283        }
284
285        $table_html = $mailtable->getHtml();
286
287        $folder_options = [];
288        foreach ($folders as $folder) {
289            $folder_d = $mtree->getNodeData($folder['obj_id']);
290
291            if ($folder['obj_id'] == $this->currentFolderId) {
292                if ($folder['type'] === 'user_folder') {
293                    $isUserSubFolder = true;
294                } elseif ($folder['type'] === 'local') {
295                    $isUserRootFolder = true;
296                    $isUserSubFolder = false;
297                }
298            }
299
300            $folder_options[$folder['obj_id']] = sprintf(
301                $this->lng->txt('mail_change_to_folder'),
302                $this->lng->txt('mail_' . $folder['title'])
303            );
304            if ($folder['type'] === 'user_folder') {
305                $pre = '';
306                for ($i = 2; $i < $folder_d['depth'] - 1; $i++) {
307                    $pre .= '&nbsp;';
308                }
309
310                if ($folder_d['depth'] > 1) {
311                    $pre .= '+';
312                }
313
314                $folder_options[$folder['obj_id']] = sprintf(
315                    $this->lng->txt('mail_change_to_folder'),
316                    $pre . ' ' . $folder['title']
317                );
318            }
319        }
320
321        if ($oneConfirmationDialogueRendered === false && $this->confirmTrashDeletion === false) {
322            $this->toolbar->setFormAction($this->ctrl->getFormAction($this, 'showFolder'));
323
324            if ($isUserRootFolder == true || $isUserSubFolder == true) {
325                $this->addSubFolderCommands($isUserSubFolder);
326            }
327        }
328
329        if ($mailtable->isTrashFolder() && $mailtable->getNumberOfMails() > 0 && $this->confirmTrashDeletion === true) {
330            $confirmationGui = new ilConfirmationGUI();
331            $confirmationGui->setHeaderText($this->lng->txt('mail_empty_trash_confirmation'));
332            $this->ctrl->setParameter($this, 'mobj_id', $this->currentFolderId);
333            $confirmationGui->setFormAction($this->ctrl->getFormAction($this, 'performEmptyTrash'));
334            $this->ctrl->clearParameters($this);
335            $confirmationGui->setConfirm($this->lng->txt('confirm'), 'performEmptyTrash');
336            $confirmationGui->setCancel($this->lng->txt('cancel'), 'showFolder');
337            $this->tpl->setVariable('CONFIRMATION', $confirmationGui->getHTML());
338        }
339
340        $this->tpl->setVariable('MAIL_TABLE', $table_html);
341        $this->tpl->printToStdout();
342    }
343
344    /**
345     * @param bool $a_show_confirm
346     */
347    protected function deleteSubFolder($a_show_confirm = true) : void
348    {
349        if ($a_show_confirm) {
350            $confirmationGui = new ilConfirmationGUI();
351            $this->ctrl->setParameter($this, 'mobj_id', $this->currentFolderId);
352            $confirmationGui->setFormAction($this->ctrl->getFormAction($this, 'showFolder'));
353            $this->ctrl->clearParameters($this);
354            $confirmationGui->setHeaderText($this->lng->txt('mail_sure_delete_folder'));
355            $confirmationGui->setCancel($this->lng->txt('cancel'), 'showFolder');
356            $confirmationGui->setConfirm($this->lng->txt('confirm'), 'performDeleteSubFolder');
357            $this->tpl->setVariable('CONFIRMATION', $confirmationGui->getHTML());
358
359            $this->showFolder(true);
360        } else {
361            $this->showFolder(false);
362        }
363    }
364
365    /**
366     * @throws ilInvalidTreeStructureException
367     */
368    protected function performDeleteSubFolder() : void
369    {
370        $parentFolderId = $this->mbox->getParentFolderId($this->currentFolderId);
371        if ($parentFolderId > 0 && $this->mbox->deleteFolder($this->currentFolderId)) {
372            ilUtil::sendInfo($this->lng->txt('mail_folder_deleted'), true);
373            $this->ctrl->setParameterByClass('ilMailGUI', 'mobj_id', (int) $parentFolderId);
374            $this->ctrl->redirectByClass('ilMailGUI');
375        } else {
376            ilUtil::sendFailure($this->lng->txt('mail_error_delete'));
377            $this->showFolder();
378        }
379    }
380
381    /**
382     * @param string $mode
383     * @return ilPropertyFormGUI
384     */
385    protected function getSubFolderForm(string $mode = 'create') : ilPropertyFormGUI
386    {
387        $form = new ilPropertyFormGUI();
388        $this->ctrl->setParameter($this, 'mobj_id', $this->currentFolderId);
389        $form->setFormAction($this->ctrl->getFormAction($this, 'performAddSubFolder'));
390        $this->ctrl->clearParameters($this);
391        if ('edit' === $mode) {
392            $form->addCommandButton('performRenameSubFolder', $this->lng->txt('save'));
393            $form->setTitle($this->lng->txt('mail_rename_folder'));
394        } else {
395            $form->addCommandButton('performAddSubFolder', $this->lng->txt('save'));
396            $form->setTitle($this->lng->txt('mail_add_folder'));
397        }
398        $form->addCommandButton('showFolder', $this->lng->txt('cancel'));
399
400        $title = new ilTextInputGUI($this->lng->txt('title'), 'subfolder_title');
401        $title->setRequired(true);
402        $form->addItem($title);
403
404        return $form;
405    }
406
407    /**
408     * Called if a folder is created by the action user
409     */
410    protected function performAddSubFolder() : void
411    {
412        $form = $this->getSubFolderForm();
413        $isFormValid = $form->checkInput();
414        $form->setValuesByPost();
415        if (!$isFormValid) {
416            $this->addSubFolder($form);
417            return;
418        }
419
420        $newFolderId = $this->mbox->addFolder($this->currentFolderId, $form->getInput('subfolder_title'));
421        if ($newFolderId > 0) {
422            ilUtil::sendSuccess($this->lng->txt('mail_folder_created'), true);
423            $this->ctrl->setParameterByClass('ilMailGUI', 'mobj_id', $newFolderId);
424            $this->ctrl->redirectByClass('ilMailGUI');
425        }
426
427        ilUtil::sendFailure($this->lng->txt('mail_folder_exists'));
428        $this->addSubFolder($form);
429    }
430
431    /**
432     * Called if the acting user wants to create a folder
433     * @param ilPropertyFormGUI|null $form
434     */
435    protected function addSubFolder(ilPropertyFormGUI $form = null) : void
436    {
437        if (null === $form) {
438            $form = $this->getSubFolderForm();
439        }
440
441        $this->tpl->setTitle($this->lng->txt('mail'));
442        $this->tpl->setContent($form->getHTML());
443        $this->tpl->printToStdout();
444    }
445
446    /**
447     * Called if the folder title is renamed by the acting user
448     */
449    protected function performRenameSubFolder() : void
450    {
451        $form = $this->getSubFolderForm('edit');
452        $isFormValid = $form->checkInput();
453        $form->setValuesByPost();
454        if (!$isFormValid) {
455            $this->renameSubFolder($form);
456            return;
457        }
458
459        $folderData = $this->mbox->getFolderData($this->currentFolderId);
460        if ($folderData['title'] === $form->getInput('subfolder_title')) {
461            $this->showFolder();
462            return;
463        }
464
465        if ($this->mbox->renameFolder($this->currentFolderId, $form->getInput('subfolder_title'))) {
466            ilUtil::sendSuccess($this->lng->txt('mail_folder_name_changed'), true);
467            $this->ctrl->setParameterByClass('ilMailGUI', 'mobj_id', $this->currentFolderId);
468            $this->ctrl->redirectByClass('ilMailGUI');
469        }
470
471        ilUtil::sendFailure($this->lng->txt('mail_folder_exists'));
472        $this->renameSubFolder($form);
473    }
474
475    /**
476     * Called if the acting user wants to rename a folder
477     * @param ilPropertyFormGUI|null $form
478     */
479    protected function renameSubFolder(ilPropertyFormGUI $form = null) : void
480    {
481        if (null === $form) {
482            $form = $this->getSubFolderForm('edit');
483            $form->setValuesByArray(['subfolder_title' => $this->mbox->getFolderData($this->currentFolderId)['title']]);
484        }
485
486        $this->tpl->setTitle($this->lng->txt('mail'));
487        $this->tpl->setContent($form->getHTML());
488        $this->tpl->printToStdout();
489    }
490
491    /**
492     * @param bool $ignoreHttpGet
493     * @return int[]
494     */
495    protected function getMailIdsFromRequest(bool $ignoreHttpGet = false) : array
496    {
497        $mailIds = $this->httpRequest->getParsedBody()['mail_id'] ?? [];
498        if (!is_array($mailIds)) {
499            return [];
500        }
501
502        if (0 === count($mailIds) && !$ignoreHttpGet) {
503            $mailId = $this->httpRequest->getQueryParams()['mail_id'] ?? 0;
504            if (is_numeric($mailId)) {
505                $mailIds = [$mailId];
506            }
507        }
508
509        return array_filter(array_map('intval', $mailIds));
510    }
511
512    /**
513     * Called if multiple messages should be marked as read in the list view
514     */
515    protected function markMailsRead() : void
516    {
517        $mailIds = $this->getMailIdsFromRequest();
518        if (count($mailIds) > 0) {
519            $this->umail->markRead($mailIds);
520            ilUtil::sendSuccess($this->lng->txt('saved_successfully'));
521        } else {
522            ilUtil::sendInfo($this->lng->txt('mail_select_one'));
523        }
524
525        $this->showFolder();
526    }
527
528    /**
529     * Called if multiple messages should be marked as un-read in the list view
530     */
531    protected function markMailsUnread() : void
532    {
533        $mailIds = $this->getMailIdsFromRequest();
534        if (count($mailIds) > 0) {
535            $this->umail->markUnread($mailIds);
536            ilUtil::sendSuccess($this->lng->txt('saved_successfully'));
537        } else {
538            ilUtil::sendInfo($this->lng->txt('mail_select_one'));
539        }
540
541        $this->showFolder();
542    }
543
544    /**
545     * Called if a single message should be be moved in the detail view
546     */
547    protected function moveSingleMail() : void
548    {
549        $mailIds = $this->getMailIdsFromRequest();
550        if (1 !== count($mailIds)) {
551            $this->showMail();
552            ilUtil::sendInfo($this->lng->txt('mail_select_one'));
553            return;
554        }
555
556        $newFolderId = (int) ($this->httpRequest->getParsedBody()['folder_id'] ?? 0);
557        $redirectFolderId = $newFolderId;
558        foreach ($mailIds as $mailId) {
559            $mailData = $this->umail->getMail($mailId);
560            if (isset($mailData['folder_id']) && is_numeric($mailData['folder_id']) && (int) $mailData['folder_id'] > 0) {
561                $redirectFolderId = $mailData['folder_id'];
562                break;
563            }
564        }
565
566        if ($this->umail->moveMailsToFolder($mailIds, $newFolderId)) {
567            ilUtil::sendSuccess($this->lng->txt('mail_moved'), true);
568            $this->ctrl->setParameter($this, 'mobj_id', $redirectFolderId);
569            $this->ctrl->redirect($this, 'showFolder');
570        } else {
571            ilUtil::sendFailure($this->lng->txt('mail_move_error'));
572            $this->showMail();
573        }
574    }
575
576    /**
577     * Called if a single message or multiple messages should be be moved in the list view
578     */
579    protected function moveMails() : void
580    {
581        $mailIds = $this->getMailIdsFromRequest();
582        if (0 === count($mailIds)) {
583            $this->showFolder();
584            ilUtil::sendInfo($this->lng->txt('mail_select_one'));
585            return;
586        }
587
588        $folderId = $this->parseFolderIdFromCommand($this->ctrl->getCmd());
589        if ($this->umail->moveMailsToFolder($mailIds, $folderId)) {
590            ilUtil::sendSuccess($this->lng->txt('mail_moved'), true);
591            $this->ctrl->setParameter($this, 'mobj_id', $this->currentFolderId);
592            $this->ctrl->redirect($this, 'showFolder');
593        } else {
594            ilUtil::sendFailure($this->lng->txt('mail_move_error'));
595            $this->showFolder();
596        }
597    }
598
599    /**
600     * Called if a single message or multiple messages should be deleted
601     */
602    protected function deleteMails() : void
603    {
604        $trashFolderId = (int) $this->mbox->getTrashFolder();
605        $mailIds = $this->getMailIdsFromRequest();
606
607        if ($trashFolderId == $this->currentFolderId) {
608            if (0 === count($mailIds)) {
609                ilUtil::sendInfo($this->lng->txt('mail_select_one'));
610                $this->errorDelete = true;
611            }
612        } else {
613            if (0 === count($mailIds)) {
614                ilUtil::sendInfo($this->lng->txt('mail_select_one'));
615            } elseif ($this->umail->moveMailsToFolder($mailIds, $trashFolderId)) {
616                ilUtil::sendSuccess($this->lng->txt('mail_moved_to_trash'), true);
617                $this->ctrl->setParameter($this, 'mobj_id', $this->currentFolderId);
618                $this->ctrl->redirect($this, 'showFolder');
619            } else {
620                ilUtil::sendFailure($this->lng->txt('mail_move_error'));
621            }
622        }
623
624        $this->showFolder();
625    }
626
627    /**
628     * Called if the final deletion of selected messages was confirmed by the acting user
629     */
630    protected function confirmDeleteMails() : void
631    {
632        $mailIds = $this->getMailIdsFromRequest();
633        if (0 === count($mailIds)) {
634            $this->showFolder();
635            ilUtil::sendInfo($this->lng->txt('mail_select_one'));
636            return;
637        }
638
639        if ((int) $this->mbox->getTrashFolder() === (int) $this->currentFolderId) {
640            $this->umail->deleteMails($mailIds);
641            ilUtil::sendSuccess($this->lng->txt('mail_deleted'), true);
642            $this->ctrl->setParameter($this, 'mobj_id', $this->currentFolderId);
643            $this->ctrl->redirect($this, 'showFolder');
644        }
645
646        $this->showFolder();
647    }
648
649    /**
650     * Detail view of a mail
651     */
652    protected function showMail() : void
653    {
654        if ((int) ilSession::get('mail_id') > 0) {
655            $mailId = (int) ilSession::get('mail_id');
656            ilSession::set('mail_id', null);
657        } else {
658            $mailId = (int) ($this->httpRequest->getQueryParams()['mail_id'] ?? 0);
659        }
660
661        $mailData = $this->umail->getMail($mailId);
662        $this->umail->markRead([$mailId]);
663
664        $this->tpl->setTitle($this->lng->txt('mail_mails_of'));
665
666        $this->tabs->clearTargets();
667        $this->ctrl->setParameter($this, 'mobj_id', $mailData['folder_id']);
668        $this->tabs->setBackTarget($this->lng->txt('back_to_folder'), $this->ctrl->getFormAction($this, 'showFolder'));
669        $this->ctrl->clearParameters($this);
670
671        $this->ctrl->setParameter($this, 'mail_id', $mailId);
672        $this->ctrl->setParameter($this, 'mobj_id', $mailData['folder_id']);
673        $this->toolbar->setFormAction($this->ctrl->getFormAction($this, 'showMail'));
674        $this->ctrl->clearParameters($this);
675
676        $form = new ilPropertyFormGUI();
677        $form->setPreventDoubleSubmission(false);
678        $form->setTableWidth('100%');
679        $this->ctrl->setParameter($this, 'mobj_id', $mailData['folder_id']);
680        $this->ctrl->setParameter($this, 'mail_id', $mailId);
681        $form->setFormAction($this->ctrl->getFormAction($this, 'showMail'));
682        $this->ctrl->clearParameters($this);
683        $form->setTitle($this->lng->txt('mail_mails_of'));
684
685        /**
686         * @var $sender ilObjUser
687         */
688        $sender = ilObjectFactory::getInstanceByObjId($mailData['sender_id'], false);
689        $replyBtn = null;
690        if ($sender && $sender->getId() && !$sender->isAnonymous()) {
691            $replyBtn = ilLinkButton::getInstance();
692            $replyBtn->setCaption('reply');
693            $this->ctrl->setParameterByClass('ilmailformgui', 'mobj_id', $mailData['folder_id']);
694            $this->ctrl->setParameterByClass('ilmailformgui', 'mail_id', $mailId);
695            $this->ctrl->setParameterByClass('ilmailformgui', 'type', 'reply');
696            $replyBtn->setUrl($this->ctrl->getLinkTargetByClass('ilmailformgui'));
697            $this->ctrl->clearParametersByClass('ilmailformgui');
698            $replyBtn->setAccessKey(ilAccessKey::REPLY);
699            $replyBtn->setPrimary(true);
700            $this->toolbar->addStickyItem($replyBtn);
701        }
702
703        $fwdBtn = ilLinkButton::getInstance();
704        $fwdBtn->setCaption('forward');
705        $this->ctrl->setParameterByClass('ilmailformgui', 'mobj_id', $mailData['folder_id']);
706        $this->ctrl->setParameterByClass('ilmailformgui', 'mail_id', $mailId);
707        $this->ctrl->setParameterByClass('ilmailformgui', 'type', 'forward');
708        $fwdBtn->setUrl($this->ctrl->getLinkTargetByClass('ilmailformgui'));
709        $this->ctrl->clearParametersByClass('ilmailformgui');
710        $fwdBtn->setAccessKey(ilAccessKey::FORWARD_MAIL);
711        if (!$replyBtn) {
712            $fwdBtn->setPrimary(true);
713            $this->toolbar->addStickyItem($fwdBtn);
714        } else {
715            $this->toolbar->addButtonInstance($fwdBtn);
716        }
717
718        $printBtn = ilLinkButton::getInstance();
719        $printBtn->setCaption('print');
720        $this->ctrl->setParameter($this, 'mail_id', $mailId);
721        $this->ctrl->setParameter($this, 'mobj_id', $mailData['folder_id']);
722        $printBtn->setUrl($this->ctrl->getLinkTarget($this, 'printMail'));
723        $this->ctrl->clearParameters($this);
724        $printBtn->setTarget('_blank');
725        $this->toolbar->addButtonInstance($printBtn);
726
727        $deleteBtn = ilSubmitButton::getInstance();
728        $deleteBtn->setCaption('delete');
729        $deleteBtn->setCommand('deleteMails');
730        $deleteBtn->setAccessKey(ilAccessKey::DELETE);
731        $this->toolbar->addButtonInstance($deleteBtn);
732
733        if ($sender && $sender->getId() && !$sender->isAnonymous()) {
734            $linked_fullname = $sender->getPublicName();
735            $picture = ilUtil::img(
736                $sender->getPersonalPicturePath('xsmall'),
737                $sender->getPublicName(),
738                '',
739                '',
740                0,
741                '',
742                'ilMailAvatar'
743            );
744
745            if (in_array(ilObjUser::_lookupPref($sender->getId(), 'public_profile'), ['y', 'g'])) {
746                $this->ctrl->setParameter($this, 'mail_id', $mailId);
747                $this->ctrl->setParameter($this, 'mobj_id', $mailData['folder_id']);
748                $this->ctrl->setParameter($this, 'user', $sender->getId());
749                $linked_fullname = '<br /><a href="' . $this->ctrl->getLinkTarget(
750                    $this,
751                    'showUser'
752                ) . '" title="' . $linked_fullname . '">' . $linked_fullname . '</a>';
753                $this->ctrl->clearParameters($this);
754            }
755
756            $from = new ilCustomInputGUI($this->lng->txt('from') . ':');
757            $from->setHtml($picture . ' ' . $linked_fullname);
758            $form->addItem($from);
759        } elseif (!$sender || !$sender->getId()) {
760            $from = new ilCustomInputGUI($this->lng->txt('from') . ':');
761            $from->setHtml($mailData['import_name'] . ' (' . $this->lng->txt('user_deleted') . ')');
762            $form->addItem($from);
763        } else {
764            $from = new ilCustomInputGUI($this->lng->txt('from') . ':');
765            $from->setHtml(
766                ilUtil::img(
767                    ilUtil::getImagePath('HeaderIconAvatar.svg'),
768                    ilMail::_getIliasMailerName(),
769                    '',
770                    '',
771                    0,
772                    '',
773                    'ilMailAvatar'
774                ) .
775                '<br />' . ilMail::_getIliasMailerName()
776            );
777            $form->addItem($from);
778        }
779
780        $to = new ilCustomInputGUI($this->lng->txt('mail_to') . ':');
781        $to->setHtml(ilUtil::htmlencodePlainString($this->umail->formatNamesForOutput((string) $mailData['rcp_to']), false));
782        $form->addItem($to);
783
784        if ($mailData['rcp_cc']) {
785            $cc = new ilCustomInputGUI($this->lng->txt('cc') . ':');
786            $cc->setHtml(ilUtil::htmlencodePlainString($this->umail->formatNamesForOutput((string) $mailData['rcp_cc']), false));
787            $form->addItem($cc);
788        }
789
790        if ($mailData['rcp_bcc']) {
791            $bcc = new ilCustomInputGUI($this->lng->txt('bc') . ':');
792            $bcc->setHtml(ilUtil::htmlencodePlainString(
793                $this->umail->formatNamesForOutput((string) $mailData['rcp_bcc']),
794                false
795            ));
796            $form->addItem($bcc);
797        }
798
799        $subject = new ilCustomInputGUI($this->lng->txt('subject') . ':');
800        $subject->setHtml(ilUtil::htmlencodePlainString($mailData['m_subject'], true));
801        $form->addItem($subject);
802
803        $date = new ilCustomInputGUI($this->lng->txt('date') . ':');
804        $date->setHtml(ilDatePresentation::formatDate(new ilDateTime($mailData['send_time'], IL_CAL_DATETIME)));
805        $form->addItem($date);
806
807        $message = new ilCustomInputGUI($this->lng->txt('message') . ':');
808        $message->setHtml(ilUtil::htmlencodePlainString($mailData['m_message'], true));
809        $form->addItem($message);
810
811        if ($mailData['attachments']) {
812            $att = new ilCustomInputGUI($this->lng->txt('attachments') . ':');
813
814            $radiog = new ilRadioGroupInputGUI('', 'filename');
815            foreach ($mailData['attachments'] as $file) {
816                $radiog->addOption(new ilRadioOption($file, md5($file)));
817            }
818
819            $att->setHtml($radiog->render());
820            $form->addCommandButton('deliverFile', $this->lng->txt('download'));
821            $form->addItem($att);
822        }
823
824        $isTrashFolder = false;
825        if ($this->mbox->getTrashFolder() == $mailData['folder_id']) {
826            $isTrashFolder = true;
827        }
828
829        $currentFolderData = $this->mbox->getFolderData($mailData['folder_id']);
830        $actions = $this->mbox->getActions((int) $mailData['folder_id']);
831
832        $selectOptions = [];
833        foreach ($actions as $key => $action) {
834            if ($key === 'moveMails') {
835                $folders = $this->mbox->getSubFolders();
836                foreach ($folders as $folder) {
837                    if (
838                        ($folder['type'] !== 'trash' || !$isTrashFolder) &&
839                        $folder['obj_id'] != $mailData['folder_id']
840                    ) {
841                        $optionText = $action . ' ' . $folder['title'];
842                        if ($folder['type'] !== 'user_folder') {
843                            $optionText = $action . ' ' . $this->lng->txt('mail_' . $folder['title']) . ($folder['type'] == 'trash' ? ' (' . $this->lng->txt('delete') . ')' : '');
844                        }
845
846                        $selectOptions[$folder['obj_id']] = $optionText;
847                    }
848                }
849            }
850        }
851
852        $folderLabel = $this->lng->txt('mail_' . $currentFolderData['title']);
853        if ($currentFolderData['type'] === 'user_folder') {
854            $folderLabel = $currentFolderData['title'];
855        }
856
857        $this->toolbar->addSeparator();
858        $this->toolbar->addText(sprintf($this->lng->txt('current_folder'), $folderLabel));
859
860        if (is_array($selectOptions) && count($selectOptions) > 0) {
861            $actions = new ilSelectInputGUI('', 'folder_id');
862            $actions->setOptions($selectOptions);
863            $this->toolbar->addInputItem($actions);
864
865            $moveBtn = ilSubmitButton::getInstance();
866            $moveBtn->setCaption('execute');
867            $moveBtn->setCommand('moveSingleMail');
868            $this->toolbar->addButtonInstance($moveBtn);
869        }
870
871        $prevMail = $this->umail->getPreviousMail($mailId);
872        $nextMail = $this->umail->getNextMail($mailId);
873        if (is_array($prevMail) || is_array($nextMail)) {
874            $this->toolbar->addSeparator();
875
876            if ($prevMail['mail_id']) {
877                $prevBtn = ilLinkButton::getInstance();
878                $prevBtn->setCaption('previous');
879                $this->ctrl->setParameter($this, 'mail_id', $prevMail['mail_id']);
880                $this->ctrl->setParameter($this, 'mobj_id', $this->currentFolderId);
881                $prevBtn->setUrl($this->ctrl->getLinkTarget($this, 'showMail'));
882                $this->ctrl->clearParameters($this);
883                $this->toolbar->addButtonInstance($prevBtn);
884            }
885
886            if ($nextMail['mail_id']) {
887                $nextBtn = ilLinkButton::getInstance();
888                $nextBtn->setCaption('next');
889                $this->ctrl->setParameter($this, 'mail_id', $nextMail['mail_id']);
890                $this->ctrl->setParameter($this, 'mobj_id', $this->currentFolderId);
891                $nextBtn->setUrl($this->ctrl->getLinkTarget($this, 'showMail'));
892                $this->ctrl->clearParameters($this);
893                $this->toolbar->addButtonInstance($nextBtn);
894            }
895        }
896
897        $this->tpl->setContent($form->getHTML());
898        $this->tpl->printToStdout();
899    }
900
901    /**
902     * Print mail
903     */
904    protected function printMail() : void
905    {
906        $tplprint = new ilTemplate('tpl.mail_print.html', true, true, 'Services/Mail');
907
908        $mailData = $this->umail->getMail((int) ($this->httpRequest->getQueryParams()['mail_id'] ?? 0));
909
910        /**
911         * @var $sender ilObjUser
912         */
913        $sender = ilObjectFactory::getInstanceByObjId($mailData['sender_id'], false);
914
915        $tplprint->setVariable('TXT_FROM', $this->lng->txt('from'));
916        if ($sender && $sender->getId() && !$sender->isAnonymous()) {
917            $tplprint->setVariable('FROM', $sender->getPublicName());
918        } elseif (!$sender || !$sender->getId()) {
919            $tplprint->setVariable('FROM', $mailData['import_name'] . ' (' . $this->lng->txt('user_deleted') . ')');
920        } else {
921            $tplprint->setVariable('FROM', ilMail::_getIliasMailerName());
922        }
923
924        $tplprint->setVariable('TXT_TO', $this->lng->txt('mail_to'));
925        $tplprint->setVariable('TO', $mailData['rcp_to']);
926
927        if ($mailData['rcp_cc']) {
928            $tplprint->setCurrentBlock('cc');
929            $tplprint->setVariable('TXT_CC', $this->lng->txt('cc'));
930            $tplprint->setVariable('CC', $mailData['rcp_cc']);
931            $tplprint->parseCurrentBlock();
932        }
933
934        if ($mailData['rcp_bcc']) {
935            $tplprint->setCurrentBlock('bcc');
936            $tplprint->setVariable('TXT_BCC', $this->lng->txt('bc'));
937            $tplprint->setVariable('BCC', $mailData['rcp_bcc']);
938            $tplprint->parseCurrentBlock();
939        }
940
941        $tplprint->setVariable('TXT_SUBJECT', $this->lng->txt('subject'));
942        $tplprint->setVariable('SUBJECT', htmlspecialchars($mailData['m_subject']));
943
944        $tplprint->setVariable('TXT_DATE', $this->lng->txt('date'));
945        $tplprint->setVariable(
946            'DATE',
947            ilDatePresentation::formatDate(new ilDateTime($mailData['send_time'], IL_CAL_DATETIME))
948        );
949
950        $tplprint->setVariable('TXT_MESSAGE', $this->lng->txt('message'));
951        $tplprint->setVariable('MAIL_MESSAGE', nl2br(htmlspecialchars($mailData['m_message'])));
952
953        $tplprint->show();
954    }
955
956    protected function deliverFile() : void
957    {
958        $mailId = $this->httpRequest->getQueryParams()['mail_id'] ?? 0;
959        if ((int) ilSession::get('mail_id') > 0) {
960            $mailId = ilSession::get('mail_id');
961            ilSession::set('mail_id', null);
962        }
963
964        $filename = $this->httpRequest->getParsedBody()['filename'] ?? '';
965        if (is_string(ilSession::get('filename')) && strlen(ilSession::get('filename')) > 0) {
966            $filename = ilSession::get('filename');
967            ilSession::set('filename', null);
968        }
969
970        try {
971            if ($mailId > 0 && $filename !== '') {
972                while (strpos($filename, '..') !== false) {
973                    $filename = str_replace('..', '', $filename);
974                }
975
976                $mailFileData = new ilFileDataMail($this->user->getId());
977                try {
978                    $file = $mailFileData->getAttachmentPathAndFilenameByMd5Hash($filename, (int) $mailId);
979                    ilUtil::deliverFile($file['path'], $file['filename']);
980                } catch (OutOfBoundsException $e) {
981                    throw new ilException('mail_error_reading_attachment');
982                }
983            } else {
984                ilUtil::sendInfo($this->lng->txt('mail_select_attachment'));
985                $this->showMail();
986            }
987        } catch (Exception $e) {
988            ilUtil::sendFailure($this->lng->txt($e->getMessage()), true);
989            $this->ctrl->setParameter($this, 'mobj_id', $this->currentFolderId);
990            $this->ctrl->redirect($this);
991        }
992    }
993
994    protected function deliverAttachments() : void
995    {
996        try {
997            $mailId = $this->httpRequest->getQueryParams()['mail_id'] ?? 0;
998
999            $mailData = $this->umail->getMail((int) $mailId);
1000            if (null === $mailData || 0 === count((array) $mailData['attachments'])) {
1001                throw new ilException('mail_error_reading_attachment');
1002            }
1003
1004            $type = $this->httpRequest->getQueryParams()['type'] ?? '';
1005
1006            $mailFileData = new ilFileDataMail($this->user->getId());
1007            if (count($mailData['attachments']) === 1) {
1008                $attachment = current($mailData['attachments']);
1009
1010                try {
1011                    if ('draft' === $type) {
1012                        if (!$mailFileData->checkFilesExist([$attachment])) {
1013                            throw new OutOfBoundsException('');
1014                        }
1015                        $pathToFile = $mailFileData->getAbsoluteAttachmentPoolPathByFilename($attachment);
1016                        $fileName = $attachment;
1017                    } else {
1018                        $file = $mailFileData->getAttachmentPathAndFilenameByMd5Hash(
1019                            md5($attachment),
1020                            (int) $mailId
1021                        );
1022                        $pathToFile = $file['path'];
1023                        $fileName = $file['filename'];
1024                    }
1025                    ilUtil::deliverFile($pathToFile, $fileName);
1026                } catch (OutOfBoundsException $e) {
1027                    throw new ilException('mail_error_reading_attachment');
1028                }
1029            } else {
1030                $mailFileData->deliverAttachmentsAsZip(
1031                    $mailData['m_subject'],
1032                    (int) $mailId,
1033                    $mailData['attachments'],
1034                    'draft' === $type
1035                );
1036            }
1037        } catch (Exception $e) {
1038            ilUtil::sendFailure($this->lng->txt($e->getMessage()), true);
1039            $this->ctrl->setParameter($this, 'mobj_id', $this->currentFolderId);
1040            $this->ctrl->redirect($this);
1041        }
1042    }
1043
1044    /**
1045     * @return ilMailFolderTableGUI
1046     */
1047    protected function getMailFolderTable() : ilMailFolderTableGUI
1048    {
1049        $sentFolderId = $this->mbox->getSentFolder();
1050        $draftsFolderId = $this->mbox->getDraftsFolder();
1051
1052        $isTrashFolder = $this->currentFolderId == $this->mbox->getTrashFolder();
1053        $isSentFolder = $this->currentFolderId == $sentFolderId;
1054        $isDraftFolder = $this->currentFolderId == $draftsFolderId;
1055
1056        $table = new ilMailFolderTableGUI($this, $this->currentFolderId, 'showFolder');
1057        $table->isSentFolder($isSentFolder)
1058            ->isDraftFolder($isDraftFolder)
1059            ->isTrashFolder($isTrashFolder)
1060            ->initFilter();
1061
1062        return $table;
1063    }
1064
1065    /**
1066     *
1067     */
1068    protected function applyFilter() : void
1069    {
1070        $table = $this->getMailFolderTable();
1071        $table->resetOffset();
1072        $table->writeFilterToSession();
1073
1074        $this->showFolder();
1075    }
1076
1077    /**
1078     *
1079     */
1080    protected function resetFilter() : void
1081    {
1082        $table = $this->getMailFolderTable();
1083        $table->resetOffset();
1084        $table->resetFilter();
1085
1086        $this->showFolder();
1087    }
1088}
1089