ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
class.ilMailAttachmentGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
29 
31 {
32  private readonly ilGlobalTemplateInterface $tpl;
33  private readonly ilLanguage $lng;
34  private readonly ilObjUser $user;
35  private readonly ilFormatMail $umail;
36  private readonly ilFileDataMail $mfile;
37  private readonly Refinery $refinery;
38  private readonly \ILIAS\UI\Factory $ui_factory;
39  private readonly \ILIAS\UI\Renderer $ui_renderer;
40  private readonly ilTabsGUI $tabs;
41  private AttachmentManagement $mode = AttachmentManagement::MANAGE;
42 
43  public function __construct()
44  {
45  global $DIC;
46 
48  $this->tpl = $DIC->ui()->mainTemplate();
49  $this->lng = $DIC->language();
50  $this->user = $DIC->user();
51  $this->tabs = $DIC->tabs();
52  $this->refinery = $DIC->refinery();
53  $this->ui_factory = $DIC->ui()->factory();
54  $this->ui_renderer = $DIC->ui()->renderer();
55 
56  $this->ctrl->saveParameter($this, 'mobj_id');
57 
58  $this->umail = new ilFormatMail($DIC->user()->getId());
59  $this->mfile = new ilFileDataMail($DIC->user()->getId());
60  }
61 
62  public function getUnsafeGetCommands(): array
63  {
64  return [
65  'handleTableActions',
66  ];
67  }
68 
69  public function getSafePostCommands(): array
70  {
71  return [];
72  }
73 
74  public function manage(): self
75  {
76  $this->mode = AttachmentManagement::MANAGE;
77  return $this;
78  }
79 
80  public function consume(): self
81  {
82  $this->mode = AttachmentManagement::CONSUME;
83  return $this;
84  }
85 
86  public function executeCommand(): void
87  {
88  if (!($cmd = $this->ctrl->getCmd())) {
89  $cmd = 'showAttachments';
90  }
91 
92  match ($cmd) {
93  AbstractCtrlAwareUploadHandler::CMD_UPLOAD,
94  AbstractCtrlAwareUploadHandler::CMD_INFO,
95  AbstractCtrlAwareUploadHandler::CMD_REMOVE => parent::executeCommand(),
96  default => $this->$cmd()
97  };
98  }
99 
100  public function saveAttachments(): void
101  {
102  $files = [];
103 
104  // Important: Do not check for uploaded files here,
105  // otherwise it is no more possible to remove files (please ignore bug reports like 10137)
106 
107  $size_of_affected_files = 0;
108  $files_of_request = $this->http->wrapper()->query()->retrieve(
109  'mail_attachments_filename',
110  $this->refinery->byTrying([
111  $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->string()),
112  $this->refinery->always([])
113  ])
114  );
115 
116  if ($files_of_request !== [] && $files_of_request[0] === 'ALL_OBJECTS') {
117  $files_of_request = array_map(static fn(array $file): string => $file['name'], $this->mfile->getUserFilesData());
118  }
119 
120  foreach ($files_of_request as $file) {
121  if (is_file($this->mfile->getMailPath() . '/' . basename($this->user->getId() . '_' . urldecode((string) $file)))) {
122  $files[] = urldecode((string) $file);
123  $size_of_affected_files += filesize(
124  $this->mfile->getMailPath() . '/' .
125  basename($this->user->getId() . '_' . urldecode((string) $file))
126  );
127  }
128  }
129 
130  if ($files !== [] &&
131  $this->mfile->getAttachmentsTotalSizeLimit() !== null &&
132  $size_of_affected_files > $this->mfile->getAttachmentsTotalSizeLimit()) {
133  $this->tpl->setOnScreenMessage(
134  'failure',
135  $this->lng->txt('mail_max_size_attachments_total_error') . ' ' .
136  ilUtil::formatSize((int) $this->mfile->getAttachmentsTotalSizeLimit())
137  );
138  $this->showAttachments();
139  return;
140  }
141 
142  $this->umail->saveAttachments($files);
143 
144  $this->ctrl->returnToParent($this);
145  }
146 
147  public function cancelSaveAttachments(): void
148  {
149  $this->ctrl->setParameter($this, 'type', ilMailFormGUI::MAIL_FORM_TYPE_ATTACH);
150  $this->ctrl->returnToParent($this);
151  }
152 
153  public function deleteAttachments(): void
154  {
155  $files = $this->http->wrapper()->query()->retrieve(
156  'mail_attachments_filename',
157  $this->refinery->byTrying([
158  $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->string()),
159  $this->refinery->always([])
160  ])
161  );
162 
163  if ($files !== [] && $files[0] === 'ALL_OBJECTS') {
164  $files = array_map(static fn(array $file): string => $file['name'], $this->mfile->getUserFilesData());
165  }
166 
167  if ($files === []) {
168  $this->tpl->setOnScreenMessage('info', $this->lng->txt('select_one'), true);
169  $this->ctrl->redirect($this);
170  }
171 
172  $this->tpl->setTitle($this->lng->txt('mail'));
173 
174  $confirmation = new ilConfirmationGUI();
175  $confirmation->setFormAction($this->ctrl->getFormAction($this, 'confirmDeleteAttachments'));
176  $confirmation->setConfirm($this->lng->txt('confirm'), 'confirmDeleteAttachments');
177  $confirmation->setCancel($this->lng->txt('cancel'), 'showAttachments');
178  $confirmation->setHeaderText($this->lng->txt('mail_sure_delete_file'));
179 
180  foreach ($files as $filename) {
181  $confirmation->addItem(
182  'filename[]',
183  ilUtil::stripSlashes($filename),
184  ilUtil::stripSlashes(urldecode((string) $filename))
185  );
186  }
187 
188  $this->tpl->setContent($confirmation->getHTML());
189  $this->tpl->printToStdout();
190  }
191 
192  public function confirmDeleteAttachments(): void
193  {
194  $files = $this->http->wrapper()->post()->retrieve(
195  'filename',
196  $this->refinery->byTrying([
197  $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->string()),
198  $this->refinery->always([])
199  ])
200  );
201 
202  if ($files === []) {
203  $this->tpl->setOnScreenMessage('info', $this->lng->txt('mail_select_one_mail'));
204  $this->showAttachments();
205  return;
206  }
207 
208  $decoded_files = [];
209  foreach ($files as $value) {
210  $decoded_files[] = urldecode((string) $value);
211  }
212 
213  $error = $this->mfile->unlinkFiles($decoded_files);
214  if ($error !== '') {
215  $this->tpl->setOnScreenMessage('failure', $this->lng->txt('mail_error_delete_file') . ' ' . $error, true);
216  } else {
217  $mail_data = $this->umail->retrieveFromStage();
218  if (is_array($mail_data['attachments'])) {
219  $tmp = [];
220  foreach ($mail_data['attachments'] as $attachment) {
221  if (!in_array($attachment, $decoded_files, true)) {
222  $tmp[] = $attachment;
223  }
224  }
225  $this->umail->saveAttachments($tmp);
226  }
227 
228  $this->tpl->setOnScreenMessage('success', $this->lng->txt('mail_files_deleted'), true);
229  }
230 
231  $this->ctrl->redirect($this);
232  }
233 
234  public function showAttachments(): void
235  {
236  $this->tpl->setTitle($this->lng->txt('mail'));
237 
238  if ($this->mode === AttachmentManagement::CONSUME) {
239  $this->tabs->clearTargets();
240  $this->tabs->setBackTarget(
241  $this->lng->txt('mail_manage_attachments_back_to_compose'),
242  $this->ctrl->getLinkTarget($this, 'cancelSaveAttachments')
243  );
244  }
245 
246  $components = [];
247  if ($this->mode === AttachmentManagement::MANAGE) {
248  $dropzone = $this->ui_factory
249  ->dropzone()
250  ->file()
251  ->standard(
252  $this->lng->txt('mail_manage_attachments'),
253  $this->lng->txt('mail_manage_attachments_drop_files_msg'),
254  '#',
255  $this->ui_factory->input()->field()->file(
256  $this,
257  $this->lng->txt('file')
258  )->withMaxFiles(42) // The answer to life, universe and the rest
259  )
260  ->withBulky(true)
261  ->withUploadButton(
262  $this->ui_factory->button()->shy(
263  $this->lng->txt('upload'),
264  '#'
265  )
266  );
267  $components[] = $dropzone;
268  }
269 
270  $mail_data = $this->umail->retrieveFromStage();
271  $files = $this->mfile->getUserFilesData();
272  $records = [];
273  $checked_items = [];
274  foreach ($files as $file) {
275  if (is_array($mail_data['attachments']) && in_array($file['name'], $mail_data['attachments'], true)) {
276  $checked_items[] = urlencode($file['name']);
277  }
278 
279  $records[] = [
280  'filename' => $file['name'],
281  'filesize' => (int) $file['size'],
282  'filecreatedate' => (int) $file['ctime'],
283  ];
284  }
285 
286  $table = new MailAttachmentTableGUI(
287  $this,
288  $this->user,
289  $records,
290  $this->ui_factory,
291  $this->ui_renderer,
292  $this->lng,
293  $this->ctrl,
294  $this->http->request(),
295  new ILIAS\Data\Factory(),
296  'handleTableActions',
298  );
299  $components[] = $table->get();
300 
301  $this->tpl->setContent($this->ui_renderer->render($components));
302 
303  if ($this->mode === AttachmentManagement::CONSUME) {
304  // The table above has to be rendered first, because it deselects all checkboxes
305  $this->tpl->addOnLoadCode('
306  const checked_items = ' . json_encode($checked_items, JSON_THROW_ON_ERROR) . ';
307  for (const item of checked_items) {
308  const checkbox = document.querySelector("input[type=\'checkbox\'][value=\'" + item + "\']");
309  if (checkbox) {
310  checkbox.checked = true;
311  }
312  }
313  ');
314  }
315 
316  $this->tpl->printToStdout();
317  }
318 
319  private function handleTableActions(): void
320  {
321  $query = $this->http->wrapper()->query();
322  if (!$query->has('mail_attachments_table_action')) {
323  return;
324  }
325 
326  $action = $query->retrieve('mail_attachments_table_action', $this->refinery->to()->string());
327  match ($action) {
328  'saveAttachments' => $this->saveAttachments(),
329  'deleteAttachments' => $this->deleteAttachments(),
330  default => $this->ctrl->redirect($this),
331  };
332  }
333 
334  protected function getUploadResult(): HandlerResult
335  {
336  $this->upload->process();
337  $array = $this->upload->getResults();
338  $result = end($array);
339 
340  if ($result instanceof UploadResult && $result->isOK()) {
341  $identifier = $this->mfile->storeUploadedFile($result);
342  $status = HandlerResult::STATUS_OK;
343  $message = $this->lng->txt('saved_successfully');
344  $this->tpl->setOnScreenMessage('success', $this->lng->txt('saved_successfully'), true);
345  } else {
346  $status = HandlerResult::STATUS_FAILED;
347  $identifier = '';
348  $message = $result->getStatus()->getMessage();
349  }
350 
351  return new BasicHandlerResult($this->getFileIdentifierParameterName(), $status, $identifier, $message);
352  }
353 
354  protected function getRemoveResult(string $identifier): HandlerResult
355  {
356  throw new DomainException('Not necessary for this handler');
357  }
358 
359  public function getInfoResult(string $identifier): ?FileInfoResult
360  {
361  throw new DomainException('Not necessary for this handler');
362  }
363 
364  public function getInfoForExistingFiles(array $file_ids): array
365  {
366  throw new DomainException('Not necessary for this handler');
367  }
368 
369  public function getFileIdentifierParameterName(): string
370  {
371  return 'userfile';
372  }
373 }
getUnsafeGetCommands()
This method must return a list of unsafe GET commands.
AttachmentManagement $mode
readonly ilFileDataMail $mfile
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getSafePostCommands()
This method must return a list of safe POST commands.
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
readonly ILIAS UI Renderer $ui_renderer
$components
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
readonly ilFormatMail $umail
executeCommand()
Since this is a ilCtrl aware UploadHandler executeCommand MUST be implemented.
getInfoResult(string $identifier)
static http()
Fetches the global http state from ILIAS.
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.
global $DIC
Definition: shib_login.php:26
$filename
Definition: buildRTE.php:78
getInfoForExistingFiles(array $file_ids)
final const string MAIL_FORM_TYPE_ATTACH
__construct(Container $dic, ilPlugin $plugin)
readonly ILIAS UI Factory $ui_factory
$message
Definition: xapiexit.php:31
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getRemoveResult(string $identifier)
readonly ilGlobalTemplateInterface $tpl