ILIAS  release_9 Revision v9.13-25-g2c18ec4c24f
class.ilObjStudyProgrammeTreeGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
29 {
33  protected string $modal_id;
35 
39  protected int $ref_id;
42 
43  public function __construct(
44  protected ilGlobalTemplateInterface $tpl,
45  protected ilCtrl $ctrl,
46  protected ilAccess $access,
47  protected ilToolbarGUI $toolbar,
48  protected ilLanguage $lng,
49  protected ilComponentLogger $log,
50  protected ILIAS $ilias,
51  protected ilSetting $ilSetting,
52  protected ilTree $ilTree,
53  protected ilRbacAdmin $rbacadmin,
54  protected ILIAS\HTTP\Wrapper\WrapperFactory $http_wrapper,
55  protected ILIAS\Refinery\Factory $refinery,
56  protected ILIAS\UI\Factory $ui_factory
57  ) {
58  $this->modal_id = "tree_modal";
59  $this->async_output_handler = new ilAsyncOutputHandler();
60  $this->lng->loadLanguageModule("prg");
61  }
62 
63  public function setRefId(int $ref_id): void
64  {
65  $this->ref_id = $ref_id;
66  }
67 
72  protected function initTree(): void
73  {
74  $this->tree = new ilObjStudyProgrammeTreeExplorerGUI($this->ref_id, $this->modal_id, "prg_tree", $this, 'view');
75 
76  $js_url = rawurldecode($this->ctrl->getLinkTarget($this, 'saveTreeOrder', '', true));
77  $this->tree->addJsConf('save_tree_url', $js_url);
78  $this->tree->addJsConf('save_button_id', 'save_order_button');
79  $this->tree->addJsConf('cancel_button_id', 'cancel_order_button');
80  }
81 
88  public function executeCommand(): void
89  {
90  $this->initTree();
91  $cmd = $this->ctrl->getCmd();
92 
93  $this->getToolbar();
94 
95  if ($cmd === "" || $cmd === null) {
96  $cmd = "view";
97  }
98 
99  // handles tree commands ("openNode", "closeNode", "getNodeAsync")
100  if ($this->tree->handleCommand()) {
101  exit();
102  }
103 
104  switch ($cmd) {
105  case "view":
106  case "create":
107  case "save":
108  case "cancel":
109  case "delete":
110  case "confirmedDelete":
111  case "cancelDelete":
112  case "getContainerSelectionExplorer":
113  case "saveTreeOrder":
114  case "createNewLeaf":
115 
116  $content = $this->$cmd();
117  break;
118  default:
119  throw new ilException("ilObjStudyProgrammeTreeGUI: " .
120  "Command not supported: $cmd");
121  }
122 
124  }
125 
129  protected function view(): string
130  {
131  $output = $this->tree->getHTML();
132  $output .= $this->initAsyncUIElements();
133 
134  return $output;
135  }
136 
140  protected function cancel(): string
141  {
143  }
144 
151  protected function saveTreeOrder(): string
152  {
153  $this->checkAccessOrFail('write');
154 
155  $tree = "";
156  if ($this->http_wrapper->post()->has("tree")) {
157  $tree = $this->http_wrapper->post()->retrieve("tree", $this->refinery->kindlyTo()->string());
158  }
159  $treeAsJson = ilUtil::stripSlashes($tree);
160  $treeData = json_decode($treeAsJson, false, 512, JSON_THROW_ON_ERROR);
161 
162  if (!is_array($treeData) || [] === $treeData) {
163  throw new ilStudyProgrammeTreeException("There is no tree data to save!");
164  }
165 
166  // saves order recursive
167  $this->storeTreeOrder($treeData);
168 
170  ['success' => true, 'message' => $this->lng->txt('prg_saved_order_successful')]
171  );
172  }
173 
177  protected function storeTreeOrder(
178  array $nodes,
179  ilContainerSorting $container_sorting = null,
180  int $parent_ref_id = null
181  ): void {
182  $sorting_position = array();
183  $position_count = 10;
184 
185  $ref_id = $parent_ref_id;
186  if (is_null($ref_id)) {
187  $ref_id = $this->ref_id;
188  }
189 
191  $parent_node = ilObjectFactoryWrapper::singleton()->getInstanceByRefId($ref_id);
192 
193  if (is_null($container_sorting)) {
194  $container_sorting = ilContainerSorting::_getInstance(ilObject::_lookupObjectId($this->ref_id));
195  }
196 
197  foreach ($nodes as $node) {
198  // get ref_id from json
199  $id = $node->id;
200  $id = substr($id, strrpos($id, "_") + 1);
201 
202  $sorting_position[$id] = $position_count;
203  $position_count += 10;
204 
205  $node_obj = ilObjectFactoryWrapper::singleton()->getInstanceByRefId((int) $id);
206  if ($node_obj instanceof ilObjStudyProgramme) {
207  $node_obj->moveTo($parent_node);
208  } else {
209  // TODO: implement a method on ilObjStudyProgramme to move leafs
210  $this->ilTree->moveTree($node_obj->getRefId(), $parent_node->getRefId());
211  $this->rbacadmin->adjustMovedObjectPermissions($node_obj->getRefId(), $parent_node->getRefId());
212  }
213 
214  // recursion if there are children
215  if (isset($node->children)) {
216  $this->storeTreeOrder(
217  $node->children,
219  (int) $id
220  );
221  }
222  }
223  $container_sorting->savePost($sorting_position);
224  }
225 
232  protected function createNewLeaf(): string
233  {
234  $this->checkAccessOrFail('create', $this->http_wrapper->post()->retrieve("parent_id", $this->refinery->kindlyTo()->int()));
235 
236  if (
237  $this->http_wrapper->post()->has("target_id") &&
238  $this->http_wrapper->post()->has("type") &&
239  $this->http_wrapper->post()->has("parent_id")
240  ) {
241  $target_id = $this->http_wrapper->post()->retrieve("target_id", $this->refinery->kindlyTo()->int());
242  $parent_id = $this->http_wrapper->post()->retrieve("parent_id", $this->refinery->kindlyTo()->int());
243 
244  // TODO: more generic way for implementing different type of leafs
245  $course_ref = new ilObjCourseReference();
246  $course_ref->setTitleType(ilContainerReference::TITLE_TYPE_REUSE);
247  $course_ref->setTargetRefId($target_id);
248 
249  $course_ref->create();
250  $course_ref->createReference();
251 
252  $course_ref->putInTree($parent_id);
253 
254  // This is how it's done in ILIAS. If you set the target ID before the creation, it won't work
255  $course_ref->setTargetId(ilObject::_lookupObjectId($target_id));
256  $course_ref->update();
257  }
258 
260  ['success' => true, 'message' => $this->lng->txt('prg_added_course_ref_successful')]
261  );
262  }
263 
264 
271  protected function getContainerSelectionExplorer(bool $convert_to_string = true)
272  {
273  $create_leaf_form = new ilAsyncContainerSelectionExplorer(
274  rawurldecode($this->ctrl->getLinkTarget($this, 'createNewLeaf', '', true)),
275  $this->refinery,
276  $this->http_wrapper->query()
277  );
278  $create_leaf_form->setId("select_course_explorer");
279 
280  $ref_expand = ROOT_FOLDER_ID;
281  if ($this->http_wrapper->query()->has("ref_repexpand")) {
282  $ref_expand = $this->http_wrapper->query()->retrieve("ref_repexpand", $this->refinery->kindlyTo()->int());
283  }
284 
285  $create_leaf_form->setExpand($ref_expand);
286  $create_leaf_form->setExpandTarget($this->ctrl->getLinkTarget($this, 'getContainerSelectionExplorer'));
287  $create_leaf_form->setAsynchExpanding(true);
288  $create_leaf_form->setTargetGet('target_id');
289  $create_leaf_form->setFrameTarget("_self");
290  $create_leaf_form->setClickable('crs', true);
291  $create_leaf_form->setTargetType('crs');
292  $create_leaf_form->setOutput(0);
293 
294  if ($convert_to_string) {
295  return $create_leaf_form->getOutput();
296  }
297 
298  return $create_leaf_form;
299  }
300 
305  {
306  $tmp_obj = new ilObjStudyProgrammeGUI();
307 
308  $create_node_form = $tmp_obj->getAsyncCreationForm();
309  $create_node_form->setTitle("");
310  $this->ctrl->setParameterByClass("ilobjstudyprogrammegui", "new_type", "prg");
311  $create_node_form->setFormAction($this->ctrl->getFormActionByClass("ilobjstudyprogrammegui", "save"));
312 
313  return $create_node_form;
314  }
315 
322  protected function create(): void
323  {
324  $parent_id = null;
325  if ($this->http_wrapper->query()->has("ref_id")) {
326  $parent_id = $this->http_wrapper->query()->retrieve("ref_id", $this->refinery->kindlyTo()->int());
327  }
328  $this->checkAccessOrFail('create', $parent_id);
329 
330  $parent = ilObjectFactoryWrapper::singleton()->getInstanceByRefId($parent_id);// TODO PHP8-REVIEW `$parent_id` is NULL, an `int` is expected
331  $accordion = new ilAccordionGUI();
332 
333  $added_slides = 0;
334  $content = "";
335  if ($parent instanceof ilObjStudyProgramme) {
336  // only allow adding new StudyProgramme-Node if there are no lp-children
337  if (!$parent->hasLPChildren()) {
338  $content_new_node = $this->getCreationForm()->getHTML();
339  $accordion->addItem($this->lng->txt('prg_create_new_node'), $content_new_node);
340  $added_slides++;
341  }
342 
343  /* only allow adding new LP-Children if there are no other StudyProgrammes
344  * AND creating crs references is activated in administration
345  */
346  if (!$parent->hasChildren() && $this->ilSetting->get("obj_dis_creation_crsr") === "") {
347  $content_new_leaf = ilUtil::getSystemMessageHTML(
348  $this->lng->txt('prg_please_select_a_course_for_creating_a_leaf')
349  );
350  $content_new_leaf .= $this->getContainerSelectionExplorer();
351 
352  $accordion->addItem($this->lng->txt('prg_create_new_leaf'), $content_new_leaf);
353  $added_slides++;
354  }
355 
356  if ($added_slides === 1) {
357  $accordion->setBehaviour(ilAccordionGUI::FIRST_OPEN);
358  }
359 
360  $content = $accordion->getHTML(true);
361  }
362 
363  // creating modal window output
364  $this->async_output_handler->setHeading($this->lng->txt("prg_async_" . $this->ctrl->getCmd()));
365  $this->async_output_handler->setContent($content);
366  $this->async_output_handler->terminate();
367  }
368 
374  protected function delete(): void
375  {
376  $this->checkAccessOrFail("delete");
377 
378  if (!$this->http_wrapper->query()->has("ref_id") || !$this->http_wrapper->query()->has("item_ref_id")) {
379  throw new ilException("Nothing to delete!");
380  }
381 
382  $element_ref_id = $this->http_wrapper->query()->retrieve("ref_id", $this->refinery->kindlyTo()->int());
383 
384  $cgui = new ilConfirmationGUI();
385 
386  $msg = $this->lng->txt("info_delete_sure");
387  if (!$this->ilSetting->get('enable_trash')) {
388  $msg .= "<br/>" . $this->lng->txt("info_delete_warning_no_trash");
389  }
390  $cgui->setHeaderText($msg);
391  $cgui->setFormAction($this->ctrl->getFormAction($this, 'confirmedDelete', '', true));
392  $cgui->setCancel($this->lng->txt("cancel"), "cancelDelete");
393  $cgui->setConfirm($this->lng->txt("confirm"), "confirmedDelete");
394  $cgui->setFormName('async_form');
395 
396  $obj_id = ilObject::_lookupObjectId((int) $element_ref_id);
397  $type = ilObject::_lookupType($obj_id);
398  $title = call_user_func(array(ilObjectFactory::getClassByType($type),'_lookupTitle'), $obj_id);
399  $alt = $this->lng->txt("icon") . " " . $this->lng->txt("obj_" . $type);
400 
401  $cgui->addItem(
402  "id[]",
403  (string)$element_ref_id,
404  $title,
405  ilObject::_getIcon($obj_id, "small", $type),
406  $alt
407  );
408  $cgui->addHiddenItem(
409  'item_ref_id',
410  $this->http_wrapper->query()->retrieve("item_ref_id", $this->refinery->kindlyTo()->string())
411  );
412 
413  $content = $cgui->getHTML();
414 
415  // creating the modal window output
416  $this->async_output_handler->setHeading($msg);
417  $this->async_output_handler->setContent($content);
418  $this->async_output_handler->terminate();
419  }
420 
426  protected function confirmedDelete(): string
427  {
428  $this->checkAccessOrFail("delete");
429 
430  if (
431  (!$this->http_wrapper->post()->has("id") || !$this->http_wrapper->post()->has("item_ref_id")) &&
432  is_array($this->http_wrapper->post()->retrieve(
433  "id[]",
434  $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int())
435  ))
436  ) {
437  throw new ilException("No item select for deletion!");
438  }
439 
440  $ids = $this->http_wrapper->post()->retrieve(
441  "id",
442  $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int())
443  );
444  $current_node = $this->http_wrapper->post()->retrieve("item_ref_id", $this->refinery->kindlyTo()->int());
445  $result = true;
446  $msg = '';
447 
448  foreach ($ids as $id) {
449  $obj = ilObjectFactoryWrapper::singleton()->getInstanceByRefId($id);
450 
451  $not_parent_of_current = true;
452  $not_root = true;
453 
454  // do some additional validation if it is a StudyProgramme
455  if ($obj instanceof ilObjStudyProgramme) {
456  //check if you are not deleting a parent element of the current element
457  $children_of_node = ilObjStudyProgramme::getAllChildren($obj->getRefId());
458  $get_ref_ids = static function (ilObjStudyProgramme $obj): int {
459  return $obj->getRefId();
460  };
461 
462  $children_ref_ids = array_map($get_ref_ids, $children_of_node);
463  $not_parent_of_current = (!in_array($current_node, $children_ref_ids));
464 
465  $not_root = ($obj->getRoot() != null);// TODO PHP8-REVIEW This is always true
466  }
467 
468  if (
469  $current_node != $id &&
470  $not_root &&
471  $not_parent_of_current &&
472  $this->checkAccess('delete', $obj->getRefId())
473  ) {
474  ilRepUtil::deleteObjects(0, [$id]);
475 
476  // deletes the tree-open-node-session storage
477  if (isset($children_of_node)) {
478  $this->tree->closeCertainNode($id);
479  foreach ($children_of_node as $child) {
480  $this->tree->closeCertainNode($child->getRefId());
481  }
482  }
483 
484  $msg = $this->lng->txt("prg_deleted_safely");
485  } else {
486  $msg = $this->lng->txt("prg_not_allowed_node_to_delete");
487  $result = false;
488  }
489  }
490 
491  return ilAsyncOutputHandler::encodeAsyncResponse(array('success' => $result, 'message' => $msg));
492  }
493 
498  protected function cancelDelete(): string
499  {
501  }
502 
507  protected function initAsyncUIElements(): string
508  {
509  // add js files
513 
514  // add bootstrap modal
515  $settings_modal = ilModalGUI::getInstance();
516  $settings_modal->setId($this->modal_id);
517  $settings_modal->setType(ilModalGUI::TYPE_LARGE);
518  $this->tpl->addOnLoadCode('$("#' . $this->modal_id . '").study_programme_modal();');
519 
520  $content = $settings_modal->getHTML();
521 
522  // init js notifications
523  $notifications = new ilAsyncNotifications();
524  $notifications->addJsConfig('events', array('success' => array('study_programme-show_success')));
525  $notifications->initJs();
526 
527  // init tree selection explorer
528  $async_explorer = new ilAsyncContainerSelectionExplorer(
529  rawurldecode($this->ctrl->getLinkTarget($this, 'createNewLeaf', '', true)),
530  $this->refinery,
531  $this->http_wrapper->query()
532  );
533  $async_explorer->initJs();
534 
535  return $content;
536  }
537 
541  protected function getToolbar(): void
542  {
543  $save_order_btn = $this->ui_factory->button()->standard($this->lng->txt('prg_save_tree_order'), '')
544  ->withOnLoadCode(fn ($id) => "$(\"#$id\").click( () => $('body').trigger('study_programme-save_order'));");
545  $cancel_order_btn = $this->ui_factory->button()->standard($this->lng->txt('prg_cancel_tree_order'), '')
546  ->withOnLoadCode(fn ($id) => "$(\"#$id\").click( () => $('body').trigger('study_programme-cancel_order'));");
547 
548  $this->toolbar->addComponent($save_order_btn);
549  $this->toolbar->addComponent($cancel_order_btn);
550  }
551 
555  protected function checkAccess(string $permission, int $ref_id = null): bool
556  {
557  if (is_null($ref_id)) {
558  $ref_id = $this->ref_id;
559  }
560  return $this->access->checkAccess($permission, '', $ref_id);
561  }
562 
568  protected function checkAccessOrFail(string $permission, int $ref_id = null): void
569  {
570  if (!$this->checkAccess($permission, $ref_id)) {
571  throw new ilException("You have no permission for " . $permission . " Object with ref_id " . $ref_id . "!");
572  }
573  }
574 }
createNewLeaf()
Creates a new leaf Currently only course references can be created.
Class ilAsyncOutputHandler Handles the output for async-requests.
exit
Definition: login.php:29
static getSystemMessageHTML(string $a_txt, string $a_type="info")
Get HTML for a system message.
Class ilObjStudyProgrammeGUI class ilObjStudyProgrammeGUI: ilPermissionGUI ilObjStudyProgrammeGUI: ...
static _getIcon(int $obj_id=0, string $size="big", string $type="", bool $offline=false)
Get icon for repository item.
confirmedDelete()
Deletes a node or a leaf in the tree.
checkAccessOrFail(string $permission, int $ref_id=null)
Checks permission of a object and throws an exception if they are not granted.
const ROOT_FOLDER_ID
Definition: constants.php:32
static handleAsyncOutput(string $normal_content, string $async_content=null, bool $apply_to_tpl=true)
Handles async output.
Class ChatMainBarProvider .
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
checkAccess(string $permission, int $ref_id=null)
Checks permission of current tree or certain child of it.
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
static deleteObjects(int $a_cur_ref_id, array $a_ids)
Delete objects.
getContainerSelectionExplorer(bool $convert_to_string=true)
Initialize the Course Explorer for creating a leaf.
string $modal_id
CSS-ID of the modal windows.
Component logger with individual log levels by component id.
initTree()
Initialize Tree Creates tree instance and set tree configuration.
static addJavaScript(bool $add_form_loader=false, string $js_base_path=null)
Adds all needed js By default is called by ilAsyncPropertyFormGUI::getHTML()
static addJavaScript(ilGlobalTemplate $main_tpl=null)
Add javascript files that are necessary to run accordion.
static encodeAsyncResponse(array $data=array())
Encode data as json for async output.
$lng
$log
Definition: result.php:33
saveTreeOrder()
Saves tree node order Data is json encoded from the jstree component.
static _lookupObjectId(int $ref_id)
setId(string $a_val)
cancelDelete()
Cancel deletion Return a json string for the async handling.
executeCommand()
Execute GUI-commands If there is a async request the response is sent as a json string.
static addJavascript()
Adds the javascript to template.
static getClassByType(string $obj_type)
getCreationForm()
Returns the async creation form for StudyProgrammes.
__construct(protected ilGlobalTemplateInterface $tpl, protected ilCtrl $ctrl, protected ilAccess $access, protected ilToolbarGUI $toolbar, protected ilLanguage $lng, protected ilComponentLogger $log, protected ILIAS $ilias, protected ilSetting $ilSetting, protected ilTree $ilTree, protected ilRbacAdmin $rbacadmin, protected ILIAS\HTTP\Wrapper\WrapperFactory $http_wrapper, protected ILIAS\Refinery\Factory $refinery, protected ILIAS\UI\Factory $ui_factory)
static getInstance()
static getAllChildren(int $a_ref_id, bool $include_references=false)
Get a list of all ilObjStudyProgrammes in the subtree starting at $a_ref_id.
global $ilSetting
Definition: privfeed.php:18
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static _getInstance(int $a_obj_id)
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
Class ilAsyncContainerSelectionExplorer A class for async ilContainerSelectionExplorer which triggers...
Class ilAsyncPropertyFormGUI.
Class ilRbacAdmin Core functions for role based access control.
static _lookupType(int $id, bool $reference=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
initAsyncUIElements()
Initializes all elements used for async-interaction Adds HTML-skeleton for the bootstrap modal dialog...
Class ilObjStudyProgrammeTreeGUI Generates the manage view for ilTrainingProgramme-Repository objects...
create()
Generates the modal window content for the creation form of nodes or leafs If there are already Study...
ilObjStudyProgrammeTreeExplorerGUI $tree
Refinery Factory $refinery