ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
class.ilObjectCopyGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
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;
76 
78 
81 
82  protected int $mode = 0;
83  protected int $sub_mode = self::SUBMODE_COMPLETE;
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['ilUser'];
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), '');
280  $this->showTargetSelectionTree();
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), '');
305  $this->showSourceSelectionTree();
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'));
455  $this->showTargetSelectionTree();
456  return;
457  }
458 
459  try {
460  $targets = $this->retriever->getArrayOfInt('target');
461  } catch (ConstraintViolationException $e) {
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  ));
490  $this->showTargetSelectionTree();
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  );
514  $this->showTargetSelectionTree();
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  {
768  $form = $this->buildCopyPageSelectionForm();
769  $this->tpl->setContent($this->ui_renderer->render($form));
770  }
771 
772  protected function saveCopyPage(): void
773  {
774  $form = $this->buildCopyPageSelectionForm();
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 }
ContainerDBRepository $container_repo
static get(string $a_var)
$res
Definition: ltiservices.php:66
RequestWrapper $request_wrapper
ilErrorHandling $error
adoptContent()
Adopt content (crs in crs, grp in grp, crs in grp or grp in crs)
static getLogger(string $a_component_id)
Get component logger.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
showSourceSearch(?string $tpl_var)
Show init screen Normally shown below the create and import form when creating a new object...
GUI class for the workflow of copying objects.
const ROOT_FOLDER_ID
Definition: constants.php:32
initTargetSelection()
Init copy from repository/search list commands.
ilAccessHandler $access
ilObjectDefinition $obj_definition
This repo stores infos on repository objects that are using booking managers as a service (resource m...
saveSourceMembership()
Save selected source from membership screen.
static isActive()
setTabs(int $tab_group, int $active_tab)
ilPasteIntoMultipleItemsExplorer Explorer
$path
Definition: ltiservices.php:29
$container
Definition: wac.php:36
static _lookupObjId(int $ref_id)
static writeOwner($obj_id, $style_id)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
static gatherFaPa(int $ref_id, array $role_ids, bool $add_action=false)
showItemSelection(bool $copy_page=false)
getParentObject()
Get parent gui object.
$ref_id
Definition: ltiauth.php:65
setReturnByClass(string $a_class, ?string $a_cmd=null)
static _lookupTitle(int $obj_id)
ilGlobalTemplateInterface $tpl
Container page object.
static _exists(string $a_parent_type, int $a_id, string $a_lang="", bool $a_no_cache=false)
Checks whether page exists.
Class ilObjectGUI Basic methods of all Output classes.
ImplementsCreationCallback $parent_obj
const CLIENT_ID
Definition: constants.php:41
static getInstanceByRefId(int $ref_id, bool $stop_on_error=true)
get an instance of an Ilias object by reference id
static _isFinished(int $a_copy_id)
global $DIC
Definition: shib_login.php:26
static _lookupStandard(int $a_id)
Lookup standard flag.
unsetSession()
Unset session variables.
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
const COPY_OBJECT
static _allocateCopyId()
Allocate a copy for further entries.
copySingleObject()
Start cloning a single (not container) object.
Manages items in repository clipboard.
$results
withValue($value)
Get an input like this with another value displayed on the client side.
Definition: Group.php:61
This describes a standard form.
Definition: Standard.php:28
Base class for all sub item list gui&#39;s.
exit
static redirect(string $a_script)
static getClassByType(string $obj_type)
ilObjectRequestRetriever $retriever
static add(int $action, int $ref_id, array $diff, bool $source_ref_id=false)
static getInstanceByObjId(?int $obj_id, bool $stop_on_error=true)
get an instance of an Ilias object by object id
form( $class_path, string $cmd, string $submit_caption="")
static writeStyleUsage(int $a_obj_id, int $a_style_id)
Write style usage.
ilObjectDataCache $obj_data_cache
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
__construct(Container $dic, ilPlugin $plugin)
ClipboardManager $clipboard
copyMultipleNonContainer(array $sources)
Copy multiple non container.
getErrorMessageOnDisallowedObjectTypeForTarget(int $ref_id)
static lookupObjectStyle(int $a_obj_id)
Lookup object style.
setSource(array $source_ids)
copyContainer(int $target_ref_id)
$message
Definition: xapiexit.php:31
static _getInstance(int $a_copy_id)
copy(int $a_id, string $a_parent_type="", int $a_new_parent_id=0, bool $a_clone_mobs=false, int $obj_copy_id=0, bool $overwrite_existing=true)
Copy page.
ArrayBasedRequestWrapper $post_wrapper
returnToParent(object $a_gui_obj, ?string $a_anchor=null)
static _getMembershipByType(int $a_usr_id, array $a_type, bool $a_only_member_role=false)
get membership by type Get course or group membership
$_COOKIE[session_name()]
Definition: xapitoken.php:54
static _lookupType(int $id, bool $reference=false)
showSourceSelectionMembership()
show target selection membership
ilPropertyFormGUI $form
static clear(string $a_var)
static set(string $a_var, $a_val)
Set a value.
ServerRequestInterface $request
setTargets(array $targets)