ILIAS  release_10 Revision v10.1-43-ga1241a92c2f
class.ilContainerResourceGUI.php
Go to the documentation of this file.
1 <?php
2 
36 
40 final class ilContainerResourceGUI implements UploadHandler
41 {
42  use URLSerializer;
43 
44  public const P_PATH = 'path';
45  public const P_PATHS = 'paths';
46 
47  public const CMD_INDEX = 'index';
48  public const CMD_INFO = 'info';
49  public const CMD_UPLOAD = 'upload';
50  public const CMD_POST_UPLOAD = 'postUpload';
51  public const CMD_REMOVE = 'remove';
52  public const CMD_DOWNLOAD = 'download';
53  public const CMD_DOWNLOAD_ZIP = 'downloadZIP';
54 
55  public const CMD_UNZIP = 'unzip';
56  public const CMD_RENDER_CONFIRM_REMOVE = 'renderConfirmRemove';
57  public const ADD_DIRECTORY = 'addDirectory';
58 
63  private \ILIAS\UI\Renderer $ui_renderer;
64  private \ILIAS\Refinery\Factory $refinery;
65  private \ILIAS\HTTP\Services $http;
67  private \ILIAS\ResourceStorage\Services $irss;
70  private \ILIAS\UI\Factory $ui_factory;
71  private \ILIAS\FileUpload\FileUpload $upload;
72  private \ILIAS\Filesystem\Util\Archive\Archives $archive;
73  private PreviewDefinition $preview_definition;
74  private ActionBuilder\ActionProvider $action_provider;
76 
77  final public function __construct(
78  private Configuration $view_configuration
79  ) {
80  global $DIC;
81  $this->ctrl = $DIC->ctrl();
82  $this->main_tpl = $DIC->ui()->mainTemplate();
83  $this->ui_renderer = $DIC->ui()->renderer();
84  $this->ui_factory = $DIC->ui()->factory();
85  $this->http = $DIC->http();
86  $this->refinery = $DIC->refinery();
87  $this->language = $DIC->language();
88  $this->language->loadLanguageModule('irss');
89  $this->irss = $DIC->resourceStorage();
90  $this->upload = $DIC->upload();
91 
92  $this->view_request = new Request(
93  $DIC->ctrl(),
94  $DIC->http()->wrapper()->query(),
95  $this->view_configuration
96  );
97 
98  // to store paramaters needed in GUI
99  $this->view_request->init($this);
100 
101  $this->action_provider = new CombinedActionProvider(
102  $this->standard_action_provider = new StandardActionProvider($this->view_request),
103  $this->view_configuration->getActionProvider()
104  );
105 
106  $data_provider = new TableDataProvider($this->view_request);
107 
108  $this->action_builder = new ActionBuilder(
109  $this->view_request,
110  $this->ctrl,
111  $DIC->ui()->factory(),
112  $DIC->language(),
113  $this->irss,
115  );
116 
117  $view_control_builder = new ViewControlBuilder(
118  $this->view_request,
119  $data_provider,
120  $this->ctrl,
121  $DIC->ui()->factory(),
122  $DIC->language()
123  );
124 
125  $upload_builder = new UploadBuilder(
126  $this->view_request,
127  $this->ctrl,
128  $DIC->ui()->factory(),
129  $DIC->language(),
130  $this
131  );
132 
133  $this->view_factory = new ViewFactory(
134  $data_provider,
135  $this->action_builder,
136  $view_control_builder,
137  $upload_builder
138  );
139  }
140 
141  // CMD CLASS
142 
143  protected function abortWithPermissionDenied(): void
144  {
145  $this->main_tpl->setOnScreenMessage('failure', $this->language->txt('msg_no_perm_read'), true);
146  $this->ctrl->redirect($this, self::CMD_INDEX);
147  }
148 
149  public function executeCommand(): void
150  {
151  if ($this->view_request->handleViewTitle()) {
152  $title = $this->view_request->getTitle();
153  if ($title !== null) {
154  $this->main_tpl->setTitle($title);
155  }
156  $description = $this->view_request->getDescription();
157  if ($description !== null) {
158  $this->main_tpl->setDescription($description);
159  }
160  }
161 
162  switch ($this->ctrl->getCmd(self::CMD_INDEX)) {
163  case self::CMD_INDEX:
164  $this->index();
165  break;
166  case self::CMD_UPLOAD:
167  $this->upload();
168  break;
169  case self::CMD_POST_UPLOAD:
170  $this->postUpload();
171  break;
172  case self::CMD_REMOVE:
173  $this->remove();
174  break;
175  case self::CMD_DOWNLOAD:
176  $this->download();
177  break;
178  case self::CMD_UNZIP:
179  $this->unzip();
180  break;
181  case self::CMD_RENDER_CONFIRM_REMOVE:
182  $this->renderConfirmRemove();
183  break;
184  case self::ADD_DIRECTORY:
185  $this->addDirectory();
186  break;
187  case self::CMD_DOWNLOAD_ZIP:
188  $this->downloadZIP();
189  break;
190  }
191  }
192 
193  // RESOURCE COLLECTION GUI
194 
195  private function index(): void
196  {
197  global $DIC;
198  $components = [];
199 
200  // Add components from Actions
201  $components = array_merge(
202  $components,
203  $this->action_provider->getComponents()
204  );
205 
206  // Add components from the selected view (currently data-table)
207  foreach ($this->view_factory->getComponentProvider($this->view_request)->getComponents() as $component) {
208  $components[] = $component;
209  }
210 
211  $this->main_tpl->setContent(
212  $this->ui_renderer->render(
214  )
215  );
216  }
217 
218  private function downloadZIP(): never
219  {
220  $this->irss->consume()->download(
221  $this->view_configuration->getContainer()->getIdentification()
222  )->overrideFileName($this->view_request->getTitle())->run();
223  }
224 
225  private function addDirectory(): void
226  {
227  if (!$this->view_request->canUserAdministrate()) {
228  $this->abortWithPermissionDenied();
229  return;
230  }
231  $modal = $this->standard_action_provider->getAddDirectoryModal()->withRequest($this->http->request());
232 
233  $directory_name = $modal->getData()[0] ?? '';
234  if (empty($directory_name)) {
235  $this->main_tpl->setOnScreenMessage('failure', $this->language->txt('msg_error_adding_directory'), true);
236  $this->ctrl->redirect($this, self::CMD_INDEX);
237  return;
238  }
239  $directory_name = $this->view_request->getPath() . $directory_name;
240 
241  $success = $this->irss->manageContainer()->createDirectoryInsideContainer(
242  $this->view_configuration->getContainer()->getIdentification(),
243  $directory_name
244  );
245 
246  if (!$success) {
247  $this->main_tpl->setOnScreenMessage('failure', $this->language->txt('msg_error_adding_directory'), true);
248  $this->ctrl->redirect($this, self::CMD_INDEX);
249  return;
250  }
251 
252  $this->main_tpl->setOnScreenMessage('success', $this->language->txt('msg_success_adding_directory'), true);
253  $this->ctrl->redirect($this, self::CMD_INDEX);
254  }
255 
256  public function upload(): void
257  {
258  if (!$this->view_request->canUserUplaod()) {
259  $this->abortWithPermissionDenied();
260  return;
261  }
262  $this->upload->process();
263  if (!$this->upload->hasUploads()) {
264  return;
265  }
266  $container = $this->view_configuration->getContainer();
267 
268  foreach ($this->upload->getResults() as $result) {
269  if (!$result->isOK()) {
270  continue;
271  }
272  // store to zip
273  $return = $this->irss->manageContainer()->addUploadToContainer(
274  $container->getIdentification(),
275  $result,
276  $this->view_request->getPath()
277  );
278  }
279 
280  // OK
281  $upload_result = new BasicHandlerResult(
282  self::P_PATH,
283  $return ? BasicHandlerResult::STATUS_OK : BasicHandlerResult::STATUS_FAILED,
284  '-',
285  'undefined error'
286  );
287  $response = $this->http->response()->withBody(Streams::ofString(json_encode($upload_result)));
288  $this->http->saveResponse($response);
289  $this->http->sendResponse();
290  $this->http->close();
291  }
292 
293  private function postUpload(): void
294  {
295  if (!$this->view_request->canUserUplaod()) {
296  $this->abortWithPermissionDenied();
297  return;
298  }
299  if ($this->http->request()->getParsedBody() === []) { // nothing uploaded
300  $this->main_tpl->setOnScreenMessage('failure', $this->language->txt('rids_appended_failed'), true);
301  } else {
302  $this->main_tpl->setOnScreenMessage('success', $this->language->txt('rids_appended'), true);
303  }
304 
305  $this->ctrl->redirect($this, self::CMD_INDEX);
306  }
307 
308  private function download(): void
309  {
310  $paths = $this->getPathsFromRequest();
311 
312  $this->view_request->getWrapper()->download(
313  $paths[0],
314  $this->view_request->getPath()
315  );
316  }
317 
318  protected function getPathsFromRequest(): array
319  {
320  $unhash = fn(string $path) => $this->unhash($path);
321  $unhash_array = static fn(array $paths) => array_map(
322  $unhash,
323  $paths
324  );
325  $to_string = $this->refinery->kindlyTo()->string();
326  $to_array_of_strings = $this->refinery->kindlyTo()->listOf(
327  $to_string
328  );
329 
330  // Get item from table
331  $token_name = $this->action_builder->getUrlToken()->getName();
332  if ($this->http->wrapper()->query()->has($token_name)) {
333  return $unhash_array(
334  $this->http->wrapper()->query()->retrieve(
335  $token_name,
336  $to_array_of_strings
337  ) ?? []
338  );
339  }
340 
341  if ($this->http->wrapper()->post()->has('interruptive_items')) {
342  return $unhash_array(
343  $this->http->wrapper()->post()->retrieve(
344  'interruptive_items',
345  $to_array_of_strings
346  )
347  );
348  }
349 
350  return [];
351  }
352 
353  private function unzip(): void
354  {
355  if (!$this->view_request->canUserAdministrate()) {
356  $this->abortWithPermissionDenied();
357  return;
358  }
359  $paths = $this->getPathsFromRequest()[0];
360  $this->view_request->getWrapper()->unzip(
361  $paths
362  );
363 
364  $this->postUpload();
365  }
366 
367  private function renderConfirmRemove(): void
368  {
369  if (!$this->view_request->canUserAdministrate()) {
370  $this->abortWithPermissionDenied();
371  return;
372  }
373  $paths = $this->getPathsFromRequest();
374 
375  $stream = Streams::ofString(
376  $this->ui_renderer->render(
377  $this->ui_factory->modal()->interruptive(
378  $this->language->txt('action_remove_zip_path'),
379  $this->language->txt('action_remove_zip_path_msg'),
380  $this->ctrl->getLinkTarget($this, self::CMD_REMOVE)
381  )->withAffectedItems(
382  array_map(function (string $path_inside_zip) {
383  return $this->ui_factory->modal()->interruptiveItem()->standard(
384  $this->hash($path_inside_zip),
385  $path_inside_zip
386  );
387  }, $paths)
388  )
389  )
390  );
391  $this->http->saveResponse($this->http->response()->withBody($stream));
392  $this->http->sendResponse();
393  $this->http->close();
394  }
395 
396  private function remove(): void
397  {
398  if (!$this->view_request->canUserAdministrate()) {
399  $this->abortWithPermissionDenied();
400  return;
401  }
402  $paths = $this->getPathsFromRequest();
403 
404  if (empty($paths)) {
405  $this->main_tpl->setOnScreenMessage('failure', $this->language->txt('msg_no_perm_read'), true);
406  $this->ctrl->redirect($this, self::CMD_INDEX);
407  return;
408  }
409 
410  foreach ($paths as $path_inside_zip) {
411  $this->irss->manageContainer()->removePathInsideContainer(
412  $this->view_configuration->getContainer()->getIdentification(),
413  $path_inside_zip
414  );
415  }
416 
417  $this->main_tpl->setOnScreenMessage('success', $this->language->txt('msg_paths_deleted'), true);
418  $this->ctrl->redirect($this, self::CMD_INDEX);
419  }
420 
421  // REQUEST HELPERS
422 
426  private function getResourceIdsFromRequest(): array
427  {
428  $token = $this->action_builder->getUrlToken();
429  $wrapper = $this->http->wrapper();
430  $to_string = $this->refinery->kindlyTo()->string();
431  $to_array_of_string = $this->refinery->to()->listOf($to_string);
432  $rid_string = null;
433 
434  if ($wrapper->query()->has($token->getName())) {
435  try {
436  $rid_string = $wrapper->query()->retrieve(
437  $token->getName(),
438  $to_string
439  );
440  $rid_strings = explode(',', $rid_string);
441  } catch (ConstraintViolationException $e) {
442  $rid_strings = $wrapper->query()->retrieve(
443  $token->getName(),
444  $to_array_of_string
445  );
446  }
447  }
448 
449  if ($wrapper->post()->has('interruptive_items')) {
450  $rid_strings = $wrapper->post()->retrieve(
451  'interruptive_items',
452  $to_array_of_string
453  );
454  }
455 
456  if ($rid_strings[0] === 'ALL_OBJECTS') {
457  return $this->view_request->getWrapper()->getResourceIdentifications();
458  }
459 
460  if ($rid_strings === []) {
461  return [];
462  }
463  $resource_identifications = [];
464  foreach ($rid_strings as $rid_string) {
465  $resource_identification = $this->irss->manage()->find($this->unhash($rid_string));
466  if ($resource_identification === null) {
467  continue;
468  }
469  $resource_identifications[] = $resource_identification;
470  }
471  return $resource_identifications;
472  }
473 
474 
475  // UPLOAD HANDLER
476  public function getFileIdentifierParameterName(): string
477  {
478  return self::P_PATH;
479  }
480 
481  public function getUploadURL(): string
482  {
483  return $this->ctrl->getLinkTarget($this, self::CMD_UPLOAD);
484  }
485 
486  public function getFileRemovalURL(): string
487  {
488  return '';
489  }
490 
491  public function getExistingFileInfoURL(): string
492  {
493  return $this->ctrl->getLinkTarget($this, self::CMD_INFO);
494  }
495 
496  public function getInfoForExistingFiles(array $file_ids): array
497  {
498  return [];
499  }
500 
501  public function getInfoResult(string $identifier): ?FileInfoResult
502  {
503  return null;
504  }
505 
506  public function supportsChunkedUploads(): bool
507  {
508  return false;
509  }
510 }
ilGlobalTemplateInterface $main_tpl
ILIAS ResourceStorage Services $irss
StandardActionProvider $standard_action_provider
ActionBuilder ActionProvider $action_provider
$response
Definition: xapitoken.php:90
$path
Definition: ltiservices.php:30
$components
$container
Definition: wac.php:13
__construct(private Configuration $view_configuration)
static http()
Fetches the global http state from ILIAS.
$token
Definition: xapitoken.php:67
global $DIC
Definition: shib_login.php:25
ILIAS FileUpload FileUpload $upload
ILIAS Filesystem Util Archive Archives $archive
language()
description: > Example for rendring a language glyph.
Definition: language.php:25