ILIAS  trunk Revision v12.0_alpha-1227-g7ff6d300864
class.ilResourceCollectionGUI.php
Go to the documentation of this file.
1<?php
2
34use ILIAS\components\ResourceStorage\BinToHexSerializer;
40use ILIAS\Services\ResourceStorage\Collections\View\EditForm;
42
47{
48 use BinToHexSerializer;
49
50 public const P_RESOURCE_ID = 'resource_id';
51 public const P_RESOURCE_IDS = 'resource_ids';
52
53 public const CMD_INDEX = 'index';
54 public const CMD_INFO = 'info';
55 public const CMD_UPLOAD = 'upload';
56 public const CMD_POST_UPLOAD = 'postUpload';
57 public const CMD_REMOVE = 'remove';
58 public const CMD_DOWNLOAD = 'download';
59
60 public const CMD_UNZIP = 'unzip';
61 public const CMD_EDIT = 'rename';
62 public const CMD_RENDER_CONFIRM_REMOVE = 'renderConfirmRemove';
63 public const CMD_STORE = 'store';
70 private Services $http;
72 private \ILIAS\ResourceStorage\Services $irss;
75 private \ILIAS\UI\Factory $ui_factory;
79
80 final public function __construct(
81 private Configuration $view_configuration
82 ) {
83 global $DIC;
84 $this->ctrl = $DIC->ctrl();
85 $this->main_tpl = $DIC->ui()->mainTemplate();
86 $this->ui_renderer = $DIC->ui()->renderer();
87 $this->ui_factory = $DIC->ui()->factory();
88 $this->http = $DIC->http();
89 $this->refinery = $DIC->refinery();
90 $this->language = $DIC->language();
91 $this->language->loadLanguageModule('irss');
92 $this->irss = $DIC->resourceStorage();
93 $this->upload = $DIC->upload();
94 $this->archive = $DIC->archives();
95 $this->preview_definition = new PreviewDefinition();
96
97 $this->view_request = new Request(
98 $DIC->ctrl(),
99 $DIC->http()->wrapper()->query(),
100 $this->view_configuration
101 );
102
103 $data_provider = new TableDataProvider($this->view_request);
104
105 $this->action_builder = new ActionBuilder(
106 $this->view_request,
107 $this->ctrl,
108 $DIC->ui()->factory(),
109 $DIC->language(),
110 $this->irss
111 );
112
114 $this->view_request,
115 $data_provider,
116 $this->ctrl,
117 $DIC->ui()->factory(),
118 $DIC->language()
119 );
120
121 $upload_builder = new UploadBuilder(
122 $this->view_request,
123 $this->ctrl,
124 $DIC->ui()->factory(),
125 $DIC->language(),
126 $this
127 );
128
129 $this->view_factory = new ViewFactory(
130 $data_provider,
131 $this->action_builder,
133 $upload_builder
134 );
135 }
136
137 // CMD CLASS
138
144 {
145 $rid = $this->getResourceIdsFromRequest()[0] ?? null;
146 if ($rid === null || !$this->view_request->getCollection()->isIn($rid)) {
148 }
149 return $rid;
150 }
151
152 protected function abortWithPermissionDenied(): void
153 {
154 $this->main_tpl->setOnScreenMessage('failure', $this->language->txt('msg_no_perm_read'), true);
155 $this->ctrl->redirect($this, self::CMD_INDEX);
156 }
157
158 final public function executeCommand(): void
159 {
160 if ($this->view_request->handleViewTitle()) {
161 $title = $this->view_request->getTitle();
162 if ($title !== null) {
163 $this->main_tpl->setTitle($title);
164 }
165 $description = $this->view_request->getDescription();
166 if ($description !== null) {
167 $this->main_tpl->setDescription($description);
168 }
169 }
170
171 $this->view_request->init($this);
172
173 switch ($this->ctrl->getCmd(self::CMD_INDEX)) {
174 case self::CMD_INDEX:
175 $this->index();
176 break;
177 case self::CMD_UPLOAD:
178 $this->upload();
179 break;
181 $this->postUpload();
182 break;
183 case self::CMD_REMOVE:
184 $this->remove();
185 break;
187 $this->download();
188 break;
189 case self::CMD_UNZIP:
190 $this->unzip();
191 break;
193 $this->renderConfirmRemove();
194 break;
195 case self::CMD_EDIT:
196 $this->edit();
197 break;
198 case self::CMD_STORE:
199 $this->store();
200 break;
201 }
202 }
203
204 // RESOURCE COLLECTION GUI
205
206 private function index(): void
207 {
208 $provider = $this->view_factory->getComponentProvider($this->view_request);
209 $components = [];
210 foreach ($provider->getComponents() as $component) {
211 $components[] = $component;
212 }
213
214 $this->main_tpl->setContent($this->ui_renderer->render($components));
215 }
216
217 public function upload(): void
218 {
219 if (!$this->view_request->canUserUplaod()) {
221 return;
222 }
223 $this->upload->process();
224 if (!$this->upload->hasUploads()) {
225 return;
226 }
227 $collection = $this->view_request->getCollection();
228 foreach ($this->upload->getResults() as $result) {
229 if (!$result->isOK()) {
230 continue;
231 }
232 // if activated, prevent duplicate files by checking filenames. in thjis case a new revision gets appended
233 if ($this->view_request->preventDuplicates()) {
234 $existing_rid = $this->irss->collection()->findIdentificationByNameIn(
235 $this->view_request->getCollection(),
236 $result->getName()
237 );
238 if ($existing_rid !== null) {
239 $this->irss->manage()->appendNewRevision(
240 $existing_rid,
241 $upload_result,
242 $this->view_configuration->getStakeholder()
243 );
244 }
245 }
246
247 $rid = $existing_rid ?? $this->irss->manage()->upload(
248 $result,
249 $this->view_configuration->getStakeholder()
250 );
251 $collection->add($rid);
252
253 // ensure flavour
254 $this->irss->flavours()->ensure(
255 $rid,
256 $this->preview_definition
257 );
258 }
259 $this->irss->collection()->store($collection);
260 $upload_result = new BasicHandlerResult(
261 self::P_RESOURCE_ID,
262 BasicHandlerResult::STATUS_OK,
263 $rid->serialize(),
264 ''
265 );
266 $response = $this->http->response()->withBody(Streams::ofString(json_encode($upload_result)));
267 $this->http->saveResponse($response);
268 $this->http->sendResponse();
269 $this->http->close();
270 }
271
272 private function postUpload(): void
273 {
274 if (!$this->view_request->canUserUplaod()) {
276 return;
277 }
278 $this->main_tpl->setOnScreenMessage('success', $this->language->txt('rids_appended'), true);
279 $this->ctrl->redirect($this, self::CMD_INDEX);
280 }
281
282 private function download(): void
283 {
284 $rid = $this->checkResourceOrRedirect();
285 $this->irss->consume()->download($rid)->run();
286 }
287
288 private function unzip(): void
289 {
290 if (!$this->view_request->canUserAdministrate()) {
292 return;
293 }
294 $rid = $this->checkResourceOrRedirect();
295 $zip_stream = $this->irss->consume()->stream($rid)->getStream();
296
297 $collection = $this->view_request->getCollection();
298
299 $unzip_options = $this->archive->unzipOptions()
300 ->withDirectoryHandling(ZipDirectoryHandling::FLAT_STRUCTURE);
301
302 foreach ($this->archive->unzip($zip_stream, $unzip_options)->getFileStreams() as $stream) {
303 $rid = $this->irss->manage()->stream(
304 Streams::ofString($stream->getContents()),
305 $this->view_configuration->getStakeholder(),
306 basename((string) $stream->getMetadata()['uri'])
307 );
308 $collection->add($rid);
309
310 // ensure flavour
311 try {
312 $this->irss->flavours()->ensure(
313 $rid,
314 $this->preview_definition
315 );
316 } catch (\Throwable) {
317 }
318 }
319 $this->irss->collection()->store($collection);
320 $this->postUpload();
321 }
322
323 private function edit(): void
324 {
325 if (!$this->view_request->canUserAdministrate()) {
327 return;
328 }
329 $rid = $this->checkResourceOrRedirect();
330 $this->ctrl->setParameter(
331 $this,
332 self::P_RESOURCE_ID,
333 $this->hash($rid->serialize())
334 );
335
336 // build simple form
337 $form = new EditForm(
338 $this->view_request,
339 $rid
340 );
341
342 $modal = $this->ui_factory->modal()->roundtrip(
343 $this->language->txt('edit'),
344 null,
345 $form->getFields(),
346 $this->ctrl->getLinkTarget($this, self::CMD_STORE)
347 );
348
349 $signal = $modal->getForm()->getSubmitSignal();
350
351 $stream = Streams::ofString(
352 $this->ui_renderer->renderAsync(
353 $modal
354 )
355 );
356
357 $this->http->saveResponse($this->http->response()->withBody($stream));
358 $this->http->sendResponse();
359 $this->http->close();
360 }
361
362 private function store(): void
363 {
364 if (!$this->view_request->canUserAdministrate()) {
366 return;
367 }
368 $rid = $this->checkResourceOrRedirect();
369 $form = (new EditForm(
370 $this->view_request,
371 $rid
372 ))->getAsForm($this->ctrl->getLinkTarget($this, self::CMD_STORE))
373 ->withRequest(
374 $this->http->request()
375 );
376 // Store the data
377 $form->getData();
378 $this->main_tpl->setOnScreenMessage('success', $this->language->txt('rids_updated'), true);
379 $this->ctrl->redirect($this, self::CMD_INDEX);
380 }
381
382 private function renderConfirmRemove(): void
383 {
384 if (!$this->view_request->canUserAdministrate()) {
386 return;
387 }
388 $rids = $this->getResourceIdsFromRequest();
389 $stream = Streams::ofString(
390 $this->ui_renderer->render(
391 $this->ui_factory->modal()->interruptive(
392 $this->language->txt('action_remove_resource'),
393 $this->language->txt('action_remove_resource_msg'),
394 $this->ctrl->getLinkTarget($this, self::CMD_REMOVE)
395 )->withAffectedItems(
396 array_map(function (ResourceIdentification $rid): Standard {
397 $revision = $this->irss->manage()->getCurrentRevision($rid);
398
399 return $this->ui_factory->modal()->interruptiveItem()->standard(
400 $this->hash($rid->serialize()),
401 $revision->getTitle()
402 );
403 }, $rids)
404 )
405 )
406 );
407 $this->http->saveResponse($this->http->response()->withBody($stream));
408 $this->http->sendResponse();
409 $this->http->close();
410 }
411
412 private function remove(): void
413 {
414 if (!$this->view_request->canUserAdministrate()) {
416 return;
417 }
418 $rids = $this->getResourceIdsFromRequest();
419 if (empty($rids)) {
420 $this->main_tpl->setOnScreenMessage('failure', $this->language->txt('msg_no_perm_read'), true);
421 $this->ctrl->redirect($this, self::CMD_INDEX);
422 return;
423 }
424 foreach ($rids as $rid) {
425 if (!$this->view_request->getCollection()->isIn($rid)) {
426 $this->main_tpl->setOnScreenMessage('failure', $this->language->txt('msg_no_perm_read'), true);
427 $this->ctrl->redirect($this, self::CMD_INDEX);
428 return;
429 }
430 }
431
432 foreach ($rids as $rid) {
433 $this->irss->manage()->remove($rid, $this->view_configuration->getStakeholder());
434 }
435
436 $this->main_tpl->setOnScreenMessage('success', $this->language->txt('rids_deleted'), true);
437 $this->ctrl->redirect($this, self::CMD_INDEX);
438 }
439
440 // REQUEST HELPERS
441
445 private function getResourceIdsFromRequest(): array
446 {
447 $token = $this->action_builder->getUrlToken();
448 $wrapper = $this->http->wrapper();
449 $to_string = $this->refinery->kindlyTo()->string();
450 $to_array_of_string = $this->refinery->to()->listOf($to_string);
451 $rid_string = null;
452
453 if ($wrapper->query()->has($token->getName())) {
454 try {
455 $rid_string = $wrapper->query()->retrieve(
456 $token->getName(),
457 $to_string
458 );
459 $rid_strings = explode(',', (string) $rid_string);
461 $rid_strings = $wrapper->query()->retrieve(
462 $token->getName(),
463 $to_array_of_string
464 );
465 }
466 }
467
468 if ($wrapper->post()->has('interruptive_items')) {
469 $rid_strings = $wrapper->post()->retrieve(
470 'interruptive_items',
471 $to_array_of_string
472 );
473 }
474
475 if (empty($rid_strings)) {
476 // try single resource
477 $rid_strings = $this->http->wrapper()->query()->has(self::P_RESOURCE_ID)
478 ? [$this->http->wrapper()->query()->retrieve(self::P_RESOURCE_ID, $this->refinery->kindlyTo()->string())]
479 : [];
480 }
481
482 if (isset($rid_strings[0]) && $rid_strings[0] === 'ALL_OBJECTS') {
483 return $this->view_request->getCollection()->getResourceIdentifications();
484 }
485
486 if ($rid_strings === []) {
487 return [];
488 }
489 $resource_identifications = [];
490 foreach ($rid_strings as $rid_string) {
491 $resource_identification = $this->irss->manage()->find($this->unhash($rid_string));
492 if ($resource_identification === null) {
493 continue;
494 }
495 $resource_identifications[] = $resource_identification;
496 }
497 return $resource_identifications;
498 }
499
500 // UPLOAD HANDLER
501 public function getFileIdentifierParameterName(): string
502 {
503 return self::P_RESOURCE_ID;
504 }
505
506 public function getUploadURL(): string
507 {
508 return $this->ctrl->getLinkTarget($this, self::CMD_UPLOAD);
509 }
510
511 public function getFileRemovalURL(): string
512 {
513 return '';
514 }
515
516 public function getExistingFileInfoURL(): string
517 {
518 return $this->ctrl->getLinkTarget($this, self::CMD_INFO);
519 }
520
521 public function getInfoForExistingFiles(array $file_ids): array
522 {
523 return [];
524 }
525
526 public function getInfoResult(string $identifier): ?FileInfoResult
527 {
528 return null;
529 }
530
531 public function supportsChunkedUploads(): bool
532 {
533 return false;
534 }
535}
$components
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
Class Services.
Definition: Services.php:38
language handling
ilGlobalTemplateInterface $main_tpl
__construct(private Configuration $view_configuration)
ILIAS ResourceStorage Services $irss
An entity that renders components to a string output.
Definition: Renderer.php:31
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
$provider
Definition: ltitoken.php:80
static http()
Fetches the global http state from ILIAS.
@ FLAT_STRUCTURE
@description Will keep the top directory of the ZIP file if there is one (simple unzip).
global $DIC
Definition: shib_login.php:26
$token
Definition: xapitoken.php:67
$response
Definition: xapitoken.php:90