ILIAS  trunk Revision v12.0_alpha-1227-g7ff6d300864
class.ilMDVocabulariesGUI.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
21use ILIAS\HTTP\Services as HTTP;
22use ILIAS\UI\Factory as UIFactory;
23use ILIAS\UI\Renderer as UIRenderer;
24use ILIAS\UI\Component\Table\Data as DataTable;
27use ILIAS\UI\Component\Modal\RoundTrip as RoundtripModal;
36use ILIAS\Refinery\Factory as Refinery;
38use JetBrains\PhpStorm\NoReturn;
40
45{
46 protected const int MAX_CONFIRMATION_VALUES = 5;
47
48 protected ilCtrl $ctrl;
49 protected HTTP $http;
52 protected ilLanguage $lng;
54 protected UIFactory $ui_factory;
55 protected UIRenderer $ui_renderer;
58 protected Refinery $refinery;
59
60 protected VocabManager $vocab_manager;
63
65 {
66 global $DIC;
67
68 $services = new InternalServices($DIC);
69
70 $this->vocab_manager = $services->vocabularies()->manager();
71 $this->presentation = new Presentation(
72 $services->presentation()->elements(),
73 $services->presentation()->utilities(),
74 $services->vocabularies()->presentation(),
75 $services->vocabularies()->slotHandler(),
76 $services->structure()->structure(),
77 $services->paths()->navigatorFactory(),
78 $services->paths()->pathFactory()
79 );
80 $this->importer = new Importer(
81 $services->paths()->pathFactory(),
82 $this->vocab_manager->controlledVocabularyCreator(),
83 $services->vocabularies()->slotHandler()
84 );
85
86 $this->ctrl = $DIC->ctrl();
87 $this->http = $DIC->http();
88 $this->temp_files = $DIC->filesystem()->temp();
89 $this->lng = $DIC->language();
90 $this->tpl = $DIC->ui()->mainTemplate();
91 $this->toolbar = $DIC->toolbar();
92 $this->ui_factory = $DIC->ui()->factory();
93 $this->ui_renderer = $DIC->ui()->renderer();
94 $this->refinery = $DIC->refinery();
95
96 $this->parent_obj_gui = $parent_obj_gui;
97 $this->access_service = new ilMDSettingsAccessService(
98 $this->parent_obj_gui->getRefId(),
99 $DIC->access()
100 );
101
102 $this->lng->loadLanguageModule("meta");
103 }
104
105 public function executeCommand(): void
106 {
107 $next_class = $this->ctrl->getNextClass($this);
108 $cmd = $this->ctrl->getCmd();
109
110 if (!$this->access_service->hasCurrentUserReadAccess()) {
111 throw new ilPermissionException($this->lng->txt('no_permission'));
112 }
113
114 switch ($next_class) {
115 case strtolower(ilMDVocabularyUploadHandlerGUI::class):
117 $this->ctrl->forwardCommand($handler);
118
119 // no break
120 default:
121 if (!$cmd || $cmd === 'view') {
122 $cmd = 'showVocabularies';
123 }
124
125 $this->$cmd();
126 break;
127 }
128 }
129
130 public function showVocabularies(): void
131 {
132 $content = [];
133
134 if ($this->access_service->hasCurrentUserWriteAccess()) {
135 $import_modal = $this->getImportModal();
136 $this->toolbar->addComponent($this->getImportButton($import_modal->getShowSignal()));
137 $content[] = $import_modal;
138 }
139
140 $content[] = $this->getTable();
141
142 $this->tpl->setContent($this->ui_renderer->render($content));
143 }
144
145 public function tableAction(): void
146 {
147 $action = $this->fetchTableAction();
148 $vocab_id = $this->fetchVocabID();
149
150 if (
151 $vocab_id === '' ||
152 ($action !== 'show_all' && !$this->access_service->hasCurrentUserWriteAccess())
153 ) {
154 $this->ctrl->redirect($this, 'showVocabularies');
155 }
156
157 switch ($action) {
158 case 'delete':
159 $this->confirmDeleteVocabulary($vocab_id);
160 return;
161
162 case 'activate':
163 $this->activateVocabulary($vocab_id);
164 return;
165
166 case 'deactivate':
167 $this->deactivateVocabulary($vocab_id);
168 return;
169
170 case 'allow_custom_input':
171 $this->allowCustomInputForVocabulary($vocab_id);
172 return;
173
174 case 'disallow_custom_input':
175 $this->disallowCustomInputForVocabulary($vocab_id);
176 return;
177
178 case 'show_all':
179 $this->showAllValuesModalForVocabulary($vocab_id);
180 return;
181
182 default:
183 $this->ctrl->redirect($this, 'showVocabularies');
184 }
185 }
186
187 public function importVocabulary(): void
188 {
189 if (!$this->access_service->hasCurrentUserWriteAccess()) {
190 $this->ctrl->redirect($this, 'showVocabularies');
191 }
192
193 $message_type = 'failure';
194 $message_text = $this->lng->txt('md_vocab_import_upload_failed');
195
196 $modal = $this->getImportModal()->withRequest($this->http->request());
197
198 $upload_folder = null;
199 if ($modal->getData()) {
200 $upload_folder = (string) ($modal->getData()['file'][0] ?? null);
201 if (!$this->temp_files->hasDir($upload_folder)) {
202 $upload_folder = null;
203 }
204 }
205
206 $file_content = null;
207 if (!is_null($upload_folder)) {
208 $files = $files = $this->temp_files->listContents($upload_folder);
209 if (count($files) === 1 && ($files[0] ?? null)?->isFile()) {
210 $file_content = $this->temp_files->read($files[0]->getPath());
211 }
212 $this->temp_files->deleteDir($upload_folder);
213 }
214
215 if (!is_null($file_content)) {
216 $result = $this->importer->import($file_content);
217
218 if ($result->wasSuccessful()) {
219 $message_type = 'success';
220 $message_text = $this->lng->txt('md_vocab_import_successful');
221 } else {
222 $message_type = 'failure';
223 $message_text = sprintf(
224 $this->lng->txt('md_vocab_import_invalid'),
225 implode("<br/>", $result->getErrors())
226 );
227 }
228 }
229
230 $this->tpl->setOnScreenMessage($message_type, $message_text, true);
231 $this->ctrl->redirect($this, 'showVocabularies');
232 }
233
234 #[NoReturn] protected function confirmDeleteVocabulary(string $vocab_id): void
235 {
236 list($url_builder, $action_parameter_token, $vocabs_id_token) = $this->getTableURLBuilderAndParameters();
237 $key = $vocabs_id_token->getName();
238
239 $vocab = $this->vocab_manager->getVocabulary($vocab_id);
241 foreach ($this->presentation->makeValuesPresentable(
242 $vocab,
243 self::MAX_CONFIRMATION_VALUES
244 ) as $value) {
245 $value_items[] = $this->ui_factory->modal()->interruptiveItem()->standard(
246 '',
247 $value,
248 );
249 }
250
251 $this->ctrl->setParameter($this, $key, $vocab_id);
252 $link = $this->ctrl->getLinkTarget($this, 'deleteVocabulary');
253 $this->ctrl->clearParameters($this);
254
255 $modal = $this->ui_factory->modal()->interruptive(
256 $this->presentation->txt('md_vocab_delete_confirmation_title'),
257 $this->presentation->txtFill(
258 'md_vocab_delete_confirmation_text',
259 $this->presentation->makeSlotPresentable($vocab->slot()),
260 $vocab->source()
261 ),
262 $link
263 )->withAffectedItems($value_items);
264 echo $this->ui_renderer->renderAsync($modal);
266 }
267
268 protected function deleteVocabulary(): void
269 {
270 $vocab_id = $this->fetchVocabID();
271 if ($vocab_id !== '') {
272 $this->vocab_manager->actions()->delete(
273 $this->vocab_manager->getVocabulary($vocab_id)
274 );
275 }
276 $this->tpl->setOnScreenMessage(
277 GlobalTemplate::MESSAGE_TYPE_SUCCESS,
278 $this->lng->txt('md_vocab_deletion_successful'),
279 true
280 );
281 $this->ctrl->redirect($this, 'showVocabularies');
282 }
283
284 protected function activateVocabulary(string $vocab_id): void
285 {
286 $this->vocab_manager->actions()->activate(
287 $this->vocab_manager->getVocabulary($vocab_id)
288 );
289 $this->tpl->setOnScreenMessage(
290 GlobalTemplate::MESSAGE_TYPE_SUCCESS,
291 $this->lng->txt('md_vocab_update_successful'),
292 true
293 );
294 $this->ctrl->redirect($this, 'showVocabularies');
295 }
296
297 protected function deactivateVocabulary(string $vocab_id): void
298 {
299 $this->vocab_manager->actions()->deactivate(
300 $this->vocab_manager->getVocabulary($vocab_id)
301 );
302 $this->tpl->setOnScreenMessage(
303 GlobalTemplate::MESSAGE_TYPE_SUCCESS,
304 $this->lng->txt('md_vocab_update_successful'),
305 true
306 );
307 $this->ctrl->redirect($this, 'showVocabularies');
308 }
309
310 protected function allowCustomInputForVocabulary(string $vocab_id): void
311 {
312 $this->vocab_manager->actions()->allowCustomInput(
313 $this->vocab_manager->getVocabulary($vocab_id)
314 );
315 $this->tpl->setOnScreenMessage(
316 GlobalTemplate::MESSAGE_TYPE_SUCCESS,
317 $this->lng->txt('md_vocab_update_successful'),
318 true
319 );
320 $this->ctrl->redirect($this, 'showVocabularies');
321 }
322
323 protected function disallowCustomInputForVocabulary(string $vocab_id): void
324 {
325 $this->vocab_manager->actions()->disallowCustomInput(
326 $this->vocab_manager->getVocabulary($vocab_id)
327 );
328 $this->tpl->setOnScreenMessage(
329 GlobalTemplate::MESSAGE_TYPE_SUCCESS,
330 $this->lng->txt('md_vocab_update_successful'),
331 true
332 );
333 $this->ctrl->redirect($this, 'showVocabularies');
334 }
335
336 #[NoReturn] protected function showAllValuesModalForVocabulary(string $vocab_id): void
337 {
338 $vocab = $this->vocab_manager->getVocabulary($vocab_id);
339 $values = $this->ui_factory->listing()->unordered(
340 $this->presentation->makeValuesPresentable($vocab)
341 );
342 $modal = $this->ui_factory->modal()->roundtrip(
343 $this->presentation->txtFill(
344 'md_vocab_all_values_title',
345 $this->presentation->makeSlotPresentable($vocab->slot()),
346 $vocab->source()
347 ),
348 [$values]
349 );
350 echo $this->ui_renderer->renderAsync($modal);
351 exit;
352 }
353
354 protected function getTable(): DataTable
355 {
356 $column_factory = $this->ui_factory->table()->column();
357 $columns = [
358 'element' => $column_factory->text($this->lng->txt('md_vocab_element_column'))->withIsSortable(false),
359 'type' => $column_factory->status($this->lng->txt('md_vocab_type_column'))->withIsSortable(false),
360 'source' => $column_factory->text($this->lng->txt('md_vocab_source_column'))->withIsSortable(false),
361 'preview' => $column_factory->text($this->lng->txt('md_vocab_preview_column'))->withIsSortable(false),
362 'active' => $column_factory->statusIcon($this->lng->txt('md_vocab_active_column'))->withIsSortable(false),
363 'custom_input' => $column_factory->statusIcon($this->lng->txt('md_vocab_custom_input_column'))->withIsSortable(false)
364 ];
365
366 list($url_builder, $action_parameter_token, $row_id_token) = $this->getTableURLBuilderAndParameters();
367 $actions_factory = $this->ui_factory->table()->action();
368 $actions = [];
369
370 if ($this->access_service->hasCurrentUserWriteAccess()) {
371 $actions ['delete'] = $actions_factory->single(
372 $this->lng->txt('md_vocab_delete_action'),
373 $url_builder->withParameter($action_parameter_token, 'delete'),
374 $row_id_token
375 )->withAsync(true);
376 $actions['activate'] = $actions_factory->single(
377 $this->lng->txt('md_vocab_activate_action'),
378 $url_builder->withParameter($action_parameter_token, 'activate'),
379 $row_id_token
380 );
381 $actions['deactivate'] = $actions_factory->single(
382 $this->lng->txt('md_vocab_deactivate_action'),
383 $url_builder->withParameter($action_parameter_token, 'deactivate'),
384 $row_id_token
385 );
386 $actions['allow_custom_input'] = $actions_factory->single(
387 $this->lng->txt('md_vocab_allow_custom_input_action'),
388 $url_builder->withParameter($action_parameter_token, 'allow_custom_input'),
389 $row_id_token
390 );
391 $actions['disallow_custom_input'] = $actions_factory->single(
392 $this->lng->txt('md_vocab_disallow_custom_input_action'),
393 $url_builder->withParameter($action_parameter_token, 'disallow_custom_input'),
394 $row_id_token
395 );
396 }
397
398 $actions['show_all'] = $actions_factory->single(
399 $this->lng->txt('md_vocab_show_all_action'),
400 $url_builder->withParameter($action_parameter_token, 'show_all'),
401 $row_id_token
402 )->withAsync(true);
403
404 return $this->ui_factory->table()->data(
405 new DataRetrieval(
406 $this->vocab_manager,
407 $this->presentation,
408 $this->ui_factory
409 ),
410 $this->lng->txt('md_vocab_table_title'),
411 $columns,
412 )->withActions($actions)->withRequest($this->http->request());
413 }
414
415 protected function getImportModal(): RoundtripModal
416 {
417 $file_input = $this->ui_factory->input()->field()->file(
419 $this->lng->txt('md_import_file_vocab')
420 )->withAcceptedMimeTypes([MimeType::TEXT__XML])->withMaxFiles(1);
421
422 return $this->ui_factory->modal()->roundtrip(
423 $this->lng->txt('md_import_vocab_modal'),
424 null,
425 ['file' => $file_input],
426 $this->ctrl->getLinkTarget($this, 'importVocabulary')
427 );
428 }
429
430 protected function getImportButton(Signal $signal): Button
431 {
432 return $this->ui_factory->button()->standard(
433 $this->lng->txt('md_import_vocab'),
434 $signal
435 );
436 }
437
438 protected function fetchTableAction(): string
439 {
440 list($url_builder, $action_parameter_token, $vocabs_id_token) = $this->getTableURLBuilderAndParameters();
441 $key = $action_parameter_token->getName();
442 if ($this->http->wrapper()->query()->has($key)) {
443 return $this->http->wrapper()->query()->retrieve(
444 $key,
445 $this->refinery->identity()
446 );
447 }
448 return '';
449 }
450
451 protected function fetchVocabID(): string
452 {
453 list($url_builder, $action_parameter_token, $vocabs_id_token) = $this->getTableURLBuilderAndParameters();
454 $key = $vocabs_id_token->getName();
455 if ($this->http->wrapper()->query()->has($key)) {
456 return $this->http->wrapper()->query()->retrieve(
457 $key,
458 $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->string())
459 )[0] ?? '';
460 }
461 return '';
462 }
463
464 protected function getTableURLBuilderAndParameters(): array
465 {
466 $url_builder = new URLBuilder(new URI(
467 rtrim(ILIAS_HTTP_PATH, '/') . '/' . $this->ctrl->getLinkTarget($this, 'tableAction')
468 ));
469 return $url_builder->acquireParameters(
470 ['metadata', 'vocab'],
471 'table_action',
472 'ids'
473 );
474 }
475}
Builds a Color from either hex- or rgb values.
Definition: Factory.php:31
Builds data types.
Definition: Factory.php:36
The scope of this class is split ilias-conform URI's into components.
Definition: URI.php:35
Mime type determination.
Definition: MimeType.php:30
Class Services.
Definition: Services.php:38
Class ilCtrl provides processing control methods.
language handling
@ilCtrl_Calls ilMDVocabulariesGUI: ilMDVocabularyUploadHandlerGUI
disallowCustomInputForVocabulary(string $vocab_id)
ilMDSettingsAccessService $access_service
allowCustomInputForVocabulary(string $vocab_id)
__construct(ilObjMDSettingsGUI $parent_obj_gui)
deactivateVocabulary(string $vocab_id)
ilGlobalTemplateInterface $tpl
activateVocabulary(string $vocab_id)
ilObjMDSettingsGUI $parent_obj_gui
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
The filesystem interface provides the public interface for the Filesystem service API consumer.
Definition: Filesystem.php:37
This describes a standard button.
Definition: Standard.php:27
This describes a Data Table.
Definition: Data.php:33
An entity that renders components to a string output.
Definition: Renderer.php:31
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...
Definition: Bulky.php:21
$handler
Definition: oai.php:31
global $DIC
Definition: shib_login.php:26