ILIAS  trunk Revision v12.0_alpha-377-g3641b37b9db
class.ilObjectCopyGUI.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
24use ILIAS\Refinery\Factory as Refinery;
27use Psr\Http\Message\ServerRequestInterface;
28use ILIAS\UI\Factory as UIFactory;
29use ILIAS\UI\Renderer as UIRenderer;
30use ILIAS\Data\Factory as DataFactory;
35
44{
45 public const SOURCE_SELECTION = 1;
46 public const TARGET_SELECTION = 2;
47 public const SEARCH_SOURCE = 3;
48
49 public const SUBMODE_COMPLETE = 1;
50 public const SUBMODE_CONTENT_ONLY = 2;
51
52 // tabs
53 public const TAB_SELECTION_TARGET_TREE = 1;
54 public const TAB_SELECTION_SOURCE_TREE = 2;
55 public const TAB_SELECTION_MEMBERSHIP = 3;
56
57 // group selection of source or target
58 public const TAB_GROUP_SC_SELECTION = 1;
59
60 protected ilCtrl $ctrl;
61 protected ilTree $tree;
62 protected ilTabsGUI $tabs;
69 protected ilObjUser $user;
71 protected ilLogger $log;
72 protected ilLanguage $lng;
75 protected Refinery $refinery;
76 protected ServerRequestInterface $request;
77 protected UIFactory $ui_factory;
78 protected UIRenderer $ui_renderer;
80
82
85
86 protected int $mode = 0;
88 protected string $type = '';
89 protected array $sources = [];
90 protected array $targets = [];
91 protected array $targets_copy_id = [];
94
95 public function __construct(ImplementsCreationCallback $parent_gui)
96 {
98 global $DIC;
99 $this->ctrl = $DIC['ilCtrl'];
100 $this->tree = $DIC['tree'];
101 $this->tabs = $DIC['ilTabs'];
102 $this->tpl = $DIC["tpl"];
103 $this->obj_definition = $DIC["objDefinition"];
104 $this->obj_data_cache = $DIC["ilObjDataCache"];
105 $this->access = $DIC->access();
106 $this->error = $DIC["ilErr"];
107 $this->user = $DIC['user']->getLoggedInUser();
108 $this->rbacsystem = $DIC['rbacsystem'];
109 $this->rbacreview = $DIC['rbacreview'];
110 $this->log = ilLoggerFactory::getLogger('obj');
111 $this->lng = $DIC['lng'];
112 $this->request_wrapper = $DIC->http()->wrapper()->query();
113 $this->post_wrapper = $DIC->http()->wrapper()->post();
114 $this->refinery = $DIC['refinery'];
115 $this->request = $DIC->http()->request();
116 $this->ui_factory = $DIC['ui.factory'];
117 $this->ui_renderer = $DIC['ui.renderer'];
118 $this->http = $DIC['http'];
119 $this->retriever = new ilObjectRequestRetriever($this->http->wrapper(), $this->refinery);
120
121 $this->container_repo = new ContainerDBRepository($DIC['ilDB']);
122
123
124 $this->parent_obj = $parent_gui;
125
126 $this->lng->loadLanguageModule('search');
127 $this->lng->loadLanguageModule('obj');
128 $this->ctrl->saveParameter($this, "crtcb");
129
130 $this->clipboard = $DIC
131 ->repository()
132 ->internal()
133 ->domain()
134 ->clipboard()
135 ;
136 }
137
138 public function executeCommand(): void
139 {
140 $this->init();
141 $this->initTabs();
142
143 $this->ctrl->getNextClass($this);
144 $cmd = $this->ctrl->getCmd();
145
146 $this->$cmd();
147 }
148
149 protected function init(): void
150 {
151 if ($this->retriever->has('smode')) {
152 $this->setSubMode($this->retriever->getMaybeInt('smode') ?? 0);
153 $this->ctrl->setParameter($this, 'smode', $this->getSubMode());
154 ilLoggerFactory::getLogger('obj')->debug('Submode is: ' . $this->getSubMode());
155 }
156
157 // save sources
158 if ($this->retriever->has('source_ids')) {
159 $this->setSource(explode('_', $this->retriever->getMaybeString('source_ids')));
160 $this->ctrl->setParameter($this, 'source_ids', implode('_', $this->getSources()));
161 ilLoggerFactory::getLogger('obj')->debug('Multiple sources: ' . implode('_', $this->getSources()));
162 }
163 if ($this->retriever->has('source_id')) {
164 $this->setSource([$this->retriever->getMaybeInt('source_id')]);
165 $this->ctrl->setParameter($this, 'source_ids', implode('_', $this->getSources()));
166 ilLoggerFactory::getLogger('obj')->debug('source_id is set: ' . implode('_', $this->getSources()));
167 }
168 if ($this->getFirstSource()) {
169 $this->setType(
171 );
172 }
173
174 // creation screen: copy section
175 if ($this->retriever->has('new_type')) {
176 $this->setMode(self::SEARCH_SOURCE);
177 $this->setType($this->retriever->getMaybeString('new_type'));
178 $this->setTarget($this->request_wrapper->retrieve("ref_id", $this->refinery->kindlyTo()->int()));
179
180 $this->ctrl->setParameter($this, 'new_type', $this->getType());
181 $this->ctrl->setParameterByClass(get_class($this->getParentObject()), 'new_type', $this->getType());
182 $this->ctrl->setParameterByClass(get_class($this->getParentObject()), 'cpfl', 1);
183 $this->ctrl->setReturnByClass(get_class($this->getParentObject()), 'create');
184
185 ilLoggerFactory::getLogger('obj')->debug('Copy from object creation for type: ' . $this->getType());
186 return;
187 }
188 // adopt content, and others?
189 elseif ($this->retriever->getMaybeInt('selectMode') === self::SOURCE_SELECTION) {
190 $this->setMode(self::SOURCE_SELECTION);
191
192 $this->ctrl->setParameterByClass(get_class($this->parent_obj), 'selectMode', self::SOURCE_SELECTION);
193 $this->setTarget($this->request_wrapper->retrieve("ref_id", $this->refinery->kindlyTo()->int()));
194 $this->ctrl->setReturnByClass(get_class($this->parent_obj), '');
195
196 ilLoggerFactory::getLogger('obj')->debug('Source selection mode. Target is: ' . $this->getFirstTarget());
197 } elseif ($this->retriever->getMaybeInt('selectMode') === self::TARGET_SELECTION) {
198 $this->setMode(self::TARGET_SELECTION);
199 $this->ctrl->setReturnByClass(get_class($this->parent_obj), '');
200 ilLoggerFactory::getLogger('obj')->debug('Target selection mode.');
201 }
202
203 // save targets
204 if ($this->retriever->has('target_ids')) {
205 $this->setTargets(explode('_', $this->retriever->getMaybeString('target_ids')));
206 ilLoggerFactory::getLogger('obj')->debug('targets are: ' . print_r($this->getTargets(), true));
207 }
208 }
209
210 protected function initTabs(): void
211 {
212 $this->lng->loadLanguageModule('cntr');
213 $this->tabs->clearTargets();
214 $this->tabs->setBackTarget(
215 $this->lng->txt('cancel'),
216 (string) $this->ctrl->getParentReturn($this->parent_obj)
217 );
218 }
219
220 protected function setTabs(int $tab_group, int $active_tab): void
221 {
222 if ($tab_group == self::TAB_GROUP_SC_SELECTION) {
223 if ($this->getSubMode() == self::SUBMODE_CONTENT_ONLY) {
224 if ($this->getMode() == self::SOURCE_SELECTION) {
225 $this->tabs->addTab(
226 (string) self::TAB_SELECTION_SOURCE_TREE,
227 $this->lng->txt('cntr_copy_repo_tree'),
228 $this->ctrl->getLinkTarget($this, 'initSourceSelection')
229 );
230 $this->tabs->addTab(
231 (string) self::TAB_SELECTION_MEMBERSHIP,
232 $this->lng->txt('cntr_copy_crs_grp'),
233 $this->ctrl->getLinkTarget($this, 'showSourceSelectionMembership')
234 );
235 }
236 }
237 }
238 $this->tabs->activateTab((string) $active_tab);
239 }
240
244 protected function adoptContent(): void
245 {
246 $this->ctrl->setParameter($this, 'smode', self::SUBMODE_CONTENT_ONLY);
247 $this->ctrl->setParameter($this, 'selectMode', self::SOURCE_SELECTION);
248
249 $this->setSubMode(self::SUBMODE_CONTENT_ONLY);
250 $this->setMode(self::SOURCE_SELECTION);
251 $this->setTarget($this->request_wrapper->retrieve("ref_id", $this->refinery->kindlyTo()->int()));
252
253 $this->initSourceSelection();
254 }
255
259 protected function initTargetSelection(): void
260 {
261 $this->ctrl->setParameter($this, 'selectMode', self::TARGET_SELECTION);
262
263 // copy opened nodes from repository explorer
264 $node_ids = is_array(ilSession::get('repexpand')) ? ilSession::get('repexpand') : [];
265
266 // begin-patch mc
267 $this->setTargets([]);
268 // cognos-blu-patch: end
269
270 // open current position
271 foreach ($this->getSources() as $source_id) {
272 if ($source_id) {
273 $path = $this->tree->getPathId($source_id);
274 foreach ($path as $node_id) {
275 if (!in_array($node_id, $node_ids)) {
276 $node_ids[] = $node_id;
277 }
278 }
279 }
280 }
281
282 ilSession::set('paste_copy_repexpand', $node_ids);
283
284 $this->ctrl->setReturnByClass(get_class($this->parent_obj), '');
286 }
287
288 protected function initSourceSelection(): void
289 {
290 // copy opened nodes from repository explorer
291 $node_ids = is_array(ilSession::get('repexpand')) ? ilSession::get('repexpand') : [];
292
293 $this->setTabs(self::TAB_GROUP_SC_SELECTION, self::TAB_SELECTION_SOURCE_TREE);
294
295 // open current position
296 // begin-patch mc
297 foreach ($this->getTargets() as $target_ref_id) {
298 $path = $this->tree->getPathId($target_ref_id);
299 foreach ($path as $node_id) {
300 if (!in_array($node_id, $node_ids)) {
301 $node_ids[] = $node_id;
302 }
303 }
304 }
305 // end-patch multi copy
306
307 ilSession::set('paste_copy_repexpand', $node_ids);
308
309 $this->ctrl->setReturnByClass(get_class($this->parent_obj), '');
311 }
312
313
317 protected function showSourceSelectionMembership(): void
318 {
319 $this->tpl->setOnScreenMessage('info', $this->lng->txt('msg_copy_clipboard_source'));
320 $this->setTabs(self::TAB_GROUP_SC_SELECTION, self::TAB_SELECTION_MEMBERSHIP);
321
323 $this,
324 'showSourceSelectionMembership',
325 'copy_selection_mmbrs'
326 );
327 $cgs->init();
328 $cgs->setObjects(
329 array_merge(
330 ilParticipants::_getMembershipByType($this->user->getId(), ['crs']),
331 ilParticipants::_getMembershipByType($this->user->getId(), ['grp'])
332 )
333 );
334 $cgs->parse();
335
336 $this->tpl->setContent($cgs->getHTML());
337 }
338
339 protected function showTargetSelectionTree(): void
340 {
341 if ($this->obj_definition->isContainer($this->getType())) {
342 $this->tpl->setOnScreenMessage('info', $this->lng->txt('msg_copy_clipboard_container'));
343 } else {
344 $this->tpl->setOnScreenMessage('info', $this->lng->txt('msg_copy_clipboard'));
345 }
346
347 $exp = new ilRepositorySelectorExplorerGUI($this, "showTargetSelectionTree");
348 $exp->setTypeWhiteList(["root", "cat", "grp", "crs", "fold", "lso", "prg"]);
349 $exp->setSelectMode("target", true);
350 if ($exp->handleCommand()) {
351 return;
352 }
353 $output = $exp->getHTML();
354
355 $t = new ilToolbarGUI();
356 $t->setFormAction($this->ctrl->getFormAction($this, "saveTarget"));
357 $primary_button = $this->ui_factory->button()->primary(
358 $this->getPrimaryButtonLabel(),
359 ''
360 )->withOnLoadCode($this->getOnLoadCode('saveTarget'));
361 $t->addComponent($primary_button);
362 $t->addSeparator();
363
364 $clipboard_btn = $this->ui_factory->button()->standard(
365 $this->lng->txt('obj_insert_into_clipboard'),
366 ''
367 )->withOnLoadCode($this->getOnLoadCode('keepObjectsInClipboard'));
368 $t->addComponent($clipboard_btn);
369
370 $cancel_btn = $this->ui_factory->button()->standard(
371 $this->lng->txt('cancel'),
372 ''
373 )->withOnLoadCode($this->getOnLoadCode('cancel'));
374 $t->addComponent($cancel_btn);
375
376 $t->setCloseFormTag(false);
377 $t->setLeadingImage(ilUtil::getImagePath("nav/arrow_upright.svg"), " ");
378 $output = $t->getHTML() . $output;
379 $t->setLeadingImage(ilUtil::getImagePath("nav/arrow_downright.svg"), " ");
380 $t->setCloseFormTag(true);
381 $t->setOpenFormTag(false);
382 $output .= "<br />" . $t->getHTML();
383
384 $this->tpl->setContent($output);
385 }
386
387 private function getPrimaryButtonLabel(): string
388 {
389 if ($this->obj_definition->isContainer($this->getType())) {
390 return $this->lng->txt('btn_next');
391 }
392
393 return $this->lng->txt('paste');
394 }
395
396 private function getOnLoadCode(string $cmd): Closure
397 {
398 return function ($id) use ($cmd) {
399 return "document.getElementById('$id')"
400 . '.addEventListener("click", '
401 . '(e) => {e.preventDefault();'
402 . 'e.target.setAttribute("name", "cmd[' . $cmd . ']");'
403 . 'e.target.form.requestSubmit(e.target);});';
404 };
405 }
406
407 protected function showSourceSelectionTree(): void
408 {
409 $this->tpl->addBlockFile(
410 'ADM_CONTENT',
411 'adm_content',
412 'tpl.paste_into_multiple_objects.html',
413 "components/ILIAS/ILIASObject"
414 );
415
416 $this->tpl->setOnScreenMessage('info', $this->lng->txt('msg_copy_clipboard_source'));
419 'ilias.php?baseClass=ilRepositoryGUI&amp;cmd=goto',
420 'paste_copy_repexpand'
421 );
422 $exp->setRequiredFormItemPermission('visible,read,copy');
423
424 $this->ctrl->setParameter($this, 'selectMode', self::SOURCE_SELECTION);
425 $exp->setExpandTarget($this->ctrl->getLinkTarget($this, 'showSourceSelectionTree'));
426 $exp->setTargetGet('ref_id');
427 $exp->setPostVar('source');
428 $exp->setCheckedItems($this->getSources());
429 $exp->highlightNode((string) $this->getFirstTarget());
430
431 // Filter to container
432 foreach (['cat', 'root', 'fold'] as $container) {
433 $exp->removeFormItemForType($container);
434 }
435
436 if (!$this->request_wrapper->has("paste_copy_repexpand")) {
437 $expanded = $this->tree->readRootId();
438 } else {
439 $expanded = $this->request_wrapper->retrieve("paste_copy_repexpand", $this->refinery->kindlyTo()->int());
440 }
441
442 $this->tpl->setVariable('FORM_TARGET', '_self');
443 $this->tpl->setVariable('FORM_ACTION', $this->ctrl->getFormAction($this, 'copySelection'));
444
445 $exp->setExpand($expanded);
446 // build html-output
447 $exp->setOutput(0);
448 $output = $exp->getOutput();
449
450 $this->tpl->setVariable('OBJECT_TREE', $output);
451 $this->tpl->setVariable('CMD_SUBMIT', 'saveSource');
452 $this->tpl->setVariable('TXT_SUBMIT', $this->lng->txt('btn_next'));
453 }
454
455 protected function saveTarget(): void
456 {
457 if (!$this->retriever->has('target')) {
458 $this->ctrl->setParameter($this, 'selectMode', self::TARGET_SELECTION);
459 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
461 return;
462 }
463
464 try {
465 $targets = $this->retriever->getArrayOfInt('target');
467 $possible_target = $this->retriever->getMaybeInt('target');
468 $targets = $possible_target === null ? [] : [$possible_target];
469 }
470
471 if ($targets !== []) {
472 $this->setTargets($targets);
473 $this->ctrl->setParameter($this, 'target_ids', implode('_', $this->getTargets()));
474 } elseif (($target = $this->retriever->getMaybeInt('target')) !== null) {
475 $this->setTarget($target);
476 $this->ctrl->setParameter($this, 'target_ids', implode('_', $this->getTargets()));
477 }
478
479 // validate allowed subtypes
480 foreach ($this->getSources() as $source_ref_id) {
481 foreach ($this->getTargets() as $target_ref_id) {
482 $target_type = ilObject::_lookupType((int) $target_ref_id, true);
483 $target_class_name = ilObjectFactory::getClassByType($target_type);
484 $target_object = new $target_class_name((int) $target_ref_id);
485 $possible_subtypes = $target_object->getPossibleSubObjects();
486
487 $source_type = ilObject::_lookupType((int) $source_ref_id, true);
488
489 if (!array_key_exists($source_type, (array) $possible_subtypes)) {
490 $this->tpl->setOnScreenMessage('failure', sprintf(
491 $this->lng->txt('msg_obj_may_not_contain_objects_of_type'),
492 $this->lng->txt('obj_' . $target_type),
493 $this->lng->txt('obj_' . $source_type)
494 ));
496 return;
497 }
498 }
499 }
500
501 if (count($this->getSources()) == 1 && $this->obj_definition->isContainer($this->getType())) {
502 // check, if object should be copied into itself
503 // begin-patch mc
504 $is_child = [];
505 foreach ($this->getTargets() as $target_ref_id) {
506 if ($this->tree->isGrandChild($this->getFirstSource(), (int) $target_ref_id)) {
508 }
509 if ($this->getFirstSource() == (int) $target_ref_id) {
511 }
512 }
513 // end-patch multi copy
514 if (count($is_child) > 0) {
515 $this->tpl->setOnScreenMessage(
516 'failure',
517 $this->lng->txt("msg_not_in_itself") . " " . implode(',', $is_child)
518 );
520 return;
521 }
522
523 $this->showItemSelection();
524 } else {
525 if (count($this->getSources()) == 1) {
526 $this->copySingleObject();
527 } else {
528 $this->copyMultipleNonContainer($this->getSources());
529 }
530 }
531 }
532
533 public function setMode(int $mode): void
534 {
535 $this->mode = $mode;
536 }
537
538 public function getMode(): int
539 {
540 return $this->mode;
541 }
542
543 public function setSubMode(int $mode): void
544 {
545 $this->sub_mode = $mode;
546 }
547
548 public function getSubMode(): int
549 {
550 return $this->sub_mode;
551 }
552
556 public function getParentObject(): ?ilObjectGUI
557 {
558 return $this->parent_obj;
559 }
560
561 public function getType(): string
562 {
563 return $this->type;
564 }
565
566 public function setType(string $type): void
567 {
568 $this->type = $type;
569 }
570
571 public function setSource(array $source_ids): void
572 {
573 $this->sources = $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int())->transform(
574 $source_ids
575 );
576 }
577
578 public function getSources(): array
579 {
580 return $this->sources;
581 }
582
583 public function getFirstSource(): int
584 {
585 if (count($this->sources)) {
586 return (int) $this->sources[0];
587 }
588 return 0;
589 }
590
591 // begin-patch mc
592 public function setTarget(int $ref_id): void
593 {
594 $this->setTargets([$ref_id]);
595 }
596
597 public function setTargets(array $targets): void
598 {
599 $this->targets = $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int())->transform(
600 $targets
601 );
602 }
603
604 public function getTargets(): array
605 {
606 return $this->targets;
607 }
608
609 public function getFirstTarget(): int
610 {
611 if (array_key_exists(0, $this->getTargets())) {
612 $targets = $this->getTargets();
613 return (int) $targets[0];
614 }
615 return 0;
616 }
617 // end-patch multi copy
618
619 protected function cancel(): void
620 {
621 $ilCtrl = $this->ctrl;
622 $ilCtrl->setReturnByClass(get_class($this->parent_obj), 'cancel');
623 $ilCtrl->returnToParent($this);
624 }
625
626 public function keepObjectsInClipboard(): void
627 {
628 $this->tpl->setOnScreenMessage('success', $this->lng->txt("obj_inserted_clipboard"), true);
629 $ilCtrl = $this->ctrl;
630 $this->clipboard->setCmd("copy");
631 $this->clipboard->setRefIds($this->getSources());
632 $ilCtrl->returnToParent($this);
633 }
634
635 protected function searchSource(): void
636 {
637 if ($this->post_wrapper->has('tit')) {
638 $this->tpl->setOnScreenMessage('info', $this->lng->txt('wizard_search_list'));
639 ilSession::set('source_query', $this->post_wrapper->retrieve("tit", $this->refinery->kindlyTo()->string()));
640 }
641
642 $this->initFormSearch();
643 $this->form->setValuesByPost();
644
645 if (!$this->form->checkInput()) {
646 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('msg_no_search_string'), true);
647 $this->ctrl->returnToParent($this);
648 return;
649 }
650
651 $tit = $this->form->getInput('tit');
652 if ($tit === "") {
653 $tit = ilSession::get('source_query', '');
654 }
655 $query_parser = new ilQueryParser($tit);
656 $query_parser->setMinWordLength(1);
657 $query_parser->setCombination(ilQueryParser::QP_COMBINATION_AND);
658 $query_parser->parse();
659 if (!$query_parser->validate()) {
660 $this->tpl->setOnScreenMessage('failure', $query_parser->getMessage(), true);
661 $this->ctrl->returnToParent($this);
662 }
663
664 // only like search since fulltext does not support search with less than 3 characters
665 $object_search = new ilLikeObjectSearch($query_parser);
666 $object_search->setFilter([$this->retriever->getMaybeString('new_type')]);
667 $res = $object_search->performSearch();
668 $res->setRequiredPermission('copy');
669 $res->filter(ROOT_FOLDER_ID, true);
670
671 if (!count($results = $res->getResultsByObjId())) {
672 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('search_no_match'), true);
673 $this->ctrl->returnToParent($this);
674 }
675
676 $table = new ilObjectCopySearchResultTableGUI($this, 'searchSource', $this->getType());
677 $table->setFormAction($this->ctrl->getFormAction($this));
678 $table->setSelectedReference($this->getFirstSource());
679 $table->parseSearchResults($results);
680 $this->tpl->setContent($table->getHTML());
681 }
682
683 protected function saveSource(): void
684 {
685 if (!$this->post_wrapper->has("source")) {
686 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
687 $this->searchSource();
688 return;
689 }
690
691 $source = $this->post_wrapper->retrieve("source", $this->refinery->kindlyTo()->int());
692 $this->setSource([$source]);
693 $this->setType(ilObject::_lookupType($source, true));
694 $this->ctrl->setParameter($this, 'source_id', $source);
695
696 foreach ($this->getSources() as $source_ref_id) {
697 if (($message = $this->getErrorMessageOnDisallowedObjectTypeForTarget($source_ref_id)) !== '') {
698 $this->tpl->setOnScreenMessage('failure', $message);
699 $this->searchSource();
700 return;
701 }
702 }
703
705 }
706
708 {
709 foreach ($this->getTargets() as $target_ref_id) {
710 $target_type = ilObject::_lookupType($target_ref_id, true);
711 $target_class_name = ilObjectFactory::getClassByType($target_type);
712 $target_object = new $target_class_name($target_ref_id);
713 $possible_subtypes = $target_object->getPossibleSubObjects();
714
715 $source_type = ilObject::_lookupType($ref_id, true);
716
717 if (!array_key_exists($source_type, $possible_subtypes)
718 && $this->getSubMode() != self::SUBMODE_CONTENT_ONLY
719 && ($source_type !== 'crs' || $target_type !== 'crs')
720 ) {
721 return sprintf(
722 $this->lng->txt('msg_obj_may_not_contain_objects_of_type'),
723 $this->lng->txt('obj_' . $target_type),
724 $this->lng->txt('obj_' . $source_type)
725 );
726 }
727 }
728
729 return '';
730 }
731
735 protected function saveSourceMembership(): void
736 {
737 $source = $this->retriever->getMaybeInt('source');
738 if ($source === null) {
739 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
740 $this->ctrl->redirect($this, 'showSourceSelectionMembership');
741 return;
742 }
743
744 $this->setSource([$source]);
745 $this->setType(ilObject::_lookupType($this->getFirstSource(), true));
746 $this->ctrl->setParameter($this, 'source_id', $source);
747
749 }
750
751 private function executeNextStepAfterSourceSelection(): void
752 {
753 if (!$this->obj_definition->isContainer($this->getType())) {
754 $this->copySingleObject();
755 return;
756 }
757
758 if (count($this->getSources()) === 1
760 'cont',
762 )
763 ) {
764 $this->showCopyPageSelection();
765 return;
766 }
767
768 $this->showItemSelection();
769 }
770
771 protected function showCopyPageSelection(): void
772 {
774 $this->tpl->setContent($this->ui_renderer->render($form));
775 }
776
777 protected function saveCopyPage(): void
778 {
780 $data = $form->withRequest($this->request)->getData();
781
782 $this->showItemSelection($data['copy_page']);
783 }
784
786 {
787 $form_action = $this->ctrl->getFormAction($this, 'saveCopyPage');
788
789 $input = [
790 'copy_page' => $this->ui_factory->input()->field()
791 ->radio(
792 $this->lng->txt('cntr_adopt_content')
793 )
794 ->withOption('1', $this->lng->txt('copy_container_page_yes_label'), $this->lng->txt('copy_container_page_yes_byline'))
795 ->withOption('0', $this->lng->txt('copy_container_page_no_label'))
796 ->withValue('1')
797 ->withAdditionalTransformation($this->refinery->kindlyTo()->bool())
798 ];
799
800 return $this->ui_factory->input()->container()->form()
801 ->standard($form_action, $input)
802 ->withSubmitLabel($this->lng->txt('next'));
803 }
804
805 protected function showItemSelection(bool $copy_page = false): void
806 {
807 if (!count($this->getSources())) {
808 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
809 $this->searchSource();
810 return;
811 }
812
813 $this->log->debug('Source(s): ' . print_r($this->getSources(), true));
814 $this->log->debug('Target(s): ' . print_r($this->getTargets(), true));
815
816 $this->tpl->setOnScreenMessage('info', $this->lng->txt($this->getType() . '_copy_threads_info'));
817 $this->tpl->addJavaScript('assets/js/ilContainer.js');
818 $this->tpl->setVariable('BODY_ATTRIBUTES', 'onload="ilDisableChilds(\'cmd\');"');
819
820 $table = new ilObjectCopySelectionTableGUI($this, 'showItemSelection', $this->getType(), $copy_page);
821 $table->parseSource($this->getFirstSource());
822
823 $this->tpl->setContent($table->getHTML());
824 }
825
829 protected function copySingleObject(): void
830 {
831 // Source defined
832 if ($this->getSources() === []) {
833 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'), true);
834 $this->ctrl->returnToParent($this);
835 }
836
837 $this->copyMultipleNonContainer($this->getSources());
838 }
839
845 public function copyMultipleNonContainer(array $sources): void
846 {
847 // check permissions
848 foreach ($sources as $source_ref_id) {
849 $source_type = ilObject::_lookupType($source_ref_id, true);
850
851 // Create permission
852 // begin-patch mc
853 foreach ($this->getTargets() as $target_ref_id) {
854 if (!$this->rbacsystem->checkAccess('create', $target_ref_id, $source_type)) {
855 $this->log->notice(
856 'Permission denied for target_id: ' .
857 $target_ref_id .
858 ' source_type: ' .
859 $source_type .
860 ' CREATE'
861 );
862 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('permission_denied'), true);
863 $this->ctrl->returnToParent($this);
864 }
865 }
866
867 // Copy permission
868 if (!$this->access->checkAccess('copy', '', $source_ref_id)) {
869 $this->log->notice('Permission denied for source_ref_id: ' . $source_ref_id . ' COPY');
870 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('permission_denied'), true);
871 $this->ctrl->returnToParent($this);
872 }
873
874 // check that these objects are really not containers
875 if ($this->obj_definition->isContainer($source_type) and $this->getSubMode() != self::SUBMODE_CONTENT_ONLY) {
876 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('cntr_container_only_on_their_own'), true);
877 $this->ctrl->returnToParent($this);
878 }
879 }
880
881 reset($sources);
882
883
884 ilLoggerFactory::getLogger('obj')->debug('Copy multiple non containers. Sources: ' . print_r($sources, true));
885
886 $new_obj = null;
887 // clone
888 foreach ($sources as $source_ref_id) {
889 ilLoggerFactory::getLogger('obj')->debug('Copying source ref_id : ' . $source_ref_id);
890
891 // begin-patch mc
892 foreach ($this->getTargets() as $target_ref_id) {
893 // Save wizard options
895 $wizard_options = ilCopyWizardOptions::_getInstance($copy_id);
896 $wizard_options->saveOwner($this->user->getId());
897 $wizard_options->saveRoot((int) $source_ref_id);
898 $wizard_options->read();
899
900 $orig = ilObjectFactory::getInstanceByRefId((int) $source_ref_id);
901 $new_obj = $orig->cloneObject($target_ref_id, $copy_id);
902
903 // Delete wizard options
904 $wizard_options->deleteAll();
905 $this->parent_obj->callCreationCallback(
906 $new_obj,
907 $this->obj_definition,
908 $this->retriever->getMaybeInt('crtcb', 0)
909 );
910
911 // rbac log
912 if (ilRbacLog::isActive()) {
913 $rbac_log_roles = $this->rbacreview->getParentRoleIds($new_obj->getRefId());
914 $rbac_log = ilRbacLog::gatherFaPa($new_obj->getRefId(), array_keys($rbac_log_roles), true);
915 ilRbacLog::add(ilRbacLog::COPY_OBJECT, $new_obj->getRefId(), $rbac_log, (bool) $source_ref_id);
916 }
917 }
918 }
919
920 $this->clipboard->clear();
921 $this->log->info('Object copy completed.');
922 if (count($sources) == 1) {
923 $this->tpl->setOnScreenMessage('success', $this->lng->txt("object_duplicated"), true);
924 $ref_id = $new_obj->getRefId();
925 } else {
926 $this->tpl->setOnScreenMessage('success', $this->lng->txt("objects_duplicated"), true);
927 $ref_id = $this->getFirstTarget();
928 }
929
930 $this->tpl->setOnScreenMessage('success', $this->lng->txt("objects_duplicated"), true);
931 ilUtil::redirect(ilLink::_getLink($ref_id));
932 }
933
934 protected function copyContainerToTargets(): void
935 {
936 $this->log->debug('Copy container to targets: ' . print_r($_REQUEST, true));
937 $this->log->debug('Source(s): ' . print_r($this->getSources(), true));
938 $this->log->debug('Target(s): ' . print_r($this->getTargets(), true));
939
940 if ($this->isCopyingParentPageNeeded()) {
941 $this->copyParentPage();
942 }
943
944 $result = 1;
945 foreach ($this->getTargets() as $target_ref_id) {
946 $result = $this->copyContainer((int) $target_ref_id);
947 }
948
949 $this->clipboard->clear();
950
951 if (ilCopyWizardOptions::_isFinished($result['copy_id'])) {
952 $this->log->info('Object copy completed.');
953 $this->tpl->setOnScreenMessage('success', $this->lng->txt("object_duplicated"), true);
954 if ($this->getSubMode() == self::SUBMODE_CONTENT_ONLY) {
955 $this->ctrl->returnToParent($this);
956 }
957 $link = ilLink::_getLink($result['ref_id']);
958 $this->ctrl->redirectToURL($link);
959 } else {
960 $this->log->debug('Object copy in progress.');
961 $this->showCopyProgress();
962 }
963 }
964
965 private function isCopyingParentPageNeeded(): bool
966 {
967 return $this->post_wrapper->has('copy_page')
968 && $this->post_wrapper->retrieve('copy_page', $this->refinery->kindlyTo()->bool());
969 }
970
971 private function copyParentPage(): void
972 {
973 $source_object = ilObjectFactory::getInstanceByRefId($this->getFirstSource());
974 $target_object = $this->getParentObject()->getObject();
976 "cont",
977 $source_object->getId()
978 )) {
979 $orig_page = new ilContainerPage($source_object->getId());
980 $orig_page->copy($target_object->getId(), "cont", $target_object->getId());
981 }
982
983 $style_id = ilObjStyleSheet::lookupObjectStyle($source_object->getId());
984 if ($style_id <= 0) {
985 return;
986 }
987 if (ilObjStyleSheet::_lookupStandard($style_id)) {
988 ilObjStyleSheet::writeStyleUsage($target_object->getId(), $style_id);
989 return;
990 }
991 $style_obj = ilObjectFactory::getInstanceByObjId($style_id);
992 $new_id = $style_obj->ilClone();
993 ilObjStyleSheet::writeStyleUsage($target_object->getId(), $new_id);
994 ilObjStyleSheet::writeOwner($target_object->getId(), $new_id);
995 $reuse = $this->container_repo->readReuse($source_object->getRefId());
996 $this->container_repo->updateReuse($target_object->getRefId(), $reuse);
997 }
998
999 protected function showCopyProgress(): void
1000 {
1002 if ($this->request_wrapper->has('ref_id')) {
1003 $ref_id = $this->request_wrapper->retrieve(
1004 'ref_id',
1005 $this->refinery->kindlyTo()->int()
1006 );
1007 }
1008
1009 $this->tabs->setBackTarget(
1010 $this->lng->txt('tab_back_to_repository'),
1011 (string) $this->ctrl->getParentReturn($this->parent_obj)
1012 );
1013
1014 $progress = new ilObjectCopyProgressTableGUI(
1015 new DataFactory(),
1016 $this->ui_renderer,
1017 $this->ui_factory,
1018 $this,
1019 'showCopyProgress',
1020 $ref_id
1021 );
1022 $progress->setObjectInfo($this->targets_copy_id);
1023 $progress->parse();
1024 $progress->init();
1025 $link = ilLink::_getLink($ref_id);
1026 $progress->setRedirectionUrl($link);
1027
1028 $this->tpl->setContent($progress->getHTML());
1029 }
1030
1031 protected function updateProgress(): void
1032 {
1033 $max_steps = $this->retriever->getMaybeInt('_max_steps');
1034 $copy_id = $this->retriever->getMaybeInt('_copy_id');
1036 $required_steps = $options->getRequiredSteps();
1037
1038 if ($required_steps === 0) {
1039 $state = $this->ui_factory->progress()->state()->bar()
1040 ->success($this->lng->txt('obj_copy_progress_success'));
1041 $this->log->debug('Update copy progress: 100%');
1042 } else {
1043 $completed_steps = $max_steps - $required_steps;
1044 $percentage = (int) min(
1045 floor(($completed_steps / $max_steps) * 100),
1046 99
1047 );
1048 $state = $this->ui_factory->progress()->state()->bar()
1049 ->determinate($percentage);
1050 $this->log->debug("Update copy progress: {$percentage}%");
1051 }
1052
1053 $html = $this->ui_renderer->renderAsync($state);
1054
1055 $this->http->saveResponse(
1056 $this->http->response()
1057 ->withHeader('Content-Type', 'text/html; charset=utf-8')
1058 ->withBody(Streams::ofString($html))
1059 );
1060 $this->http->sendResponse();
1061 $this->http->close();
1062 }
1063
1064 protected function copyContainer(int $target_ref_id): array
1065 {
1066 if ($this->getSubMode() != self::SUBMODE_CONTENT_ONLY) {
1067 if (!$this->rbacsystem->checkAccess('create', $target_ref_id, $this->getType())) {
1068 $this->log->notice(
1069 'Permission denied for target: ' .
1070 $target_ref_id .
1071 ' type: ' .
1072 $this->getType() .
1073 ' CREATE'
1074 );
1075 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('permission_denied'), true);
1076 $this->ctrl->returnToParent($this);
1077 }
1078 }
1079
1080 if (!$this->getFirstSource()) {
1081 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'), true);
1082 $this->ctrl->returnToParent($this);
1083 }
1084
1085 $options = [];
1086 if ($this->post_wrapper->has("cp_options")) {
1087 $options = $this->post_wrapper->retrieve(
1088 "cp_options",
1089 $this->refinery->kindlyTo()->dictOf(
1090 $this->refinery->kindlyTo()->dictOf($this->refinery->kindlyTo()->string())
1091 )
1092 );
1093 }
1094
1095 $this->log->debug('Copy container (sources): ' . print_r($this->getSources(), true));
1096
1098 $result = $orig->cloneAllObject(
1099 $_COOKIE[session_name()],
1100 CLIENT_ID,
1101 $this->getType(),
1102 $target_ref_id,
1103 $this->getFirstSource(),
1104 $options,
1105 false,
1106 $this->getSubMode()
1107 );
1108
1109 $this->targets_copy_id[$target_ref_id] = $result['copy_id'];
1110
1111 $new_ref_id = (int) $result['ref_id'];
1112 if ($new_ref_id > 0) {
1113 $new_obj = ilObjectFactory::getInstanceByRefId((int) $result['ref_id'], false);
1114 if ($new_obj instanceof ilObject) {
1115 $this->parent_obj->callCreationCallback(
1116 $new_obj,
1117 $this->obj_definition,
1118 $this->retriever->getMaybeInt('crtcb', 0)
1119 );
1120 }
1121 }
1122 return $result;
1123 }
1124
1131 public function showSourceSearch(?string $tpl_var): ?ilPropertyFormGUI
1132 {
1133 $this->unsetSession();
1134 $this->initFormSearch();
1135
1136 if ($tpl_var) {
1137 $this->tpl->setVariable($tpl_var, $this->form->getHTML());
1138 return null;
1139 }
1140
1141 return $this->form;
1142 }
1143
1144 protected function initFormSearch(): void
1145 {
1146 $this->form = new ilPropertyFormGUI();
1147 $this->form->setTableWidth('600px');
1148 $this->ctrl->setParameter($this, 'new_type', $this->getType());
1149 $this->form->setFormAction($this->ctrl->getFormAction($this));
1150 $this->form->setTitle($this->lng->txt($this->getType() . '_copy'));
1151 $this->form->addCommandButton('searchSource', $this->lng->txt('search_for'));
1152 $this->form->addCommandButton('cancel', $this->lng->txt('cancel'));
1153
1154 $tit = new ilTextInputGUI($this->lng->txt('title'), 'tit');
1155 $tit->setSize(40);
1156 $tit->setMaxLength(70);
1157 $tit->setRequired(true);
1158 $tit->setInfo($this->lng->txt('wizard_title_info'));
1159 $this->form->addItem($tit);
1160 }
1161
1165 protected function unsetSession(): void
1166 {
1167 ilSession::clear('source_query');
1168 $this->setSource([]);
1169 }
1170}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
Builds a Color from either hex- or rgb values.
Definition: Factory.php:31
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
Manages items in repository clipboard.
This repo stores infos on repository objects that are using booking managers as a service (resource m...
error(string $a_errmsg)
Container page object.
static _allocateCopyId()
Allocate a copy for further entries.
static _isFinished(int $a_copy_id)
static _getInstance(int $a_copy_id)
Class ilCtrl provides processing control methods.
setReturnByClass(string $a_class, ?string $a_cmd=null)
@inheritDoc
returnToParent(object $a_gui_obj, ?string $a_anchor=null)
@inheritDoc
Error Handling & global info handling.
language handling
static getLogger(string $a_component_id)
Get component logger.
Component logger with individual log levels by component id.
static _lookupStandard(int $a_id)
Lookup standard flag.
static writeStyleUsage(int $a_obj_id, int $a_style_id)
Write style usage.
static writeOwner($obj_id, $style_id)
static lookupObjectStyle(int $a_obj_id)
Lookup object style.
User class.
GUI class for the workflow of copying objects.
ilPropertyFormGUI $form
unsetSession()
Unset session variables.
ServerRequestInterface $request
copyMultipleNonContainer(array $sources)
Copy multiple non container.
ContainerDBRepository $container_repo
ilErrorHandling $error
setTabs(int $tab_group, int $active_tab)
ilObjectDefinition $obj_definition
initTargetSelection()
Init copy from repository/search list commands.
ilObjectRequestRetriever $retriever
setSource(array $source_ids)
ilObjectDataCache $obj_data_cache
getParentObject()
Get parent gui object.
copySingleObject()
Start cloning a single (not container) object.
ilGlobalTemplateInterface $tpl
saveSourceMembership()
Save selected source from membership screen.
ClipboardManager $clipboard
ImplementsCreationCallback $parent_obj
copyContainer(int $target_ref_id)
getErrorMessageOnDisallowedObjectTypeForTarget(int $ref_id)
ArrayBasedRequestWrapper $post_wrapper
GlobalHttpState $http
ilAccessHandler $access
showSourceSearch(?string $tpl_var)
Show init screen Normally shown below the create and import form when creating a new object.
adoptContent()
Adopt content (crs in crs, grp in grp, crs in grp or grp in crs)
showSourceSelectionMembership()
show target selection membership
showItemSelection(bool $copy_page=false)
setTargets(array $targets)
RequestWrapper $request_wrapper
class ilObjectDataCache
parses the objects.xml it handles the xml-description of all ilias objects
static getClassByType(string $obj_type)
static getInstanceByRefId(int $ref_id, bool $stop_on_error=true)
get an instance of an Ilias object by reference id
static getInstanceByObjId(?int $obj_id, bool $stop_on_error=true)
get an instance of an Ilias object by object id
Class ilObjectGUI Basic methods of all Output classes.
Base class for all sub item list gui's.
Class ilObject Basic functions for all objects.
static _lookupType(int $id, bool $reference=false)
static _lookupObjId(int $ref_id)
static _lookupTitle(int $obj_id)
static _exists(string $a_parent_type, int $a_id, string $a_lang="", bool $a_no_cache=false)
Checks whether page exists.
static _getMembershipByType(int $a_usr_id, array $a_type, bool $a_only_member_role=false)
get membership by type Get course or group membership
ilPasteIntoMultipleItemsExplorer Explorer
This class represents a property form user interface.
const COPY_OBJECT
static add(int $action, int $ref_id, array $diff, bool $source_ref_id=false)
static gatherFaPa(int $ref_id, array $role_ids, bool $add_action=false)
static isActive()
class ilRbacReview Contains Review functions of core Rbac.
class ilRbacSystem system function like checkAccess, addActiveRole ... Supporting system functions ar...
Explorer for selecting repository items.
static get(string $a_var)
static clear(string $a_var)
static set(string $a_var, $a_val)
Set a value.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This class represents a text property in a property form.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco...
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
static redirect(string $a_script)
const CLIENT_ID
Definition: constants.php:41
const ROOT_FOLDER_ID
Definition: constants.php:32
Interface GlobalHttpState.
Interface RequestWrapper.
This describes a standard form.
Definition: Standard.php:30
An entity that renders components to a string output.
Definition: Renderer.php:31
Interface ilAccessHandler This interface combines all available interfaces which can be called via gl...
$ref_id
Definition: ltiauth.php:66
$path
Definition: ltiservices.php:30
$res
Definition: ltiservices.php:69
static http()
Fetches the global http state from ILIAS.
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
form(?array $class_path, string $cmd, string $submit_caption="")
$results
global $DIC
Definition: shib_login.php:26
$container
@noRector
Definition: wac.php:37
$_COOKIE[session_name()]
Definition: xapitoken.php:52