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