ILIAS  trunk Revision v11.0_alpha-2638-g80c1d007f79
class.ilObjectListGUI.php
Go to the documentation of this file.
1 <?php
2 
19 declare(strict_types=1);
20 
35 
48 {
49  public const IL_LIST_AS_TRIGGER = 'trigger';
50  public const IL_LIST_FULL = 'full';
51 
52  public const DETAILS_MINIMAL = 10;
53  public const DETAILS_SEARCH = 20 ;
54  public const DETAILS_ALL = 30;
55 
56  public const CONTEXT_REPOSITORY = 1;
57  public const CONTEXT_WORKSPACE = 2;
58  public const CONTEXT_WORKSPACE_SHARING = 4;
59  public const CONTEXT_PERSONAL_DESKTOP = 5;
60  public const CONTEXT_SEARCH = 6;
61 
62  public const DOWNLOAD_CHECKBOX_NONE = 0;
63  public const DOWNLOAD_CHECKBOX_ENABLED = 1;
64  public const DOWNLOAD_CHECKBOX_DISABLED = 2;
65 
66  protected static array $cnt_notes = [];
67  protected static array $cnt_tags = [];
68  protected static array $tags = [];
69  protected static array $comments_activation = [];
70  protected static bool $preload_done = false;
71  protected static int $js_unique_id = 0;
72  protected static string $tpl_file_name = 'tpl.container_list_item.html';
73  protected static string $tpl_component = 'components/ILIAS/Container';
74  private \ILIAS\Notes\Service $notes_service;
75  protected bool $force_rate_parent = false;
76 
77  protected array $access_cache;
79  protected ilObjUser $user;
80  protected LocalDIC $object_dic;
83  protected ilTree $tree;
84  protected ilSetting $settings;
85  protected HTTPServices $http;
86  protected UIServices $ui;
90  protected ilLanguage $lng;
91  protected string $mode;
92  protected bool $path_enabled;
93  protected int $context;
96 
97  protected bool $static_link_enabled = false;
98  protected bool $delete_enabled = false;
99  protected bool $cut_enabled = false;
100  protected bool $subscribe_enabled = false;
101  protected bool $link_enabled = false;
102  protected bool $copy_enabled = true;
103  protected bool $progress_enabled = false;
104  protected bool $notice_properties_enabled = true;
105  protected bool $info_screen_enabled = false;
106  protected string $type;
107  protected string $gui_class_name = '';
108  protected array $commands = [];
109 
112  protected int $requested_ref_id;
113  protected string $requested_cmd;
114  protected string $requested_base_class;
116 
117 
118  protected bool $description_enabled = true;
119  protected bool $preconditions_enabled = true;
120  protected bool $properties_enabled = true;
121  protected bool $commands_enabled = true;
122  protected array $cust_prop = [];
124  protected array $cust_commands = [];
126  protected array $cust_modals = [];
127  protected int $condition_depth = 0;
128  protected bool $std_cmd_only = false;
129  protected array $sub_item_html = [];
130  protected bool $multi_download_enabled = false;
131  protected int $download_checkbox_state = self::DOWNLOAD_CHECKBOX_NONE;
132  protected int $obj_id;
133  protected int $ref_id;
134  protected int $sub_obj_id;
135  protected ?string $sub_obj_type;
137  protected bool $substitutions_enabled = false;
138  protected bool $icons_enabled = false;
139  protected bool $checkboxes_enabled = false;
140  protected bool $position_enabled = false;
141  protected bool $item_detail_links_enabled = false;
142  protected array $item_detail_links = [];
143  protected string $item_detail_links_intro = '';
144  protected bool $search_fragments_enabled = false;
145  protected string $search_fragment = '';
146  protected bool $path_linked = false;
147  protected int $relevance = 0;
148  protected bool $expand_enabled = false;
149  protected bool $is_expanded = true;
150  protected bool $bold_title = false;
151  protected int $details_level = self::DETAILS_ALL;
152  protected int $reference_ref_id = 0;
153  protected ?int $reference_obj_id = null;
154  protected bool $separate_commands = false;
155  protected bool $search_fragment_enabled = false;
156  protected ?string $additional_information = '';
157  protected bool $repository_transfer_enabled = false;
158  protected bool $shared = false;
159  protected bool $restrict_to_goto = false;
160  protected bool $comments_enabled = false;
161  protected bool $comments_settings_enabled = false;
162  protected bool $notes_enabled = false;
163  protected bool $tags_enabled = false;
164  protected bool $rating_enabled = false;
165  protected bool $rating_categories_enabled = false;
166  protected ?string $rating_text = null;
167  protected ?array $rating_ctrl_path = null;
168  protected bool $timings_enabled = true;
169  protected bool $force_visible_only = false;
170  protected array $prevent_duplicate_commands = [];
171  protected int $parent_ref_id;
172  protected string $title_link = '';
173  protected bool $title_link_disabled = false;
174  protected bool $lp_cmd_enabled = false;
175  protected bool $lp_settings_cmd_enabled = true;
176  protected array $current_actions = [];
177  protected ?ilPathGUI $path_gui = null;
178  protected array $default_command_params = [];
179  protected array $header_icons = [];
180  protected ?object $container_obj = null;
181  protected ilTemplate $tpl;
182  protected string $position_value;
183  protected int $path_start_node;
184  protected array $default_command = [];
185  protected bool $adm_commands_included;
186  protected bool $prevent_access_caching;
187  protected array $condition_target;
188  protected array $notice_prop = [];
189  protected string $ajax_hash;
190  protected ilListItemAccessCache $acache;
191  protected string $position_field_index = '';
192  protected string $title = '';
193  protected string $description = '';
195 
196  public function __construct(int $context = self::CONTEXT_REPOSITORY)
197  {
199  global $DIC;
200 
201  $this->access = $DIC['ilAccess'];
202  $this->user = $DIC['ilUser'];
203  $this->object_dic = LocalDIC::dic();
204  $this->obj_definition = $DIC['objDefinition'];
205  $this->tree = $DIC['tree'];
206  $this->settings = $DIC['ilSetting'];
207  $this->http = $DIC->http();
208  $this->ui = $DIC->ui();
209  $this->main_tpl = $DIC['tpl'];
210  $this->rbacsystem = $DIC['rbacsystem'];
211  $this->ctrl = $DIC['ilCtrl'];
212  $this->lng = $DIC['lng'];
213  $this->mode = self::IL_LIST_FULL;
214  $this->path_enabled = false;
215  $this->context = $context;
216  $this->request_wrapper = $DIC->http()->wrapper()->query();
217  $this->refinery = $DIC['refinery'];
218 
219  $this->enableComments(false);
220  $this->enableNotes(false);
221  $this->enableTags(false);
222 
223  // unique js-ids
224  $this->setParentRefId((int) ($_REQUEST['ref_id'] ?? 0));
225 
226  $this->init();
227 
228  $this->ldap_mapping = ilLDAPRoleGroupMapping::_getInstance();
229  $this->fav_manager = new ilFavouritesManager();
230 
231  $this->lng->loadLanguageModule('obj');
232  $this->lng->loadLanguageModule('rep');
233  $params = $DIC->http()->request()->getQueryParams();
234  $this->requested_ref_id = (int) ($params['ref_id'] ?? null);
235  $this->requested_cmd = (string) ($params['cmd'] ?? null);
236  $this->requested_base_class = (string) ($params['baseClass'] ?? null);
237  $this->clipboard = $DIC
238  ->repository()
239  ->internal()
240  ->domain()
241  ->clipboard();
242  $this->notes_service = $DIC->notes();
243  }
244 
245  public function setContainerObject(object $container_obj): void
246  {
247  $this->container_obj = $container_obj;
248  }
249 
250  public function getContainerObject(): ?object
251  {
252  return $this->container_obj;
253  }
254 
255 
261  public function init(): void
262  {
263  // Create static links for default command (linked title) or not
264  $this->static_link_enabled = true;
265  $this->delete_enabled = true;
266  $this->cut_enabled = true;
267  $this->subscribe_enabled = true;
268  $this->link_enabled = false;
269  $this->copy_enabled = false;
270  $this->progress_enabled = false;
271  $this->notice_properties_enabled = true;
272  $this->info_screen_enabled = false;
273  $this->type = ''; // 'cat', 'course', ...
274  $this->gui_class_name = ''; // 'ilobjcategorygui', 'ilobjcoursegui', ...
275 
276  // general commands array, e.g.
277  $this->commands = ilObjectAccess::_getCommands();
278  }
279 
280  public function enableProperties(bool $status): void
281  {
282  $this->properties_enabled = $status;
283  }
284 
285  public function getPropertiesStatus(): bool
286  {
288  }
289 
290  public function enablePreconditions(bool $status): void
291  {
292  $this->preconditions_enabled = $status;
293  }
294 
295  public function getPreconditionsStatus(): bool
296  {
298  }
299 
300  public function enableNoticeProperties(bool $status): void
301  {
302  $this->notice_properties_enabled = $status;
303  }
304 
305  public function getNoticePropertiesStatus(): bool
306  {
308  }
309 
310  public function enableDescription(bool $status): void
311  {
312  $this->description_enabled = $status;
313  }
314 
315  public function getDescriptionStatus(): bool
316  {
318  }
319 
320  public function enableSearchFragments(bool $status): void
321  {
322  $this->search_fragment_enabled = $status;
323  }
324 
325  public function getSearchFragmentStatus(): bool
326  {
328  }
329 
330  public function enableLinkedPath(bool $status): void
331  {
332  $this->path_linked = $status;
333  }
334 
335  public function setRelevance(int $rel): void
336  {
337  $this->relevance = $rel;
338  }
339 
340  public function getRelevance(): int
341  {
342  return $this->relevance;
343  }
344 
345  public function enableIcon(bool $status): void
346  {
347  $this->icons_enabled = $status;
348  }
349 
350  public function getIconStatus(): bool
351  {
352  return $this->icons_enabled;
353  }
354 
355  public function enableCheckbox(bool $status): void
356  {
357  $this->checkboxes_enabled = $status;
358  }
359 
360  public function getCheckboxStatus(): bool
361  {
363  }
364 
365  public function enableExpand(bool $status): void
366  {
367  $this->expand_enabled = $status;
368  }
369 
370  public function getExpandStatus(): bool
371  {
372  return $this->expand_enabled;
373  }
374 
375  public function setExpanded(bool $status): void
376  {
377  $this->is_expanded = $status;
378  }
379 
380  public function isExpanded(): bool
381  {
382  return $this->is_expanded;
383  }
388  public function setPositionInputField(string $field_index, string $position_value): void
389  {
390  $this->position_enabled = true;
391  $this->position_field_index = $field_index;
392  $this->position_value = $position_value;
393  }
394 
395  public function enableDelete(bool $status): void
396  {
397  $this->delete_enabled = $status;
398  }
399 
400  public function getDeleteStatus(): bool
401  {
402  return $this->delete_enabled;
403  }
404 
405  public function enableCut(bool $status): void
406  {
407  $this->cut_enabled = $status;
408  }
409 
410  public function getCutStatus(): bool
411  {
412  return $this->cut_enabled;
413  }
414 
415  public function enableCopy(bool $status): void
416  {
417  $this->copy_enabled = $status;
418  }
419 
420  public function getCopyStatus(): bool
421  {
422  return $this->copy_enabled;
423  }
424 
425  public function enableSubscribe(bool $status): void
426  {
427  $this->subscribe_enabled = $status;
428  }
429 
430  public function getSubscribeStatus(): bool
431  {
433  }
434 
435  public function enableLink(bool $status): void
436  {
437  $this->link_enabled = $status;
438  }
439 
440  public function getLinkStatus(): bool
441  {
442  return $this->link_enabled;
443  }
444 
445  public function enablePath(bool $path, int $start_node = 0, ?\ilPathGUI $path_gui = null): void
446  {
447  $this->path_enabled = $path;
448  $this->path_start_node = $start_node;
449  $this->path_gui = $path_gui;
450  }
451 
452  public function getPathStatus(): bool
453  {
454  return $this->path_enabled;
455  }
456 
457  public function enableCommands(bool $status, bool $std_only = false): void
458  {
459  $this->commands_enabled = $status;
460  $this->std_cmd_only = $std_only;
461  }
462 
463  public function getCommandsStatus(): bool
464  {
466  }
467 
468  public function enableInfoScreen(bool $info_screen): void
469  {
470  $this->info_screen_enabled = $info_screen;
471  }
472 
473  public function getInfoScreenStatus(): bool
474  {
476  }
477 
478  protected function enableLearningProgress(bool $enabled): void
479  {
480  $this->lp_cmd_enabled = $enabled;
481  }
482 
483  protected function enableLPSettingsCommand(bool $enabled): void
484  {
485  $this->lp_settings_cmd_enabled = $enabled;
486  }
487 
493  public function addSubItemHTML(string $html): void
494  {
495  $this->sub_item_html[] = $html;
496  }
497 
498  public function enableProgressInfo(bool $status): void
499  {
500  $this->progress_enabled = $status;
501  }
502 
503  public function getProgressInfoStatus(): bool
504  {
506  }
507 
508  public function enableSubstitutions(bool $status): void
509  {
510  $this->substitutions_enabled = $status;
511  }
512 
513  public function getSubstitutionStatus(): bool
514  {
516  }
517 
522  public function enableItemDetailLinks(bool $status): void
523  {
524  $this->item_detail_links_enabled = $status;
525  }
526 
530  public function getItemDetailLinkStatus(): bool
531  {
533  }
534 
540  public function setItemDetailLinks(array $detail_links, string $intro_txt = ''): void
541  {
542  $this->item_detail_links = $detail_links;
543  $this->item_detail_links_intro = $intro_txt;
544  }
545 
546  public function insertItemDetailLinks(): void
547  {
548  if (!count($this->item_detail_links)) {
549  return;
550  }
551  if (strlen($this->item_detail_links_intro)) {
552  $this->tpl->setCurrentBlock('item_detail_intro');
553  $this->tpl->setVariable('ITEM_DETAIL_INTRO_TXT', $this->item_detail_links_intro);
554  $this->tpl->parseCurrentBlock();
555  }
556 
557  foreach ($this->item_detail_links as $info) {
558  $this->tpl->setCurrentBlock('item_detail_link');
559  $this->tpl->setVariable('ITEM_DETAIL_LINK_TARGET', $info['target']);
560  $this->tpl->setVariable('ITEM_DETAIL_LINK_DESC', $info['desc']);
561  $this->tpl->setVariable('ITEM_DETAIL_LINK_HREF', $info['link']);
562  $this->tpl->setVariable('ITEM_DETAIL_LINK_NAME', $info['name']);
563  $this->tpl->parseCurrentBlock();
564  }
565  $this->tpl->setCurrentBlock('item_detail_links');
566  $this->tpl->parseCurrentBlock();
567  }
568  public function setTitle(string $title): void
569  {
570  $this->title = $this->refinery->encode()->htmlSpecialCharsAsEntities()->transform(
571  $title
572  );
573  }
574 
578  public function getTitle(): string
579  {
580  return $this->title;
581  }
582 
583  public function setDescription(string $description): void
584  {
585  $this->description = $this->refinery->encode()->htmlSpecialCharsAsEntities()->transform(
586  $description
587  );
588  }
589 
593  public function getDescription(): string
594  {
595  return $this->description;
596  }
597 
601  public function setSearchFragment(string $text): void
602  {
603  $this->search_fragment = $text;
604  }
605 
606  public function getSearchFragment(): string
607  {
608  return $this->search_fragment;
609  }
610 
611  public function setSeparateCommands(bool $val): void
612  {
613  $this->separate_commands = $val;
614  }
615 
616  public function getSeparateCommands(): bool
617  {
619  }
620 
626  public function getCommandId(): int
627  {
628  return $this->ref_id;
629  }
630 
631  public function setAdditionalInformation(?string $val): void
632  {
633  $this->additional_information = $val;
634  }
635 
636  public function getAdditionalInformation(): ?string
637  {
639  }
640 
646  public function setDetailsLevel(int $level): void
647  {
648  $this->details_level = $level;
649  }
650 
651  public function getDetailsLevel(): int
652  {
653  return $this->details_level;
654  }
655 
659  public function enableRepositoryTransfer(bool $value): void
660  {
661  $this->repository_transfer_enabled = $value;
662  }
663 
667  public function restrictToGoto(bool $value): void
668  {
669  $this->restrict_to_goto = $value;
670  }
671 
672  public function getDefaultCommand(): array
673  {
674  return $this->default_command;
675  }
676 
677  public function checkCommandAccess(
678  string $permission,
679  string $cmd,
680  int $ref_id,
681  string $type,
682  ?int $obj_id = null
683  ): bool {
684  // e.g: sub items should not be readable since their parent session is readonly.
685  if ($permission != 'visible' and $this->isVisibleOnlyForced()) {
686  return false;
687  }
688 
689  $cache_prefix = null;
690  if ($this->context == self::CONTEXT_WORKSPACE || $this->context == self::CONTEXT_WORKSPACE_SHARING) {
691  $cache_prefix = 'wsp';
692  if (!isset($this->ws_access)) {
693  $this->ws_access = new ilWorkspaceAccessHandler();
694  }
695  }
696 
697  if (isset($this->access_cache[$permission]['-' . $cmd][$cache_prefix . $ref_id])) {
698  return $this->access_cache[$permission]['-' . $cmd][$cache_prefix . $ref_id];
699  }
700 
701  if ($this->context == self::CONTEXT_REPOSITORY || $this->context == self::CONTEXT_SEARCH) {
702  $access = $this->access->checkAccess($permission, $cmd, $ref_id, $type, (int) $obj_id);
703  if ($this->access->getPreventCachingLastResult()) {
704  $this->prevent_access_caching = true;
705  }
706  } else {
707  $access = $this->ws_access->checkAccess($permission, $cmd, $ref_id, $type);
708  }
709 
710  $this->access_cache[$permission]['-' . $cmd][$cache_prefix . $ref_id] = $access;
711  return $access;
712  }
713 
717  public function initItem(
718  int $ref_id,
719  int $obj_id,
720  string $type,
721  string $title = '',
722  string $description = ''
723  ): void {
724  $this->access_cache = [];
725  $this->ref_id = $ref_id;
726  $this->obj_id = $obj_id;
727  $this->object_properties = $this->object_dic['properties.aggregator']->getFor($obj_id);
728  $this->setTitle($title);
729  $this->setDescription($description);
730 
731  // checks, whether any admin commands are included in the output
732  $this->adm_commands_included = false;
733  $this->prevent_access_caching = false;
734 
735  // prepare ajax calls
736  if ($this->context == self::CONTEXT_REPOSITORY) {
738  } else {
740  }
741  $this->setAjaxHash(ilCommonActionDispatcherGUI::buildAjaxHash($node_type, $ref_id, $type, $obj_id));
742  }
743 
744  public function setConditionTarget(int $ref_id, int $obj_id, string $target_type): void
745  {
746  $this->condition_target = [
747  'ref_id' => $ref_id,
748  'obj_id' => $obj_id,
749  'target_type' => $target_type
750  ];
751  }
752 
753  public function resetConditionTarget(): void
754  {
755  $this->condition_target = [];
756  }
757 
758  public function disableTitleLink(bool $status): void
759  {
760  $this->title_link_disabled = $status;
761  }
762 
763  public function setDefaultCommandParameters(array $params): void
764  {
765  $this->default_command_params = $params;
766  }
767 
773  public function createDefaultCommand(array $command): array
774  {
775  if ($this->static_link_enabled and !$this->default_command_params) {
776  if ($link = ilLink::_getStaticLink($this->ref_id, $this->type, false)) {
777  $command['link'] = $link;
778  $command['frame'] = '_top';
779  }
780  }
781  if ($this->default_command_params) {
782  $params = [];
783  foreach ($this->default_command_params as $name => $value) {
784  $params[] = $name . '=' . $value;
785  }
786  $params = implode('&', $params);
787 
788  if (!stristr($command['link'], '?')) {
789  $command['link'] .= '?' . $params;
790  } else {
791  $command['link'] .= '&' . $params;
792  }
793  }
794  return $command;
795  }
796 
805  public function getCommandLink(string $cmd): string
806  {
807  if ($this->context == self::CONTEXT_REPOSITORY || $this->context == self::CONTEXT_SEARCH) {
808  // BEGIN WebDAV Get mount webfolder link.
809  if ($cmd == 'mount_webfolder' && ilDAVActivationChecker::_isActive()) {
810  $uri_builder = new ilWebDAVUriBuilder($this->http->request());
811  return $uri_builder->getUriToMountInstructionModalByRef($this->ref_id);
812  }
813  // END WebDAV Get mount webfolder link.
814 
815  $this->ctrl->setParameterByClass('ilrepositorygui', 'ref_id', $this->getCommandId());
816  $cmd_link = $this->ctrl->getLinkTargetByClass('ilrepositorygui', $cmd);
817  $this->ctrl->setParameterByClass('ilrepositorygui', 'ref_id', $this->requested_ref_id);
818  return $cmd_link;
819  }
820 
821  $this->ctrl->setParameterByClass($this->gui_class_name, 'ref_id', '');
822  $this->ctrl->setParameterByClass($this->gui_class_name, 'wsp_id', $this->ref_id);
823  return $this->ctrl->getLinkTargetByClass($this->gui_class_name, $cmd);
824  }
825 
834  public function getCommandFrame(string $cmd): string
835  {
836  return '';
837  }
838 
847  public function getCommandImage(string $cmd): string
848  {
849  return '';
850  }
851 
863  public function getProperties(): array
864  {
865  $props = [];
866 
867  // #8280: WebDav is only supported in repository
868  if ($this->context == self::CONTEXT_REPOSITORY) {
869  // add centralized offline status
870  if (ilObject::lookupOfflineStatus($this->obj_id)) {
871  $props[] =
872  [
873  'alert' => true,
874  'property' => $this->lng->txt('status'),
875  'value' => $this->lng->txt('offline')
876  ];
877  }
878 
879  // BEGIN WebDAV Display locking information
881  // Show lock info
882  $webdav_dic = new ilWebDAVDIC();
883  $webdav_dic->initWithoutDIC();
884  $webdav_lock_backend = $webdav_dic->locksbackend();
885  if ($this->user->getId() !== ANONYMOUS_USER_ID) {
886  if ($lock = $webdav_lock_backend->getLocksOnObjectId($this->obj_id)) {
887  $lock_user = new ilObjUser($lock->getIliasOwner());
888 
889  $props[] = [
890  'alert' => false,
891  'property' => $this->lng->txt('in_use_by'),
892  'value' => $lock_user->getLogin(),
893  'link' =>
894  './ilias.php?user=' .
895  $lock_user->getId() .
896  '&cmd=showUserProfile&cmdClass=ildashboardgui&baseClass=ilDashboardGUI'
897  ];
898  }
899  }
900  }
901  // END WebDAV Display warning for invisible files and files with special characters
902  }
903 
904  return $props;
905  }
906 
907  public function addCustomProperty(
908  string $property = '',
909  string $value = '',
910  bool $alert = false,
911  bool $newline = false
912  ): void {
913  $this->cust_prop[] = [
914  'property' => $property,
915  'value' => $value,
916  'alert' => $alert,
917  'newline' => $newline
918  ];
919  }
920 
921  public function getCustomProperties(array $prop): array
922  {
923  if (is_array($this->cust_prop)) {
924  foreach ($this->cust_prop as $property) {
925  $prop[] = $property;
926  }
927  }
928  return $prop;
929  }
930 
931  public function getAlertProperties(): array
932  {
933  $alert = [];
934  foreach ($this->getProperties() as $prop) {
935  if (isset($prop['alert']) && $prop['alert'] == true) {
936  $alert[] = $prop;
937  }
938  }
939  return $alert;
940  }
941 
942  public function getNoticeProperties(): array
943  {
944  $this->notice_prop = [];
945  if ($infos = $this->ldap_mapping->getInfoStrings($this->obj_id, true)) {
946  foreach ($infos as $info) {
947  $this->notice_prop[] = ['value' => $info];
948  }
949  }
950  return $this->notice_prop;
951  }
952 
953  public function addCustomCommand(string $link, string $lang_var, string $frame = '', string $onclick = ''): void
954  {
955  $this->cust_commands[] = [
956  'link' => $link,
957  'lang_var' => $lang_var,
958  'frame' => $frame,
959  'onclick' => $onclick
960  ];
961  }
962 
963  public function addCustomCommandButton(
964  Button $button,
965  ?Modal $triggeredModal = null
966  ): void {
967  $this->cust_commands[] = $button;
968  if ($triggeredModal !== null) {
969  $this->cust_modals[] = $triggeredModal;
970  }
971  }
972 
973  public function forceVisibleOnly(bool $stat): void
974  {
975  $this->force_visible_only = $stat;
976  }
977 
978  public function isVisibleOnlyForced(): bool
979  {
981  }
982 
1006  public function getCommands(): array
1007  {
1008  $ref_commands = [];
1009  foreach ($this->commands as $command) {
1010  $permission = $command['permission'];
1011  $cmd = $command['cmd'];
1012  $lang_var = $command['lang_var'] ?? '';
1013  $txt = '';
1014  $info_object = null;
1015  $cmd_link = '';
1016  $cmd_frame = '';
1017  $cmd_image = '';
1018  $access_granted = false;
1019 
1020  if (isset($command['txt'])) {
1021  $txt = $command['txt'];
1022  }
1023 
1024  // Suppress commands that don't make sense for anonymous users
1025  if (
1026  $this->user->getId() == ANONYMOUS_USER_ID &&
1027  (isset($command['enable_anonymous']) && $command['enable_anonymous'] == 'false')
1028  ) {
1029  continue;
1030  }
1031 
1032  // all access checking should be made within $this->access and
1033  // the checkAccess of the ilObj...Access classes
1034  // $access = $this->access->checkAccess($permission, $cmd, $this->ref_id, $this->type);
1035  $access = $this->checkCommandAccess($permission, $cmd, $this->ref_id, $this->type);
1036 
1037  if ($access) {
1038  $access_granted = true;
1039  $cmd_link = $this->getCommandLink($command['cmd']);
1040  $cmd_frame = $this->getCommandFrame($command['cmd']);
1041  $cmd_image = $this->getCommandImage($command['cmd']);
1042  } else {
1043  $info_object = $this->access->getInfo();
1044  }
1045 
1046  if (!isset($command['default'])) {
1047  $command['default'] = '';
1048  }
1049  $ref_commands[] = [
1050  'permission' => $permission,
1051  'cmd' => $cmd,
1052  'link' => $cmd_link,
1053  'frame' => $cmd_frame,
1054  'lang_var' => $lang_var,
1055  'txt' => $txt,
1056  'granted' => $access_granted,
1057  'access_info' => $info_object,
1058  'img' => $cmd_image,
1059  'default' => $command['default']
1060  ];
1061  }
1062 
1063  return $ref_commands;
1064  }
1065 
1073  public function getIconImageType(): string
1074  {
1075  return $this->type;
1076  }
1077 
1078  public function insertTitle(): void
1079  {
1080  if ($this->restrict_to_goto) {
1081  $this->default_command = [
1082  'frame' => '',
1083  'link' => $this->buildGotoLink()
1084  ];
1085  }
1086  // begin-patch lok
1087  if (
1088  !$this->default_command ||
1089  (!$this->getCommandsStatus() && !$this->restrict_to_goto) ||
1090  $this->title_link_disabled
1091  ) {
1092  // end-patch lok
1093  $this->tpl->setCurrentBlock('item_title');
1094  $this->tpl->setVariable('TXT_TITLE', $this->getTitle());
1095  } else {
1096  $this->default_command['link'] = $this->modifyTitleLink($this->default_command['link']);
1097 
1098  list($this->default_command['link'], $this->default_command['frame']) =
1099  $this->modifySAHSlaunch($this->default_command['link'], $this->default_command['frame']);
1100 
1101  if ($this->default_command['frame'] != '') {
1102  $this->tpl->setCurrentBlock('title_linked_frame');
1103  $this->tpl->setVariable('TARGET_TITLE_LINKED', $this->default_command['frame']);
1104  $this->tpl->parseCurrentBlock();
1105  }
1106 
1107  // workaround for repository frameset
1108  $this->default_command['link'] = $this->appendRepositoryFrameParameter($this->default_command['link']);
1109 
1110  // the default command is linked with the title
1111  $this->tpl->setCurrentBlock('item_title_linked');
1112  $this->tpl->setVariable('TXT_TITLE_LINKED', $this->getTitle());
1113  $this->tpl->setVariable('HREF_TITLE_LINKED', $this->default_command['link']);
1114 
1115  // New Preview Implementation, File-Objects only
1116  if ($this->type === 'file') {
1117  $preview = new ilObjFilePreviewRendererGUI($this->obj_id);
1118  if ($preview->has()) {
1119  $this->tpl->setVariable('PREVIEW_GLYPH', $preview->getRenderedTriggerComponents());
1120  $this->tpl->parseCurrentBlock();
1121  }
1122  }
1123  }
1124  $this->tpl->parseCurrentBlock();
1125 
1126  if ($this->bold_title == true) {
1127  $this->tpl->touchBlock('bold_title_start');
1128  $this->tpl->touchBlock('bold_title_end');
1129  }
1130  }
1131 
1132  protected function buildGotoLink(): ?string
1133  {
1134  switch ($this->context) {
1135  case self::CONTEXT_WORKSPACE_SHARING:
1136  return ilWorkspaceAccessHandler::getGotoLink($this->ref_id, $this->obj_id);
1137 
1138  default:
1139  // not implemented yet
1140  break;
1141  }
1142  return null;
1143  }
1144 
1145  public function insertSubstitutions(): void
1146  {
1147  $fields_shown = false;
1148  foreach ($this->substitutions->getParsedSubstitutions($this->ref_id, $this->obj_id) as $data) {
1149  if ($data['bold']) {
1150  $data['name'] = '<strong>' . $data['name'] . '</strong>';
1151  $data['value'] = '<strong>' . $data['value'] . '</strong>';
1152  }
1153  $this->tpl->touchBlock('std_prop');
1154  $this->tpl->setCurrentBlock('item_property');
1155  if ($data['show_field']) {
1156  $this->tpl->setVariable('TXT_PROP', $data['name']);
1157  }
1158  $this->tpl->setVariable('VAL_PROP', $data['value']);
1159  $this->tpl->parseCurrentBlock();
1160 
1161  if ($data['newline']) {
1162  $this->tpl->touchBlock('newline_prop');
1163  }
1164  $fields_shown = false;
1165  }
1166  }
1167 
1168  public function insertDescription(): void
1169  {
1170  if ($this->getSubstitutionStatus()) {
1171  $this->insertSubstitutions();
1172  if (!$this->substitutions->isDescriptionEnabled()) {
1173  return;
1174  }
1175  }
1176 
1177  $this->tpl->setCurrentBlock('item_description');
1178  $this->tpl->setVariable('TXT_DESC', $this->getDescription());
1179  $this->tpl->parseCurrentBlock();
1180  }
1181 
1185  public function insertSearchFragment(): void
1186  {
1187  if (strlen($this->getSearchFragment())) {
1188  $this->tpl->setCurrentBlock('search_fragment');
1189  $this->tpl->setVariable('TXT_SEARCH_FRAGMENT', $this->getSearchFragment() . ' ...');
1190  $this->tpl->parseCurrentBlock();
1191  }
1192  }
1193 
1199  public function setMode(string $mode): void
1200  {
1201  $this->mode = $mode;
1202  }
1203 
1209  public function getMode(): string
1210  {
1211  return $this->mode;
1212  }
1213 
1217  public function setConditionDepth(int $depth): void
1218  {
1219  $this->condition_depth = $depth;
1220  }
1221 
1228  public function isMode(string $mode): bool
1229  {
1230  return $mode === $this->mode;
1231  }
1232 
1233  public function determineProperties(): array
1234  {
1235  $props = $this->getCustomProperties(
1236  $this->getProperties()
1237  );
1238 
1239  if ($this->context != self::CONTEXT_WORKSPACE && $this->context != self::CONTEXT_WORKSPACE_SHARING) {
1240  // add learning progress custom property
1241  $lp = ilLPStatus::getListGUIStatus($this->obj_id);
1242  if ($lp) {
1243  $props[] = [
1244  'alert' => false,
1245  'property' => $this->lng->txt('learning_progress'),
1246  'value' => $lp,
1247  'newline' => true
1248  ];
1249  }
1250 
1251  // add no item access note in public section
1252  // for items that are visible but not readable
1253  if ($this->user->getId() === ANONYMOUS_USER_ID) {
1254  if (!$this->access->checkAccess('read', '', $this->ref_id, $this->type, $this->obj_id)) {
1255  $props[] = [
1256  'alert' => true,
1257  'value' => $this->lng->txt('no_access_item_public'),
1258  'newline' => true
1259  ];
1260  }
1261  }
1262  }
1263 
1264  // reference objects have translated ids, revert to originals
1265  $note_ref_id = $this->ref_id;
1266  $note_obj_id = $this->obj_id;
1267  if ($this->reference_ref_id) {
1268  $note_ref_id = $this->reference_ref_id;
1269  $note_obj_id = $this->reference_obj_id;
1270  }
1271  $redraw_js = 'il.Object.redrawListItem(' . $note_ref_id . ');';
1272 
1273  // add common properties (comments, notes, tags)
1274  if (
1275  (
1276  (
1277  isset(self::$cnt_notes[$note_obj_id][Note::PRIVATE]) &&
1278  self::$cnt_notes[$note_obj_id][Note::PRIVATE] > 0
1279  ) || (
1280  isset(self::$cnt_notes[$note_obj_id][Note::PUBLIC]) &&
1281  self::$cnt_notes[$note_obj_id][Note::PUBLIC] > 0
1282  ) || (
1283  isset(self::$cnt_tags[$note_obj_id]) && self::$cnt_tags[$note_obj_id] > 0
1284  ) || (
1285  isset(self::$tags[$note_obj_id]) && is_array(self::$tags[$note_obj_id])
1286  )
1287  ) && ($this->user->getId() !== ANONYMOUS_USER_ID)
1288  ) {
1289  $nl = true;
1290  $cnt_comments = self::$cnt_notes[$note_obj_id][Note::PUBLIC] ?? 0;
1291  if ($this->isCommentsActivated($this->type, $this->ref_id, $this->obj_id, false, false)
1292  && $cnt_comments > 0) {
1293  $props[] = [
1294  'alert' => false,
1295  'property' => $this->lng->txt('notes_comments'),
1296  'value' =>
1297  '<a href="#" onclick="return ' .
1298  ilNoteGUI::getListCommentsJSCall($this->ajax_hash, $redraw_js) . '">' .
1299  self::$cnt_notes[$note_obj_id][Note::PUBLIC] . '</a>',
1300  'newline' => $nl
1301  ];
1302  $nl = false;
1303  }
1304 
1305  $cnt_notes = self::$cnt_notes[$note_obj_id][Note::PRIVATE] ?? 0;
1306  if ($this->notes_enabled && $cnt_notes > 0) {
1307  $props[] = [
1308  'alert' => false,
1309  'property' => $this->lng->txt('notes'),
1310  'value' =>
1311  '<a href="#" onclick="return ' .
1312  ilNoteGUI::getListNotesJSCall($this->ajax_hash, $redraw_js) . '">' .
1313  self::$cnt_notes[$note_obj_id][Note::PRIVATE] . '</a>',
1314  'newline' => $nl
1315  ];
1316  $nl = false;
1317  }
1318  $cnt_tags = self::$cnt_tags[$note_obj_id] ?? 0;
1319  if ($this->tags_enabled && ($cnt_tags > 0 || isset(self::$tags[$note_obj_id]))) {
1320  $tags_set = new ilSetting('tags');
1321  if ($tags_set->get('enable')) {
1322  $tags_url = ilTaggingGUI::getListTagsJSCall($this->ajax_hash, $redraw_js);
1323 
1324  // list object tags
1325  if (isset(self::$tags[$note_obj_id])) {
1326  $tags_tmp = [];
1327  foreach (self::$tags[$note_obj_id] as $tag => $is_tag_owner) {
1328  if ($is_tag_owner) {
1329  $tags_tmp[] = '<a class="ilTag ilTagRelHigh" href="#" onclick="return ' .
1330  $tags_url . '">' . $tag . '</a>';
1331  } else {
1332  $tags_tmp[] = '<span class="ilTag ilTagRelMiddle">' . $tag . '</span>';
1333  }
1334  }
1335  $tags_value = implode(' ', $tags_tmp);
1336  $nl = true;
1337  $prop_text = '';
1338  } // tags counter
1339  else {
1340  $tags_value = '<a href="#" onclick="return ' . $tags_url . '">' .
1341  self::$cnt_tags[$note_obj_id] . '</a>';
1342  $prop_text = $this->lng->txt('tagging_tags');
1343  }
1344  $props[] = [
1345  'alert' => false,
1346  'property' => $prop_text,
1347  'value' => $tags_value,
1348  'newline' => $nl
1349  ];
1350  }
1351  }
1352  }
1353 
1354  if (!isset($props)) {
1355  return [];
1356  }
1357 
1358  return $props;
1359  }
1360 
1361  public function insertProperties(): void
1362  {
1363  $props = $this->determineProperties();
1364  $cnt = 1;
1365  if (is_array($props) && count($props) > 0) {
1366  foreach ($props as $prop) {
1367  if ($cnt > 1) {
1368  $this->tpl->touchBlock('separator_prop');
1369  }
1370 
1371  if (isset($prop['alert']) && $prop['alert'] == true) {
1372  $this->tpl->touchBlock('alert_prop');
1373  } else {
1374  $this->tpl->touchBlock('std_prop');
1375  }
1376 
1377  if (isset($prop['newline']) && $prop['newline'] == true && $cnt > 1) {
1378  $this->tpl->touchBlock('newline_prop');
1379  }
1380 
1381  //BEGIN WebDAV: Support hidden property names.
1382  if (
1383  isset($prop['property']) &&
1384  (($prop['propertyNameVisible'] ?? null) !== false) &&
1385  $prop['property'] != ''
1386  ) {
1387  //END WebDAV: Support hidden property names.
1388  $this->tpl->setCurrentBlock('prop_name');
1389  $this->tpl->setVariable('TXT_PROP', $prop['property']);
1390  $this->tpl->parseCurrentBlock();
1391  }
1392 
1393  $this->tpl->setCurrentBlock('item_property');
1394  //BEGIN WebDAV: Support links in property values.
1395  if (isset($prop['link']) && $prop['link']) {
1396  $this->tpl->setVariable('LINK_PROP', $prop['link']);
1397  $this->tpl->setVariable('LINK_VAL_PROP', $prop['value']);
1398  } else {
1399  $this->tpl->setVariable('VAL_PROP', $prop['value']);
1400  }
1401  //END WebDAV: Support links in property values.
1402  $this->tpl->parseCurrentBlock();
1403 
1404  $cnt++;
1405  }
1406  $this->tpl->setCurrentBlock('item_properties');
1407  $this->tpl->parseCurrentBlock();
1408  }
1409  }
1410 
1411  public function insertNoticeProperties(): void
1412  {
1413  $this->getNoticeProperties();
1414  foreach ($this->notice_prop as $property) {
1415  $this->tpl->setCurrentBlock('notice_item');
1416  $this->tpl->setVariable('NOTICE_ITEM_VALUE', $property['value']);
1417  $this->tpl->parseCurrentBlock();
1418  }
1419  $this->tpl->setCurrentBlock('notice_property');
1420  $this->tpl->parseCurrentBlock();
1421  }
1422 
1423  protected function parseConditions(int $toggle_id, array $conditions, bool $obligatory = true): bool
1424  {
1425  $num_required = ilConditionHandler::calculateEffectiveRequiredTriggers($this->ref_id, $this->obj_id);
1426  $num_optional_required =
1427  $num_required -
1428  count($conditions) +
1429  count(ilConditionHandler::getEffectiveOptionalConditionsOfTarget($this->ref_id, $this->obj_id))
1430  ;
1431 
1432  // Check if all conditions are fulfilled
1433  $visible_conditions = [];
1434  $passed_optional = 0;
1435  foreach ($conditions as $condition) {
1436  if ($obligatory && !$condition['obligatory']) {
1437  continue;
1438  }
1439  if (!$obligatory && $condition['obligatory']) {
1440  continue;
1441  }
1442 
1443  if ($this->tree->isDeleted($condition['trigger_ref_id'])) {
1444  continue;
1445  }
1446 
1447  $ok = ilConditionHandler::_checkCondition($condition) && !ilMemberViewSettings::getInstance()->isActive();
1448 
1449  if (!$ok) {
1450  $visible_conditions[] = $condition['id'];
1451  }
1452 
1453  if (!$obligatory && $ok) {
1454  ++$passed_optional;
1455  // optional passed
1456  if ($passed_optional >= $num_optional_required) {
1457  return true;
1458  }
1459  }
1460  }
1461 
1462  $missing_cond_exist = false;
1463  foreach ($conditions as $condition) {
1464  if (!in_array($condition['id'], $visible_conditions)) {
1465  continue;
1466  }
1467 
1468  $operator = ilConditionHandlerGUI::translateOperator($condition['trigger_obj_id'], $condition['operator'], $condition['value']);
1469  $cond_txt = $operator . ' ' . $condition['value'];
1470 
1471  // display trigger item
1472  $class = $this->obj_definition->getClassName($condition['trigger_type']);
1473  $location = $this->obj_definition->getLocation($condition['trigger_type']);
1474  if ($class == '' && $location == '') {
1475  continue;
1476  }
1477  $missing_cond_exist = true;
1478 
1479  $full_class = 'ilObj' . $class . 'ListGUI';
1480  $item_list_gui = new $full_class($this->context);
1481  $item_list_gui->setMode(self::IL_LIST_AS_TRIGGER);
1482  $item_list_gui->enablePath(false);
1483  $item_list_gui->enableIcon(true);
1484  $item_list_gui->setConditionDepth($this->condition_depth + 1);
1485  $item_list_gui->setParentRefId($this->ref_id);
1486  $item_list_gui->addCustomProperty($this->lng->txt('precondition_required_itemlist'), $cond_txt, false, true);
1487  $item_list_gui->enableCommands($this->commands_enabled, $this->std_cmd_only);
1488  $item_list_gui->enableProperties($this->properties_enabled);
1489 
1490  $trigger_html = $item_list_gui->getListItemHTML(
1491  $condition['trigger_ref_id'],
1492  $condition['trigger_obj_id'],
1493  ilObject::_lookupTitle($condition['trigger_obj_id']),
1494  ''
1495  );
1496  $this->tpl->setCurrentBlock('precondition');
1497  if ($trigger_html == '') {
1498  $trigger_html = $this->lng->txt('precondition_not_accessible');
1499  }
1500  $this->tpl->setVariable('TXT_CONDITION', trim($cond_txt));
1501  $this->tpl->setVariable('TRIGGER_ITEM', $trigger_html);
1502  $this->tpl->parseCurrentBlock();
1503  }
1504 
1505  if ($missing_cond_exist && $obligatory) {
1506  $this->tpl->setCurrentBlock('preconditions');
1507  $this->tpl->setVariable('CONDITION_TOGGLE_ID', '_obl_' . $toggle_id);
1508  $this->tpl->setVariable('TXT_PRECONDITIONS', $this->lng->txt('preconditions_obligatory_hint'));
1509  $this->tpl->parseCurrentBlock();
1510  } elseif ($missing_cond_exist && !$obligatory) {
1511  $this->tpl->setCurrentBlock('preconditions');
1512  $this->tpl->setVariable('CONDITION_TOGGLE_ID', '_opt_' . $toggle_id);
1513  $this->tpl->setVariable(
1514  'TXT_PRECONDITIONS',
1515  sprintf(
1516  $this->lng->txt('preconditions_optional_hint'),
1517  $num_optional_required - $passed_optional
1518  )
1519  );
1520  $this->tpl->parseCurrentBlock();
1521  }
1522 
1523  return !$missing_cond_exist;
1524  }
1525 
1529  public function insertPreconditions(): void
1530  {
1531  // do not show multi level conditions (messes up layout)
1532  if ($this->condition_depth > 0) {
1533  return;
1534  }
1535 
1536  if ($this->context == self::CONTEXT_WORKSPACE) {
1537  return;
1538  }
1539 
1540  if (isset($this->condition_target) && is_array($this->condition_target)
1541  && count($this->condition_target) > 0) {
1542  $conditions = ilConditionHandler::_getEffectiveConditionsOfTarget(
1543  (int) $this->condition_target['ref_id'],
1544  (int) $this->condition_target['obj_id'],
1545  $this->condition_target['target_type'] ?? ''
1546  );
1547  } else {
1548  $conditions = ilConditionHandler::_getEffectiveConditionsOfTarget($this->ref_id, $this->obj_id);
1549  }
1550 
1551  if (sizeof($conditions)) {
1552  for ($i = 0; $i < count($conditions); $i++) {
1553  $conditions[$i]['title'] = ilObject::_lookupTitle($conditions[$i]['trigger_obj_id']);
1554  }
1555  $conditions = ilArrayUtil::sortArray($conditions, 'title', 'DESC');
1556 
1557  ++self::$js_unique_id;
1558  // Show obligatory and optional preconditions seperated
1559  $all_done_obl = $this->parseConditions(self::$js_unique_id, $conditions);
1560  $all_done_opt = $this->parseConditions(self::$js_unique_id, $conditions, false);
1561 
1562  if (!$all_done_obl || !$all_done_opt) {
1563  $this->tpl->setCurrentBlock('preconditions_toggle');
1564  $this->tpl->setVariable('PRECONDITION_TOGGLE_INTRO', $this->lng->txt('precondition_toggle'));
1565  $this->tpl->setVariable('PRECONDITION_TOGGLE_TRIGGER', $this->lng->txt('show'));
1566  $this->tpl->setVariable('PRECONDITION_TOGGLE_ID', self::$js_unique_id);
1567  $this->tpl->setVariable('TXT_PRECONDITION_SHOW', $this->lng->txt('show'));
1568  $this->tpl->setVariable('TXT_PRECONDITION_HIDE', $this->lng->txt('hide'));
1569  $this->tpl->parseCurrentBlock();
1570  }
1571  }
1572  }
1573 
1577  public function insertCommand(
1578  string $href,
1579  string $text,
1580  string $frame = '',
1581  string $img = '',
1582  string $cmd = '',
1583  string $onclick = ''
1584  ): void {
1585  // #11099
1586  $checksum = md5($href . $text);
1587  if ($href !== '#' && in_array($checksum, $this->prevent_duplicate_commands)) {
1588  return;
1589  }
1590 
1591  if ($href !== '#') {
1592  $this->prevent_duplicate_commands[] = $checksum;
1593  }
1594 
1595  if ($cmd === 'mount_webfolder') {
1596  $onclick = "triggerWebDAVModal('$href')";
1597  $href = '#';
1599  }
1600 
1601  $action = $this->ui->factory()
1602  ->button()
1603  ->shy($text, $href);
1604 
1605  if ($frame !== '') {
1606  $action = $this->ui->factory()->link()->standard($text, $href)->withOpenInNewViewport(true);
1607  }
1608 
1609  if ($onclick !== '') {
1610  $action = $action->withAdditionalOnLoadCode(function ($id) use ($onclick): string {
1611  return "$('#$id').click(function(){" . $onclick . ';});';
1612  });
1613  }
1614 
1615 
1616 
1617  $this->current_actions[] = $action;
1618  }
1619 
1620  public function insertDeleteCommand(): void
1621  {
1622  if ($this->std_cmd_only) {
1623  return;
1624  }
1625 
1626  if (is_object($this->getContainerObject()) and
1628  if ($this->checkCommandAccess('delete', '', $this->ref_id, $this->type)) {
1629  $this->ctrl->setParameter($this->getContainerObject(), 'item_ref_id', $this->getCommandId());
1630  $cmd_link = $this->ctrl->getLinkTarget($this->getContainerObject(), 'delete');
1631  $this->insertCommand($cmd_link, $this->lng->txt('delete'));
1632  $this->adm_commands_included = true;
1633  }
1634  return;
1635  }
1636 
1637  if ($this->checkCommandAccess('delete', '', $this->ref_id, $this->type)) {
1638  $this->ctrl->setParameter(
1639  $this->container_obj,
1640  'ref_id',
1641  $this->container_obj->getObject()->getRefId()
1642  );
1643  $this->ctrl->setParameter($this->container_obj, 'item_ref_id', $this->getCommandId());
1644  $cmd_link = $this->ctrl->getLinkTarget($this->container_obj, 'delete');
1645  $this->insertCommand($cmd_link, $this->lng->txt('delete'));
1646  $this->adm_commands_included = true;
1647  }
1648  }
1649 
1650  public function insertLinkCommand(): void
1651  {
1652  $objDefinition = $this->obj_definition;
1653 
1654  if ($this->std_cmd_only) {
1655  return;
1656  }
1657 
1658  // #17307
1659  if (
1660  !$this->checkCommandAccess('delete', '', $this->ref_id, $this->type) ||
1661  !$objDefinition->allowLink($this->type)
1662  ) {
1663  return;
1664  }
1665 
1666  // BEGIN PATCH Lucene search
1667  if ($this->getContainerObject() instanceof ilAdministrationCommandHandling) {
1668  $this->ctrl->setParameter($this->getContainerObject(), 'item_ref_id', $this->getCommandId());
1669  $cmd_link = $this->ctrl->getLinkTarget($this->getContainerObject(), 'link');
1670  $this->insertCommand($cmd_link, $this->lng->txt('link'));
1671  $this->adm_commands_included = true;
1672  return;
1673  }
1674  // END PATCH Lucene Search
1675 
1676  // if the permission is changed here, it has
1677  // also to be changed in ilContainerGUI, admin command check
1678  $this->ctrl->setParameter(
1679  $this->container_obj,
1680  'ref_id',
1681  $this->container_obj->getObject()->getRefId()
1682  );
1683  $this->ctrl->setParameter($this->container_obj, 'item_ref_id', $this->getCommandId());
1684  $cmd_link = $this->ctrl->getLinkTarget($this->container_obj, 'link');
1685  $this->insertCommand($cmd_link, $this->lng->txt('link'));
1686  $this->adm_commands_included = true;
1687  }
1688 
1689  public function insertCutCommand(bool $to_repository = false): void
1690  {
1691  if ($this->std_cmd_only) {
1692  return;
1693  }
1694  // BEGIN PATCH Lucene search
1695  if (
1697  ) {
1698  if ($this->checkCommandAccess('delete', '', $this->ref_id, $this->type)) {
1699  $this->ctrl->setParameter($this->getContainerObject(), 'item_ref_id', $this->getCommandId());
1700  $cmd_link = $this->ctrl->getLinkTarget($this->getContainerObject(), 'cut');
1701  $this->insertCommand($cmd_link, $this->lng->txt('move'));
1702  $this->adm_commands_included = true;
1703  }
1704  return;
1705  }
1706  // END PATCH Lucene Search
1707 
1708  // if the permission is changed here, it has
1709  // also to be changed in ilContainerContentGUI, determineAdminCommands
1710  if ($this->checkCommandAccess('delete', '', $this->ref_id, $this->type) && $this->container_obj->getObject()) {
1711  $this->ctrl->setParameter(
1712  $this->container_obj,
1713  'ref_id',
1714  $this->container_obj->getObject()->getRefId()
1715  );
1716  $this->ctrl->setParameter($this->container_obj, 'item_ref_id', $this->getCommandId());
1717 
1718  if (!$to_repository) {
1719  $cmd_link = $this->ctrl->getLinkTarget($this->container_obj, 'cut');
1720  $this->insertCommand($cmd_link, $this->lng->txt('move'));
1721  } else {
1722  $cmd_link = $this->ctrl->getLinkTarget($this->container_obj, 'cut_for_repository');
1723  $this->insertCommand($cmd_link, $this->lng->txt('wsp_move_to_repository'));
1724  }
1725 
1726  $this->adm_commands_included = true;
1727  }
1728  }
1729 
1730  public function insertCopyCommand(bool $to_repository = false): void
1731  {
1732  if ($this->std_cmd_only) {
1733  return;
1734  }
1735 
1736  if ($this->checkCommandAccess('copy', 'copy', $this->ref_id, $this->type) &&
1737  $this->obj_definition->allowCopy($this->type)) {
1738  if ($this->context != self::CONTEXT_WORKSPACE && $this->context != self::CONTEXT_WORKSPACE_SHARING) {
1739  $this->ctrl->setParameterByClass('ilobjectcopygui', 'source_id', $this->getCommandId());
1740  $cmd_copy = $this->ctrl->getLinkTargetByClass([get_class($this->container_obj), 'ilobjectcopygui'], 'initTargetSelection');
1741  $this->insertCommand($cmd_copy, $this->lng->txt('copy'));
1742  } else {
1743  $this->ctrl->setParameter(
1744  $this->container_obj,
1745  'ref_id',
1746  $this->container_obj->getObject()->getRefId()
1747  );
1748  $this->ctrl->setParameter($this->container_obj, 'item_ref_id', $this->getCommandId());
1749 
1750  if (!$to_repository) {
1751  $cmd_copy = $this->ctrl->getLinkTarget($this->container_obj, 'copy');
1752  $this->insertCommand($cmd_copy, $this->lng->txt('copy'));
1753  } else {
1754  $cmd_copy = $this->ctrl->getLinkTarget($this->container_obj, 'copy_to_repository');
1755  $this->insertCommand($cmd_copy, $this->lng->txt('wsp_copy_to_repository'));
1756  }
1757  }
1758 
1759  $this->adm_commands_included = true;
1760  }
1761  }
1762 
1763  public function insertPasteCommand(): void
1764  {
1765  if ($this->std_cmd_only) {
1766  return;
1767  }
1768 
1769  if (!$this->obj_definition->isContainer(ilObject::_lookupType($this->obj_id))) {
1770  return;
1771  }
1772 
1773  if (
1775  $this->clipboard->hasEntries()
1776  ) {
1777  $this->ctrl->setParameter($this->getContainerObject(), 'item_ref_id', $this->getCommandId());
1778  $cmd_link = $this->ctrl->getLinkTarget($this->getContainerObject(), 'paste');
1779  $this->insertCommand($cmd_link, $this->lng->txt('paste'));
1780  $this->adm_commands_included = true;
1781  }
1782  }
1783 
1784  public function insertSubscribeCommand(): void
1785  {
1786  if ($this->std_cmd_only
1787  || $this->user->getId() === ANONYMOUS_USER_ID
1788  || !$this->getContainerObject() instanceof ilDesktopItemHandling
1789  || $this->settings->get('rep_favourites', '0') !== '1') {
1790  return;
1791  }
1792 
1794 
1795  // #17467 - add ref_id to link (in repository only!)
1796  if (
1797  is_object($this->container_obj) &&
1798  !($this->container_obj instanceof ilAdministrationCommandHandling) &&
1799  method_exists($this->container_obj, 'getObject') &&
1800  is_object($this->container_obj->getObject())
1801  ) {
1802  $this->ctrl->setParameter(
1803  $this->container_obj,
1804  'ref_id',
1805  $this->container_obj->getObject()->getRefId()
1806  );
1807  }
1808  if ($this->getContainerObject() instanceof ilDesktopItemHandling) {
1809  $this->ctrl->setParameter($this->container_obj, 'type', $type);
1810  $this->ctrl->setParameter($this->container_obj, 'item_ref_id', $this->getCommandId());
1811 
1812  if (!$this->fav_manager->ifIsFavourite($this->user->getId(), $this->getCommandId())) {
1813  // Pass type and object ID to ilAccess to improve performance
1814  if ($this->checkCommandAccess('read', '', $this->ref_id, $this->type, $this->obj_id)) {
1815  $cmd_link = $this->ctrl->getLinkTarget($this->container_obj, 'addToDesk');
1816  $this->insertCommand($cmd_link, $this->lng->txt('rep_add_to_favourites'));
1817  }
1818  } else {
1819  $cmd_link = $this->ctrl->getLinkTarget($this->container_obj, 'removeFromDesk');
1820  $this->insertCommand($cmd_link, $this->lng->txt('rep_remove_from_favourites'));
1821  }
1822 
1823  $this->ctrl->clearParameters($this->container_obj);
1824  }
1825  }
1826 
1827  public function insertInfoScreenCommand(): void
1828  {
1829  if ($this->std_cmd_only) {
1830  return;
1831  }
1832  $this->insertCommand(
1833  $this->getCommandLink('infoScreen'),
1834  $this->lng->txt('info_short'),
1835  $this->getCommandFrame('infoScreen'),
1836  ilUtil::getImagePath('standard/icon_info.svg')
1837  );
1838  }
1839 
1843  public function insertCommonSocialCommands(bool $header_actions = false): void
1844  {
1845  if ($this->std_cmd_only || $this->user->isAnonymous()) {
1846  return;
1847  }
1848 
1849  $this->lng->loadLanguageModule('notes');
1850  $this->lng->loadLanguageModule('tagging');
1851  $cmd_frame = $this->getCommandFrame('infoScreen');
1852 
1853  // reference objects have translated ids, revert to originals
1854  $note_ref_id = $this->ref_id;
1855  if ($this->reference_ref_id) {
1856  $note_ref_id = $this->reference_ref_id;
1857  }
1858 
1859  $js_updater = $header_actions
1860  ? 'il.Object.redrawActionHeader();'
1861  : 'il.Object.redrawListItem(' . $note_ref_id . ')';
1862 
1863  $comments_enabled = $this->isCommentsActivated($this->type, $this->ref_id, $this->obj_id, $header_actions);
1864  if ($comments_enabled) {
1865  $this->insertCommand(
1866  '#',
1867  $this->lng->txt('notes_comments'),
1868  $cmd_frame,
1869  '',
1870  '',
1871  ilNoteGUI::getListCommentsJSCall($this->ajax_hash, $js_updater)
1872  );
1873  }
1874 
1875  if ($this->notes_enabled) {
1876  $this->insertCommand(
1877  '#',
1878  $this->lng->txt('notes'),
1879  $cmd_frame,
1880  '',
1881  '',
1882  ilNoteGUI::getListNotesJSCall($this->ajax_hash, $js_updater)
1883  );
1884  }
1885 
1886  if ($this->tags_enabled) {
1887  $this->insertCommand(
1888  '#',
1889  $this->lng->txt('tagging_set_tag'),
1890  $cmd_frame,
1891  '',
1892  '',
1893  ilTaggingGUI::getListTagsJSCall($this->ajax_hash, $js_updater)
1894  );
1895  }
1896  }
1897 
1904  public function insertTimingsCommand(): void
1905  {
1906  if (
1907  $this->std_cmd_only || is_null($this->container_obj) ||
1908  !method_exists($this->container_obj, 'getObject') ||
1909  !is_object($this->container_obj->getObject())
1910  ) {
1911  return;
1912  }
1913 
1914  $parent_ref_id = $this->container_obj->getObject()->getRefId();
1915  $parent_type = $this->container_obj->getObject()->getType();
1916 
1917  // #18737
1918  if ($this->reference_ref_id) {
1919  $this->ctrl->setParameterByClass('ilconditionhandlergui', 'ref_id', $this->reference_ref_id);
1920  }
1921 
1922  if (
1923  $this->checkCommandAccess('write', '', $parent_ref_id, $parent_type) ||
1924  $this->checkCommandAccess('write', '', $this->ref_id, $this->type)
1925  ) {
1926  $this->ctrl->setParameterByClass(
1927  get_class($this->container_obj),
1928  'tl_id',
1929  $this->ref_id
1930  );
1931  $time_limit_link = $this->ctrl->getLinkTargetByClass(
1932  get_class($this->container_obj),
1933  'editAvailabilityPeriod'
1934  );
1935  $this->insertCommand($time_limit_link, $this->lng->txt('edit_availability_period'));
1936  $this->ctrl->clearParameterByClass(
1937  get_class($this->container_obj),
1938  'tl_id',
1939  );
1940 
1941  $this->ctrl->setParameterByClass(
1942  'ilconditionhandlergui',
1943  'cadh',
1944  $this->ajax_hash
1945  );
1946  $this->ctrl->setParameterByClass(
1947  'ilconditionhandlergui',
1948  'parent_id',
1949  $parent_ref_id
1950  );
1951 
1952  $availbility_link = $this->ctrl->getLinkTargetByClass(
1953  [$this->gui_class_name, 'ilcommonactiondispatchergui', 'ilobjectactivationgui', 'ilconditionhandlergui'],
1954  'listConditions'
1955  );
1956 
1957  $this->insertCommand($availbility_link, $this->lng->txt('preconditions'));
1958  }
1959 
1960  if ($this->reference_ref_id) {
1961  $this->ctrl->setParameterByClass('ilconditionhandlergui', 'ref_id', $this->ref_id);
1962  }
1963  }
1964 
1968  private function populateCommands(
1969  bool $for_header
1970  ): void {
1971  $commands = $this->getCommands();
1972  if (!$this->getCommandsStatus() || $this->commandsNeedToBeHidden($for_header)) {
1973  foreach ($commands as $command) {
1974  if ($command['default'] === true) {
1975  $this->default_command = $command['granted'] === true ? $this->createDefaultCommand($command) : [];
1976  }
1977  return;
1978  }
1979  return;
1980  }
1981 
1982  $this->ctrl->setParameterByClass($this->gui_class_name, 'ref_id', $this->ref_id);
1983 
1984  $this->current_actions = [];
1985  $this->default_command = [];
1986  $this->prevent_duplicate_commands = [];
1987 
1988  // we only allow the following commands inside the header actions
1989  $valid_header_commands = ['mount_webfolder'];
1990 
1991  foreach ($commands as $command) {
1992  if ($for_header && !in_array($command['cmd'], $valid_header_commands)
1993  || $command['granted'] === false) {
1994  continue;
1995  }
1996 
1997  if ($command['default'] !== true) {
1998  if (!$this->std_cmd_only) {
1999  // workaround for repository frameset
2000  $command['link'] =
2001  $this->appendRepositoryFrameParameter($command['link']);
2002 
2003  $cmd_link = $command['link'];
2004  $txt = ($command['lang_var'] == '')
2005  ? $command['txt']
2006  : $this->lng->txt($command['lang_var']);
2007  $this->insertCommand(
2008  $cmd_link,
2009  $txt,
2010  $command['frame'],
2011  $command['img'],
2012  $command['cmd']
2013  );
2014  }
2015  } else {
2016  $this->default_command = $this->createDefaultCommand($command);
2017  }
2018  }
2019 
2020  // custom commands
2021  if (is_array($this->cust_commands)) {
2022  foreach ($this->cust_commands as $command) {
2023  if ($command instanceof Button) {
2024  $this->current_actions[] = $command;
2025  continue;
2026  }
2027 
2028  $this->insertCommand(
2029  $command['link'],
2030  $this->lng->txt($command['lang_var']),
2031  $command['frame'],
2032  '',
2033  $command['cmd'] ?? '',
2034  $command['onclick']
2035  );
2036  }
2037  }
2038  $this->insertLPSettingsCommand();
2039 
2040  // info screen command
2041  if ($this->getInfoScreenStatus()) {
2042  $this->insertInfoScreenCommand();
2043  }
2044 
2045  $this->insertLPCommand();
2046 
2047  if (!$this->isMode(self::IL_LIST_AS_TRIGGER)) {
2048  // edit timings
2049  if ($this->timings_enabled) {
2050  $this->insertTimingsCommand();
2051  }
2052 
2053  // delete
2054  if ($this->delete_enabled) {
2055  $this->insertDeleteCommand();
2056  }
2057 
2058  // link
2059  if ($this->link_enabled) {
2060  $this->insertLinkCommand();
2061  }
2062 
2063  // cut
2064  if ($this->cut_enabled) {
2065  $this->insertCutCommand();
2066  }
2067 
2068  // copy
2069  if ($this->copy_enabled) {
2070  $this->insertCopyCommand();
2071  }
2072 
2073  // cut/copy from workspace to repository
2074  if ($this->repository_transfer_enabled) {
2075  $this->insertCutCommand(true);
2076  $this->insertCopyCommand(true);
2077  }
2078 
2079  // subscribe
2080  if ($this->subscribe_enabled) {
2081  $this->insertSubscribeCommand();
2082  }
2083 
2084  // multi download
2085  if ($this->multi_download_enabled && $for_header) {
2086  $this->insertMultiDownloadCommand();
2087  }
2088 
2089  // BEGIN PATCH Lucene search
2090  if ($this->cut_enabled or $this->link_enabled) {
2091  $this->insertPasteCommand();
2092  }
2093  // END PATCH Lucene Search
2094  }
2095 
2096  // common social commands (comment, notes, tags)
2097  if (!$this->isMode(self::IL_LIST_AS_TRIGGER)) {
2098  $this->insertCommonSocialCommands($for_header);
2099  }
2100  }
2101 
2105  // there is one case, where no action menu should be displayed:
2106  // public area, category, no info tab
2107  // todo: make this faster and remove type specific implementation if possible
2108  private function commandsNeedToBeHidden(
2109  bool $for_header
2110  ): bool {
2111  if (!$for_header
2112  && $this->user->getId() === ANONYMOUS_USER_ID && $this->checkInfoPageOnAsynchronousRendering()
2113  && $this->object_properties->getPropertyInfoTabVisibility()) {
2114  return true;
2115  }
2116  return false;
2117  }
2118 
2119  public function enableComments(bool $value, bool $enable_comments_settings = true): void
2120  {
2121  if ($this->settings->get('disable_comments')) {
2122  $value = false;
2123  }
2124 
2125  $this->comments_enabled = $value;
2126  $this->comments_settings_enabled = $enable_comments_settings;
2127  }
2128 
2129  public function enableNotes(bool $value): void
2130  {
2131  if ($this->settings->get('disable_notes')) {
2132  $value = false;
2133  }
2134 
2135  $this->notes_enabled = $value;
2136  }
2137 
2138  public function enableTags(bool $value): void
2139  {
2140  $tags_set = new ilSetting('tags');
2141  if (!$tags_set->get('enable')) {
2142  $value = false;
2143  }
2144  $this->tags_enabled = $value;
2145  }
2146 
2147  public function enableRating(
2148  bool $value,
2149  ?string $text = null,
2150  bool $categories = false,
2151  ?array $ctrl_path = null,
2152  bool $force_rate_parent = false
2153  ): void {
2154  $this->rating_enabled = $value;
2155 
2156  if ($this->rating_enabled) {
2157  $this->rating_categories_enabled = $categories;
2158  $this->rating_text = $text;
2159  $this->rating_ctrl_path = $ctrl_path;
2160  $this->force_rate_parent = $force_rate_parent;
2161  }
2162  }
2163 
2169  public function enableMultiDownload(bool $value): void
2170  {
2171  $folder_set = new ilSetting('fold');
2172  if (!$folder_set->get('enable_multi_download')) {
2173  $value = false;
2174  }
2175  $this->multi_download_enabled = $value;
2176  }
2177 
2178  public function insertMultiDownloadCommand(): void
2179  {
2180  if ($this->std_cmd_only) {
2181  return;
2182  }
2183 
2184  if (!$this->obj_definition->isContainer(ilObject::_lookupType($this->obj_id))) {
2185  return;
2186  }
2187 
2188  if ($this->getContainerObject() instanceof ilContainerGUI) {
2189  $this->ctrl->setParameter($this->getContainerObject(), 'type', '');
2190  $this->ctrl->setParameter($this->getContainerObject(), 'item_ref_id', '');
2191  $this->ctrl->setParameter($this->getContainerObject(), 'active_node', '');
2192  // bugfix mantis 24559
2193  // undoing an erroneous change inside mantis 23516 by
2194  // adding 'Download Multiple Objects'-functionality for non-admins
2195  // as they don't have the possibility to use the multi-download-capability of the manage-tab
2196  $user_id = $this->user->getId();
2197  $hasAdminAccess = $this->access->checkAccessOfUser($user_id, 'crs_admin', $this->ctrl->getCmd(), $this->requested_ref_id);
2198  // to still prevent duplicate download functions for admins
2199  // the following if-else statement keeps the redirection for admins
2200  // while letting other course members access the original multi-download functionality
2201  if ($hasAdminAccess) {
2202  $cmd = ($this->requested_cmd == 'enableAdministrationPanel')
2203  ? 'render'
2204  : 'enableAdministrationPanel';
2205  } else {
2206  $cmd = ($this->requested_cmd == 'enableMultiDownload')
2207  ? 'render'
2208  : 'enableMultiDownload';
2209  }
2210  $cmd_link = $this->ctrl->getLinkTarget($this->getContainerObject(), $cmd);
2211  $this->insertCommand($cmd_link, $this->lng->txt('download_multiple_objects'));
2212  }
2213  }
2214 
2215  public function enableDownloadCheckbox(int $ref_id): void
2216  {
2217  // TODO: delegate to list object class!
2218  if (!$this->getContainerObject()->isActiveAdministrationPanel() || $this->clipboard->hasEntries()) {
2219  if (
2220  in_array($this->type, ['file', 'fold']) &&
2221  $this->access->checkAccess('read', '', $ref_id, $this->type)
2222  ) {
2223  $this->download_checkbox_state = self::DOWNLOAD_CHECKBOX_ENABLED;
2224  } else {
2225  $this->download_checkbox_state = self::DOWNLOAD_CHECKBOX_DISABLED;
2226  }
2227  } else {
2228  $this->download_checkbox_state = self::DOWNLOAD_CHECKBOX_NONE;
2229  }
2230  }
2231 
2232  public function getDownloadCheckboxState(): int
2233  {
2235  }
2236 
2240  public static function prepareJsLinks(
2241  string $redraw_url,
2242  string $notes_url,
2243  string $tags_url,
2245  ): void {
2246  global $DIC;
2247 
2248  if (is_null($tpl)) {
2249  $tpl = $DIC['tpl'];
2250  }
2251 
2252  //if ($notes_url) {
2253  $DIC->notes()->gui()->initJavascript($notes_url);
2254  //}
2255 
2256  if ($tags_url) {
2257  ilTaggingGUI::initJavascript($tags_url, $tpl);
2258  }
2259 
2260  if ($redraw_url) {
2261  $tpl->addOnLoadCode('il.Object.setRedrawAHUrl("' . $redraw_url . '");');
2262  }
2263  }
2264 
2265  public function setHeaderSubObject(?string $type, ?int $id): void
2266  {
2267  $this->sub_obj_type = $type;
2268  $this->sub_obj_id = (int) $id;
2269  }
2270 
2271  public function addHeaderIcon(
2272  string $id,
2273  string $img,
2274  ?string $tooltip = null,
2275  ?string $onclick = null,
2276  ?string $status_text = null,
2277  ?string $href = null
2278  ): void {
2279  $this->header_icons[$id] = [
2280  'img' => $img,
2281  'tooltip' => $tooltip,
2282  'onclick' => $onclick,
2283  'status_text' => $status_text,
2284  'href' => $href
2285  ];
2286  }
2287 
2288  public function addHeaderIconHTML(string $id, string $html): void
2289  {
2290  $this->header_icons[$id] = $html;
2291  }
2292 
2293  public function addHeaderGlyph(string $id, ILIAS\UI\Component\Symbol\Glyph\Glyph $glyph, $onclick = null): void
2294  {
2295  $this->header_icons[$id] = ['glyph' => $glyph, 'onclick' => $onclick];
2296  }
2297 
2298  public function setAjaxHash(string $hash): void
2299  {
2300  $this->ajax_hash = $hash;
2301  }
2302 
2303  public function getHeaderAction(?ilGlobalTemplateInterface $main_tpl = null): string
2304  {
2305  if ($main_tpl == null) {
2306  $main_tpl = $this->main_tpl;
2307  }
2308 
2309  $htpl = new ilTemplate('tpl.header_action.html', true, true, 'components/ILIAS/ILIASObject');
2310 
2311  $redraw_js = 'il.Object.redrawActionHeader();';
2312 
2313  // tags
2314  if ($this->tags_enabled) {
2316  $this->obj_id,
2317  ilObject::_lookupType($this->obj_id),
2318  0,
2319  '',
2320  $this->user->getId()
2321  );
2322  if (count($tags) > 0) {
2323  $this->lng->loadLanguageModule('tagging');
2324 
2325  $f = $this->ui->factory();
2326  $this->addHeaderGlyph(
2327  'tags',
2328  $f->symbol()->glyph()->tag('#')
2329  ->withCounter($f->counter()->status(count($tags))),
2330  ilTaggingGUI::getListTagsJSCall($this->ajax_hash, $redraw_js)
2331  );
2332  }
2333  }
2334 
2335  // notes and comments
2336  $comments_enabled = $this->isCommentsActivated($this->type, $this->ref_id, $this->obj_id, true, false);
2337  if ($this->notes_enabled || $comments_enabled) {
2338  $type = ($this->sub_obj_type == '') ? $this->type : $this->sub_obj_type;
2339  $context = $this->notes_service->data()->context($this->obj_id, $this->sub_obj_id, $type);
2340  $cnt[$this->obj_id][Note::PUBLIC] = $this->notes_service->domain()->getNrOfCommentsForContext($context);
2341  $cnt[$this->obj_id][Note::PRIVATE] = $this->notes_service->domain()->getNrOfNotesForContext($context);
2342  if (
2343  $this->notes_enabled &&
2344  isset($cnt[$this->obj_id][Note::PRIVATE]) &&
2345  $cnt[$this->obj_id][Note::PRIVATE] > 0
2346  ) {
2347  $f = $this->ui->factory();
2348  $this->addHeaderGlyph(
2349  'notes',
2350  $f->symbol()->glyph()->note('#')
2351  ->withCounter($f->counter()->status((int) $cnt[$this->obj_id][Note::PRIVATE])),
2352  ilNoteGUI::getListNotesJSCall($this->ajax_hash, $redraw_js)
2353  );
2354  }
2355 
2356  if (
2357  $comments_enabled &&
2358  isset($cnt[$this->obj_id][Note::PUBLIC]) &&
2359  $cnt[$this->obj_id][Note::PUBLIC] > 0
2360  ) {
2361  $this->lng->loadLanguageModule('notes');
2362  $f = $this->ui->factory();
2363  $this->addHeaderGlyph(
2364  'comments',
2365  $f->symbol()->glyph()->comment('#')
2366  ->withCounter($f->counter()->status((int) $cnt[$this->obj_id][Note::PUBLIC])),
2367  ilNoteGUI::getListCommentsJSCall($this->ajax_hash, $redraw_js)
2368  );
2369  }
2370  }
2371 
2372  // rating
2373  if ($this->rating_enabled) {
2374  $rating_gui = new ilRatingGUI();
2375  $rating_gui->enableCategories($this->rating_categories_enabled);
2376  // never rate sub objects from header action!
2377  $rating_gui->setObject($this->obj_id, $this->type);
2378  if ($this->rating_text) {
2379  $rating_gui->setYourRatingText($this->rating_text);
2380  }
2381 
2382  $ajax_hash = $this->force_rate_parent
2384  : $this->ajax_hash;
2385  $this->ctrl->setParameterByClass('ilRatingGUI', 'cadh', $ajax_hash);
2386  $this->ctrl->setParameterByClass('ilRatingGUI', 'rnsb', true);
2387  if ($this->rating_ctrl_path) {
2388  $rating_gui->setCtrlPath($this->rating_ctrl_path);
2389  $ajax_url = $this->ctrl->getLinkTargetByClass($this->rating_ctrl_path, 'saveRating', '', true);
2390  } else {
2391  $ajax_url = $this->ctrl->getLinkTargetByClass('ilRatingGUI', 'saveRating', '', true);
2392  }
2393  $main_tpl->addOnLoadCode('il.Object.setRatingUrl("' . $ajax_url . '");');
2394  $this->addHeaderIconHTML(
2395  'rating',
2396  $rating_gui->getHTML(
2397  true,
2398  $this->checkCommandAccess('read', '', $this->ref_id, $this->type),
2399  'il.Object.saveRating(%rating%);'
2400  )
2401  );
2402  }
2403 
2404  if ($this->header_icons) {
2405  $chunks = [];
2406  foreach ($this->header_icons as $id => $attr) {
2407  $id = 'headp_' . $id;
2408 
2409  if (is_array($attr)) {
2410  if (isset($attr['glyph']) && $attr['glyph']) {
2411  if ($attr['onclick']) {
2412  $htpl->setCurrentBlock('prop_glyph_oc');
2413  $htpl->setVariable('GLYPH_ONCLICK', $attr['onclick']);
2414  $htpl->parseCurrentBlock();
2415  }
2416  $renderer = $this->ui->renderer();
2417  $html = $renderer->render($attr['glyph']);
2418  $htpl->setCurrentBlock('prop_glyph');
2419  $htpl->setVariable('GLYPH', $html);
2420  $htpl->parseCurrentBlock();
2421  } else {
2422  if ($attr['onclick']) {
2423  $htpl->setCurrentBlock('onclick');
2424  $htpl->setVariable('PROP_ONCLICK', $attr['onclick']);
2425  $htpl->parseCurrentBlock();
2426  }
2427 
2428  if ($attr['status_text']) {
2429  $htpl->setCurrentBlock('status');
2430  $htpl->setVariable('PROP_TXT', $attr['status_text']);
2431  $htpl->parseCurrentBlock();
2432  }
2433 
2434 
2435  $htpl->setCurrentBlock('prop');
2436  if ($attr['href'] || $attr['onclick']) {
2437  $htpl->setVariable('TAG', 'a');
2438  } else {
2439  $htpl->setVariable('TAG', 'span');
2440  }
2441  $htpl->setVariable('PROP_ID', $id);
2442  $htpl->setVariable('IMG_SRC', $attr['img']);
2443  if ($attr['href'] != '') {
2444  $htpl->setVariable('PROP_HREF', ' href="' . $attr['href'] . '" ');
2445  }
2446 
2447  if ($attr['tooltip']) {
2448  $htpl->setVariable('IMG_ADDITIONAL', "alt=\"{$attr['tooltip']}\" title=\"{$attr['tooltip']}\"");
2449  }
2450  $htpl->parseCurrentBlock();
2451  }
2452  } else {
2453  $chunks[] = $attr;
2454  }
2455  }
2456 
2457  if (sizeof($chunks)) {
2458  $htpl->setVariable(
2459  'PROP_CHUNKS',
2460  implode('&nbsp;&nbsp;&nbsp;', $chunks) . '&nbsp;&nbsp;&nbsp;'
2461  );
2462  }
2463  }
2464 
2465  $this->setTitle(ilObject::_lookupTitle($this->obj_id));
2466  $dropdown_label = '<span class="hidden-xs">' .
2467  $this->lng->txt('actions') .
2468  '</span>';
2469  $dropdown = $this->getCommandsDropdown($dropdown_label, true);
2470  $htpl->setVariable(
2471  'ACTION_DROP_DOWN',
2472  $this->ui->renderer()->render($dropdown)
2473  );
2474 
2475  if ($this->cust_modals !== []) {
2476  $htpl->setVariable('TRIGGERED_MODALS', $this->ui->renderer()->render($this->cust_modals));
2477  }
2478 
2479  return $htpl->get();
2480  }
2481 
2482 
2487  public function appendRepositoryFrameParameter(string $link): string
2488  {
2489  // we should get rid of this nonsense with 4.4 (alex)
2490  $base_class = $this->request_wrapper->retrieve('baseClass', $this->refinery->kindlyTo()->string());
2491  if (
2492  (strtolower($base_class) != 'ilrepositorygui') &&
2493  is_int(strpos($link, 'baseClass=ilRepositoryGUI'))
2494  ) {
2495  if ($this->type != 'frm') {
2496  $link = ilUtil::appendUrlParameterString($link, 'rep_frame=1');
2497  }
2498  }
2499 
2500  return $link;
2501  }
2502 
2503  protected function modifyTitleLink(string $default_link): string
2504  {
2505  if ($this->default_command_params) {
2506  $params = [];
2507  foreach ($this->default_command_params as $name => $value) {
2508  $params[] = $name . '=' . $value;
2509  }
2510  $params = implode('&', $params);
2511 
2512 
2513  // #12370
2514  if (!stristr($default_link, '?')) {
2515  $default_link = ($default_link . '?' . $params);
2516  } else {
2517  $default_link = ($default_link . '&' . $params);
2518  }
2519  }
2520  return $default_link;
2521  }
2522 
2526  public function modifySAHSlaunch(string $link, string $target): array
2527  {
2528  if (strstr($link, ilSAHSPresentationGUI::class) === false) {
2529  return [$link, $target];
2530  }
2531 
2532  $sahs_obj = new ilObjSAHSLearningModule($this->ref_id);
2533  $om = $sahs_obj->getOpenMode();
2534  $width = $sahs_obj->getWidth();
2535  $height = $sahs_obj->getHeight();
2536  if (($om == 5 || $om == 1) && $width > 0 && $height > 0) {
2537  $om++;
2538  }
2539  if ($om !== 0 && !$this->http->agent()->isMobile()) {
2540  $this->default_command['frame'] = '';
2541  $link =
2542  'javascript:void(0); onclick=startSAHS(\'' .
2543  $link .
2544  '\',\'' .
2545  $target .
2546  '\',' .
2547  $om .
2548  ',' .
2549  $width .
2550  ',' .
2551  $height .
2552  ');'
2553  ;
2554  } else {
2555  $target = "ilContObj" . $this->ref_id;
2556  }
2557  return [$link, $target];
2558  }
2559 
2560  public function insertPath(): void
2561  {
2562  if ($this->getPathStatus() != false) {
2563  if (!$this->path_gui instanceof \ilPathGUI) {
2564  $path_gui = new \ilPathGUI();
2565  } else {
2566  $path_gui = $this->path_gui;
2567  }
2568 
2569  $path_gui->enableTextOnly(!$this->path_linked);
2570  $path_gui->setUseImages(false);
2571 
2572  $start_node = ROOT_FOLDER_ID;
2573  if ($this->path_start_node) {
2574  $start_node = $this->path_start_node;
2575  }
2576 
2577  $this->tpl->setCurrentBlock('path_item');
2578  $this->tpl->setVariable('PATH_ITEM', $path_gui->getPath($start_node, $this->ref_id));
2579  $this->tpl->parseCurrentBlock();
2580 
2581  $this->tpl->setCurrentBlock('path');
2582  $this->tpl->setVariable('TXT_LOCATION', $this->lng->txt('locator'));
2583  $this->tpl->parseCurrentBlock();
2584  }
2585  }
2586 
2587  public function insertProgressInfo(): void
2588  {
2589  }
2590 
2591  public function insertIconsAndCheckboxes(): void
2592  {
2593  $cnt = 0;
2594  if ($this->getCheckboxStatus()) {
2595  $this->tpl->setCurrentBlock('check');
2596  $this->tpl->setVariable('VAL_ID', $this->getCommandId());
2597  $this->tpl->setVariable('CHECK_TITLE', $this->lng->txt('select') . ' ' . $this->getTitle());
2598  $this->tpl->parseCurrentBlock();
2599  $cnt += 1;
2600  } elseif ($this->getDownloadCheckboxState() != self::DOWNLOAD_CHECKBOX_NONE) {
2601  $this->tpl->setCurrentBlock('check_download');
2602  $this->tpl->setVariable('CHECK_DOWNLOAD_TITLE', $this->lng->txt('download') . ' ' . $this->getTitle());
2603  if ($this->getDownloadCheckboxState() == self::DOWNLOAD_CHECKBOX_ENABLED) {
2604  $this->tpl->setVariable('VAL_ID', $this->getCommandId());
2605  } else {
2606  $this->tpl->setVariable('VAL_VISIBILITY', 'visibility: hidden;" disabled="disabled');
2607  }
2608  $this->tpl->parseCurrentBlock();
2609  $cnt += 1;
2610  } elseif ($this->getExpandStatus()) {
2611  $this->tpl->setCurrentBlock('expand');
2612 
2613  if ($this->isExpanded()) {
2614  $this->ctrl->setParameter($this->container_obj, 'expand', -1 * $this->obj_id);
2615  // 'view' added, see #19922
2616  $this->tpl->setVariable('EXP_HREF', $this->ctrl->getLinkTarget($this->container_obj, 'view', $this->getUniqueItemId(true)));
2617  $this->ctrl->clearParameters($this->container_obj);
2618  $this->tpl->setVariable('EXP_IMG', ilUtil::getImagePath('nav/tree_exp.svg'));
2619  $this->tpl->setVariable('EXP_ALT', $this->lng->txt('collapse'));
2620  } else {
2621  $this->ctrl->setParameter($this->container_obj, 'expand', $this->obj_id);
2622  // 'view' added, see #19922
2623  $this->tpl->setVariable('EXP_HREF', $this->ctrl->getLinkTarget($this->container_obj, 'view', $this->getUniqueItemId(true)));
2624  $this->ctrl->clearParameters($this->container_obj);
2625  $this->tpl->setVariable('EXP_IMG', ilUtil::getImagePath('nav/tree_col.svg'));
2626  $this->tpl->setVariable('EXP_ALT', $this->lng->txt('expand'));
2627  }
2628 
2629  $this->tpl->parseCurrentBlock();
2630  $cnt += 1;
2631  }
2632 
2633  if ($this->getIconStatus()) {
2634  if ($cnt == 1) {
2635  $this->tpl->touchBlock('i_1');
2636  }
2637 
2638  $this->tpl->setCurrentBlock('icon');
2639  $this->tpl->setVariable('ALT_ICON', $this->buildTranslatedType());
2640 
2641  $this->tpl->setVariable(
2642  'SRC_ICON',
2643  $this->getTypeIcon()
2644  );
2645  $this->tpl->parseCurrentBlock();
2646  $cnt += 1;
2647  }
2648 
2649  $this->tpl->touchBlock('d_' . $cnt);
2650  }
2651 
2655  public function getTypeIcon(): string
2656  {
2657  return ilObject::getIconForReference(
2658  $this->ref_id,
2659  $this->obj_id,
2660  'small',
2661  $this->getIconImageType()
2662  );
2663  }
2664 
2665  public function insertSubItems(): void
2666  {
2667  foreach ($this->sub_item_html as $sub_html) {
2668  $this->tpl->setCurrentBlock('subitem');
2669  $this->tpl->setVariable('SUBITEM', $sub_html);
2670  $this->tpl->parseCurrentBlock();
2671  }
2672  }
2673 
2674  public function insertPositionField(): void
2675  {
2676  if ($this->position_enabled) {
2677  $this->tpl->setCurrentBlock('position');
2678  $this->tpl->setVariable('POS_ID', $this->position_field_index);
2679  $this->tpl->setVariable('POS_VAL', $this->position_value);
2680  $this->tpl->parseCurrentBlock();
2681  }
2682  }
2683 
2688  public function adminCommandsIncluded(): bool
2689  {
2690  return $this->adm_commands_included;
2691  }
2692 
2696  public function getListItemHTML(
2697  int $ref_id,
2698  int $obj_id,
2699  string $title,
2700  string $description
2701  ): string {
2702  // this variable stores whether any admin commands
2703  // are included in the output
2704  $this->adm_commands_included = false;
2705 
2706  // only for performance exploration
2707  $type = ilObject::_lookupType($obj_id);
2708 
2709  $this->initItem($ref_id, $obj_id, $type, $title, $description);
2710 
2711  if ($this->rating_enabled) {
2712  if (ilRating::hasRatingInListGUI($this->obj_id, $this->type)) {
2713  $may_rate = $this->checkCommandAccess('read', '', $this->ref_id, $this->type);
2714  $rating = new ilRatingGUI();
2715  $rating->setObject($this->obj_id, $this->type);
2716  $this->addCustomProperty(
2717  '',
2718  $rating->getListGUIProperty($this->ref_id, $may_rate, $this->ajax_hash, $this->parent_ref_id),
2719  false,
2720  true
2721  );
2722  }
2723  }
2724 
2725  // visible check
2726  if (!$this->checkCommandAccess('visible', '', $ref_id, '', $obj_id)) {
2727  $this->resetCustomData();
2728  return '';
2729  }
2730 
2731  // BEGIN WEBDAV
2732  if ($type == 'file' and ilObjFileAccess::_isFileHidden($title)) {
2733  $this->resetCustomData();
2734  return '';
2735  }
2736  // END WEBDAV
2737 
2738  $this->tpl = new ilTemplate(
2739  static::$tpl_file_name,
2740  true,
2741  true,
2742  static::$tpl_component,
2743  'DEFAULT',
2744  false,
2745  true
2746  );
2747 
2748  if ($this->getCommandsStatus()) {
2749  if (!$this->getSeparateCommands()) {
2750  $dropdown = $this->getCommandsDropdown($title);
2751  $this->tpl->setVariable(
2752  'COMMAND_SELECTION_LIST',
2753  $this->ui->renderer()->render($dropdown)
2754  );
2755  }
2756  }
2757 
2758  if ($this->getProgressInfoStatus()) {
2759  $this->insertProgressInfo();
2760  }
2761 
2762  // insert title and describtion
2763  $this->insertTitle();
2764  if (!$this->isMode(self::IL_LIST_AS_TRIGGER)) {
2765  if ($this->getDescriptionStatus()) {
2766  $this->insertDescription();
2767  }
2768  }
2769 
2770  if ($this->getSearchFragmentStatus()) {
2771  $this->insertSearchFragment();
2772  }
2773 
2774  // properties
2775  if ($this->getPropertiesStatus()) {
2776  $this->insertProperties();
2777  }
2778 
2779  // notice properties
2780  if ($this->getNoticePropertiesStatus()) {
2781  $this->insertNoticeProperties();
2782  }
2783 
2784  // preconditions
2785  if ($this->getPreconditionsStatus()) {
2786  $this->insertPreconditions();
2787  }
2788 
2789  // path
2790  $this->insertPath();
2791 
2792  if ($this->getItemDetailLinkStatus()) {
2793  $this->insertItemDetailLinks();
2794  }
2795 
2796  // icons and checkboxes
2797  $this->insertIconsAndCheckboxes();
2798 
2799  // input field for position
2800  $this->insertPositionField();
2801 
2802  // subitems
2803  $this->insertSubItems();
2804 
2805  $this->resetCustomData();
2806 
2807  $this->tpl->setVariable('DIV_CLASS', 'ilContainerListItemOuter');
2808  $this->tpl->setVariable(
2809  'DIV_ID',
2810  'data-list-item-id="' . $this->getUniqueItemId(true) . '" id = "' . $this->getUniqueItemId(true) . '"'
2811  );
2812  $this->tpl->setVariable('ADDITIONAL', $this->getAdditionalInformation());
2813 
2814  if (is_object($this->getContainerObject())) {
2815  // #11554 - make sure that internal ids are reset
2816  $this->ctrl->setParameter($this->getContainerObject(), 'item_ref_id', '');
2817  }
2818 
2819  // if file upload is enabled the content is wrapped by a UI dropzone.
2820  $content = $this->tpl->get();
2821  $file_upload_dropzone = new ilObjFileUploadDropzone($this->ref_id, $content);
2822  if ($this->context === self::CONTEXT_REPOSITORY
2823  && ($this->requested_cmd === "view" || $this->requested_cmd === "" || $this->requested_cmd === "render")
2824  && $file_upload_dropzone->isUploadAllowed($this->type)
2825  && !(new ModeSessionRepository())->isAdminMode()
2826  ) {
2827  return $file_upload_dropzone->getDropzoneHtml();
2828  }
2829 
2830  return $content;
2831  }
2832 
2836  protected function resetCustomData(): void
2837  {
2838  // #15747
2839  $this->cust_prop = [];
2840  $this->cust_commands = [];
2841  $this->cust_modals = [];
2842  $this->sub_item_html = [];
2843  $this->position_enabled = false;
2844  }
2845 
2849  public function setParentRefId(int $ref_id): void
2850  {
2851  $this->parent_ref_id = $ref_id;
2852  }
2853 
2860  public function getUniqueItemId(bool $as_div = false): string
2861  {
2862  // use correct id for references
2863  $id_ref = $this->ref_id;
2864  if ($this->reference_ref_id > 0) {
2865  $id_ref = $this->reference_ref_id;
2866  }
2867 
2868  // add unique identifier for preconditions (objects can appear twice in same container)
2869  if ($this->condition_depth) {
2870  $id_ref .= '_pc' . $this->condition_depth;
2871  }
2872 
2873  // unique
2874  $id_ref .= '_pref_' . $this->parent_ref_id;
2875 
2876  if (!$as_div) {
2877  return $id_ref;
2878  } else {
2879  // action menu [yellow] toggle
2880  return 'lg_div_' . $id_ref;
2881  }
2882  }
2883 
2887  public function getCommandsHTML(string $title = ''): string
2888  {
2889  return $this->ui->renderer()->render($this->getCommandsDropdown($title, false));
2890  }
2891 
2892  private function getCommandsDropdown(string $title, bool $for_header = false): StandardDropdown
2893  {
2894  $this->populateCommands($for_header);
2895  return $this->ui->factory()
2896  ->dropdown()
2897  ->standard($this->current_actions)
2898  ->withAriaLabel(sprintf(
2899  $this->lng->txt('actions_for'),
2900  htmlspecialchars(addslashes($title))
2901  ));
2902  }
2903 
2907  public function isSideBlock(): bool
2908  {
2909  return false;
2910  }
2911 
2912  public function setBoldTitle(bool $bold_title): void
2913  {
2914  $this->bold_title = $bold_title;
2915  }
2916 
2917  public function isTitleBold(): bool
2918  {
2919  return $this->bold_title;
2920  }
2921 
2922  public static function preloadCommonProperties(array $obj_ids, int $context): void
2923  {
2924  global $DIC;
2925  $lng = $DIC->language();
2926  $ilSetting = $DIC->settings();
2927  $ilUser = $DIC->user();
2928  $notes_manager = $DIC->notes()->internal()->domain()->notes();
2929 
2930  if ($context == self::CONTEXT_REPOSITORY) {
2931  $active_notes = !$ilSetting->get('disable_notes');
2932  $active_comments = !$ilSetting->get('disable_comments');
2933 
2934  if ($active_comments) {
2935  // needed for action
2936  self::$comments_activation = $DIC->notes()
2937  ->internal()
2938  ->domain()
2939  ->notes()->commentsActiveMultiple($obj_ids);
2940  }
2941 
2942  // properties are optional
2943  if ($ilSetting->get('comments_tagging_in_lists')) {
2944  if ($active_notes || $active_comments) {
2945  // @todo: should be refactored, see comment in notes db repo
2946  self::$cnt_notes = $notes_manager->countNotesAndCommentsMultipleObjects(
2947  $obj_ids,
2948  true
2949  );
2950 
2951  $lng->loadLanguageModule('notes');
2952  }
2953 
2954  $tags_set = new ilSetting('tags');
2955  if ($tags_set->get('enable')) {
2956  $all_users = (bool) $tags_set->get('enable_all_users');
2957 
2958  if (!$ilSetting->get('comments_tagging_in_lists_tags')) {
2959  self::$cnt_tags = ilTagging::_countTags($obj_ids, $all_users);
2960  } else {
2961  $tag_user_id = null;
2962  if (!$all_users) {
2963  $tag_user_id = $ilUser->getId();
2964  }
2965  self::$tags = ilTagging::_getListTagsForObjects($obj_ids, $tag_user_id);
2966  }
2967 
2968  $lng->loadLanguageModule('tagging');
2969  }
2970  }
2971 
2972  $lng->loadLanguageModule('rating');
2973  }
2974 
2975  self::$preload_done = true;
2976  }
2977 
2981  protected function isCommentsActivated(
2982  string $type,
2983  int $ref_id,
2984  int $obj_id,
2985  bool $header_actions,
2986  bool $check_write_access = true
2987  ): bool {
2988  if ($this->comments_enabled) {
2989  if (!$this->comments_settings_enabled) {
2990  return true;
2991  }
2992  if ($check_write_access && $this->checkCommandAccess('write', '', $ref_id, $type)) {
2993  return true;
2994  }
2995  // fallback to single object check if no preloaded data
2996  // only the repository does preloadCommonProperties() yet
2997  if (!$header_actions && self::$preload_done) {
2998  if (isset(self::$comments_activation[$obj_id]) &&
2999  self::$comments_activation[$obj_id]) {
3000  return true;
3001  }
3002  } elseif ($this->notes_service->domain()->commentsActive($obj_id)) {
3003  return true;
3004  }
3005  }
3006  return false;
3007  }
3008 
3012  public function enableTimings(bool $status): void
3013  {
3014  $this->timings_enabled = $status;
3015  }
3016 
3020  public function getAsListItem(
3021  int $ref_id,
3022  int $obj_id,
3023  string $type,
3024  string $title,
3025  string $description
3026  ): ?Item {
3027  $ui = $this->ui;
3028 
3029  // even b tag produced bugs, see #32304
3030  $description = $this->refinery->encode()->htmlSpecialCharsAsEntities()->transform(
3031  $description
3032  );
3033 
3034  $this->initItem(
3035  $ref_id,
3036  $obj_id,
3037  $type,
3038  $title,
3039  $description
3040  );
3041 
3042  $this->enableCommands(true);
3043 
3044  // actions
3045  $this->populateCommands(false);
3046 
3047  $dropdown = $this->getCommandsDropdown($title);
3048  $def_command = $this->getDefaultCommand();
3049 
3050  if ($def_command['link'] ?? false) {
3051  list($def_command['link'], $def_command['frame']) =
3052  $this->modifySAHSlaunch($def_command['link'], $def_command['frame']);
3053  $new_viewport = !in_array($def_command['frame'], ['', '_top', '_self', '_parent'], true);
3054  $link = $this->ui->factory()
3055  ->link()
3056  ->standard($this->getTitle(), $def_command['link'])
3057  ->withOpenInNewViewport($new_viewport);
3058  $list_item = $ui->factory()->item()->standard($link);
3059  } else {
3060  $list_item = $ui->factory()->item()->standard($this->getTitle());
3061  }
3062 
3063  if ($description != '') {
3064  $list_item = $list_item->withDescription($description);
3065  }
3066  $list_item = $list_item->withActions($dropdown)->withLeadIcon(
3067  $this->ui->factory()->symbol()->icon()->custom(
3068  $this->getTypeIcon(),
3069  $this->buildTranslatedType(),
3070  'medium'
3071  )
3072  );
3073 
3074 
3075  $l = [];
3076  $this->enableComments(true);
3077  $this->enableNotes(true);
3078  $this->enableTags(true);
3079  $this->enableRating(true);
3080 
3081  foreach ($this->determineProperties() as $p) {
3082  //if ($p['property'] !== $this->lng->txt('learning_progress')) {
3083  $l[(string) $p['property']] = (string) $p['value'];
3084  //}
3085  }
3086  if (count($l) > 0) {
3087  $list_item = $list_item->withProperties($l);
3088  }
3089 
3090  return $list_item;
3091  }
3092 
3096  public function getAsCard(
3097  int $ref_id,
3098  int $obj_id,
3099  string $type,
3100  string $title,
3101  string $description
3102  ): ?RepositoryObject {
3103  $ui = $this->ui;
3104 
3105  $title = $this->refinery->encode()->htmlSpecialCharsAsEntities()->transform($title);
3106  // even b tag produced bugs, see #32304
3107  $description = $this->refinery->encode()->htmlSpecialCharsAsEntities()->transform(
3108  $description
3109  );
3110 
3111  $this->initItem(
3112  $ref_id,
3113  $obj_id,
3114  $type,
3115  $title,
3116  $description
3117  );
3118 
3119  $user = $this->user;
3120  $access = $this->access;
3121 
3122  $this->enableCommands(true);
3123 
3124  $sections = [];
3125  if ($description !== '') {
3126  $sections[] = $ui->factory()->legacy()->content('<div class="il-multi-line-cap-3">' . $description . '</div>');
3127  }
3128 
3129  $this->populateCommands(false);
3130 
3131  $def_command = $this->getDefaultCommand();
3132 
3133  $dropdown = $this->getCommandsDropdown($title);
3134 
3135  // workaround for #26205
3136  // we should get rid of _top links completely and gifure our how
3137  // to manage scorm links better
3138  $def_cmd_frame = ($def_command['frame'] ?? '');
3139  if ($def_cmd_frame === '_top') {
3140  $def_cmd_frame = '';
3141  }
3142  $def_cmd_link = ($def_command['link'] ?? '');
3143 
3144  // workaround for scorm
3145  list($modified_link, $def_cmd_frame) =
3146  $this->modifySAHSlaunch($def_cmd_link, $def_cmd_frame);
3147 
3148  $image = $this->getTileImage();
3149 
3150  if ($def_cmd_link != '') { // #24256
3151  if ($def_cmd_frame !== '' && ($modified_link === $def_cmd_link)) {
3152  $signal = (new SignalGenerator())->create();
3153  $this->main_tpl->addOnLoadCode(
3154  "$(document).on('{$signal->getId()}', function(event, signalData) {"
3155  . ' window.open("' . str_replace(
3156  '&amp;',
3157  '&',
3158  $def_cmd_link
3159  ) . '", "' . $def_cmd_frame . '");'
3160  . '});'
3161  );
3162 
3163  $image = $image->withAction($signal);
3164 
3165  $button =
3166  $ui->factory()->button()->shy($title, '')->appendOnClick($signal);
3167  $title = $ui->renderer()->render($button);
3168  } else {
3169  $image = $image->withAction($modified_link);
3170  }
3171  }
3172 
3173  if ($type == 'sess') {
3174  if ($title != '') {
3175  $title = ': ' . $title;
3176  }
3177  $app_info = ilSessionAppointment::_lookupAppointment($obj_id);
3178  $title = ilSessionAppointment::_appointmentToString(
3179  $app_info['start'],
3180  $app_info['end'],
3181  (bool) $app_info['fullday']
3182  ) . $title;
3183  }
3184 
3185  $icon = $this->ui->factory()->symbol()->icon()->custom(
3186  $this->getTypeIcon(),
3187  $this->buildTranslatedType(),
3188  'medium'
3189  );
3190 
3191  // card title action
3192  $card_title_action = '';
3193  if ($def_cmd_link != '' && ($def_cmd_frame == '' || $modified_link != $def_cmd_link)) { // #24256
3194  $card_title_action = $modified_link;
3195  } elseif ($def_cmd_link == '' &&
3196  $this->getInfoScreenStatus() &&
3197  $access->checkAccessOfUser(
3198  $user->getId(),
3199  'visible',
3200  '',
3201  $ref_id
3202  )) {
3203  $card_title_action = ilLink::_getLink($ref_id);
3204  if ($image->getAction() == '') {
3205  $image = $image->withAction($card_title_action);
3206  }
3207  }
3208 
3209  $card = $ui->factory()->card()->repositoryObject(
3210  $title . '<span data-list-item-id="' . $this->getUniqueItemId(true) . '"></span>',
3211  $image
3212  )->withObjectIcon(
3213  $icon
3214  )->withActions(
3215  $dropdown
3216  );
3217 
3218  if ($card_title_action != '') {
3219  $card = $card->withTitleAction($card_title_action);
3220  }
3221 
3222  $l = [];
3223  foreach ($this->determineProperties() as $p) {
3224  if (isset($p['alert']) && $p['alert'] == true
3225  && isset($p['property']) && $p['property'] !== $this->lng->txt('learning_progress')) {
3226  $l[(string) $p['property']] = (string) $p['value'];
3227  }
3228  }
3229  if (count($l) > 0) {
3230  $prop_list = $ui->factory()->listing()->descriptive($l);
3231  $sections[] = $prop_list;
3232  }
3233  if (count($sections) > 0) {
3234  $card = $card->withSections($sections);
3235  }
3236 
3237  $lp = ilLPStatus::getListGUIStatus($obj_id, false);
3238  if (is_array($lp) && array_key_exists('status', $lp)) {
3239  $percentage = (int) ilLPStatus::_lookupPercentage($obj_id, $this->user->getId());
3240  if ($lp['status'] == ilLPStatus::LP_STATUS_COMPLETED_NUM) {
3241  $percentage = 100;
3242  }
3243 
3244  $card = $card->withProgress(
3245  $ui->factory()
3246  ->chart()
3247  ->progressMeter()
3248  ->mini(100, $percentage)
3249  );
3250  }
3251 
3252  return $card;
3253  }
3254 
3255  public function checkInfoPageOnAsynchronousRendering(): bool
3256  {
3257  return false;
3258  }
3259 
3260  private function getTileImage(): Image
3261  {
3262  return $this->object_properties->getPropertyTileImage()
3263  ->getTileImage()->getImage($this->ui->factory()->image());
3264  }
3265 
3269  public function insertLPCommand(): void
3270  {
3271  if ($this->std_cmd_only || !$this->lp_cmd_enabled) {
3272  return;
3273  }
3274  $relevant = ilLPStatus::hasListGUIStatus($this->obj_id);
3275  if ($relevant) {
3276  $cmd_link = $this->getCommandLink('learningProgress');
3277  $this->insertCommand(
3278  $cmd_link,
3279  $this->lng->txt('learning_progress')
3280  );
3281  }
3282  }
3283 
3287  private function insertLPSettingsCommand(): void
3288  {
3289  if (!$this->lp_settings_cmd_enabled
3290  || !ilObjUserTracking::_enabledLearningProgress()
3291  || ilObjectLP::getTypeClass($this->type) === ''
3292  || ! $this->checkCommandAccess('edit_learning_progress', '', $this->ref_id, $this->type)
3293  ) {
3294  return;
3295  }
3296 
3297  $cmd_link = '';
3298  $this->ctrl->setParameterByClass(ilLearningProgressGUI::class, 'ref_id', $this->ref_id);
3299  switch ($this->type) {
3300  case 'sahs':
3301  switch (ilObjSAHSLearningModule::_lookupSubType($this->obj_id)) {
3302  case 'scorm2004':
3303  $scorm_class = ilObjSCORM2004LearningModuleGUI::class;
3304  break;
3305  case 'scorm':
3306  $scorm_class = ilObjSCORMLearningModuleGUI::class;
3307  break;
3308  default:
3309  $scorm_class = '';
3310  break;
3311  }
3312 
3313  $cmd_link = $this->ctrl->getLinkTargetByClass([
3314  ilSAHSEditGUI::class,
3315  $scorm_class,
3316  ilLearningProgressGUI::class,
3317  ilLPListOfSettingsGUI::class
3318  ]);
3319  break;
3320 
3321  case 'lm':
3322  $cmd_link = $this->ctrl->getLinkTargetByClass([
3323  ilLMEditorGUI::class,
3324  ilObjLearningModuleGUI::class,
3325  ilLearningProgressGUI::class,
3326  ilLPListOfSettingsGUI::class
3327  ]);
3328  break;
3329 
3330  case 'lso':
3331  $cmd_link = $this->ctrl->getLinkTargetByClass([
3332  ilObjLearningSequenceGUI::class,
3333  ilLearningProgressGUI::class,
3334  ilLPListOfSettingsGUI::class
3335  ]);
3336  break;
3337 
3338  case 'copa':
3339  case 'iass':
3340  case 'tst':
3341  case 'htlm':
3342  case 'exc':
3343  case 'svy':
3344  case 'mcst':
3345  case 'file':
3346  case 'crs':
3347  $gui_class = 'ilObj' . $this->obj_definition->getClassName($this->type) . 'GUI';
3348  $cmd_link = $this->ctrl->getLinkTargetByClass([
3349  ilRepositoryGUI::class,
3350  $gui_class,
3351  ilLearningProgressGUI::class,
3352  ilLPListOfSettingsGUI::class
3353  ]);
3354  break;
3355 
3356  case 'prgr':
3357  case 'prg':
3358  case 'lso':
3359  break;
3360  default:
3361  break;
3362  }
3363 
3364  $this->ctrl->setParameterByClass('ilrepositorygui', 'ref_id', $this->requested_ref_id);
3365  if ($cmd_link !== '') {
3366  $this->insertCommand(
3367  $cmd_link,
3368  $this->lng->txt('listaction_learning_progress_settings')
3369  );
3370  }
3371  }
3372 
3373  private function buildTranslatedType(): string
3374  {
3375  if ($this->obj_definition->isPlugin($this->getIconImageType())) {
3376  return ilObjectPlugin::lookupTxtById($this->getIconImageType(), 'obj_' . $this->getIconImageType());
3377  }
3378 
3379  return $this->lng->txt('obj_' . $this->getIconImageType());
3380  }
3381 }
getCommands()
get all current commands for a specific ref id (in the permission context of the current user) ...
This describes commonalities between the different modals.
Definition: Modal.php:34
setHeaderSubObject(?string $type, ?int $id)
parseConditions(int $toggle_id, array $conditions, bool $obligatory=true)
insertSearchFragment()
Insert highlighted search fragment.
setConditionTarget(int $ref_id, int $obj_id, string $target_type)
getDescription()
getDescription overwritten in class.ilObjLinkResourceList.php
static appendUrlParameterString(string $a_url, string $a_par, bool $xml_style=false)
$renderer
init()
initialisation
static string $tpl_component
ilListItemAccessCache $acache
modifySAHSlaunch(string $link, string $target)
workaround: SAHS in new javavasript-created window or iframe
const ANONYMOUS_USER_ID
Definition: constants.php:27
setParentRefId(int $ref_id)
Set current parent ref id to enable unique js-ids (sessions, etc.)
setMode(string $mode)
set output mode
enableCommands(bool $status, bool $std_only=false)
setAdditionalInformation(?string $val)
setContainerObject(object $container_obj)
setSearchFragment(string $text)
initItem(int $ref_id, int $obj_id, string $type, string $title='', string $description='')
initialize new item (is called by getItemHTML())
$location
Definition: buildRTE.php:22
if(! $DIC->user() ->getId()||!ilLTIConsumerAccess::hasCustomProviderCreationAccess()) $params
Definition: ltiregstart.php:31
insertPreconditions()
insert all missing preconditions
Interface Observer Contains several chained tasks and infos about them.
setDescription(string $description)
addOnLoadCode(string $a_code, int $a_batch=2)
Add on load code.
checkAccess(string $a_permission, string $a_cmd, int $a_ref_id, string $a_type="", ?int $a_obj_id=null, ?int $a_tree_id=null)
check access for an object (provide $a_type and $a_obj_id if available for better performance) ...
static translateOperator(int $a_obj_id, string $a_operator, string $value='')
checkCommandAccess(string $permission, string $cmd, int $ref_id, string $type, ?int $obj_id=null)
getCommandFrame(string $cmd)
Get command target frame.
static getGotoLink(int $a_node_id, int $a_obj_id, string $a_additional="")
appendRepositoryFrameParameter(string $link)
workaround: all links into the repository (from outside) must tell repository to set up the frameset ...
enableExpand(bool $status)
enableDelete(bool $status)
insertCopyCommand(bool $to_repository=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...
getItemDetailLinkStatus()
get item detail link status
setPositionInputField(string $field_index, string $position_value)
enableMultiDownload(bool $value)
Toggles whether multiple objects can be downloaded at once or not.
small()
description: > This can be used, when space is very scarce and the label cannot be displayed ...
Definition: small.php:34
setDetailsLevel(int $level)
Details level Currently used in Search which shows only limited properties of forums Currently used f...
commandsNeedToBeHidden(bool $for_header)
Fix bug #12417: We hide the action menu when we are in the public area.
ilAccessHandler $access
ILIAS Notes Service $notes_service
ilFavouritesManager $fav_manager
enableSubscribe(bool $status)
ilWorkspaceAccessHandler $ws_access
getCommandsDropdown(string $title, bool $for_header=false)
addCustomCommandButton(Button $button, ?Modal $triggeredModal=null)
enableLinkedPath(bool $status)
ilGlobalTemplateInterface $main_tpl
static initJavascript(string $a_ajax_url, ?ilGlobalTemplateInterface $a_main_tpl=null)
$path
Definition: ltiservices.php:29
enableInfoScreen(bool $info_screen)
static _lookupObjId(int $ref_id)
static lookupOfflineStatus(int $obj_id)
Lookup offline status using objectDataCache.
static string $tpl_file_name
static buildAjaxHash(int $node_type, ?int $node_id, string $obj_type, int $obj_id, ?string $sub_type=null, ?int $sub_id=null, int $news_id=0)
Build ajax hash.
enablePath(bool $path, int $start_node=0, ?\ilPathGUI $path_gui=null)
while($session_entry=$r->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) return null
enablePreconditions(bool $status)
enableSearchFragments(bool $status)
enableProperties(bool $status)
static _getInstance()
Get singleton instance of this class.
collapse()
description: > Example for rendering a collapse glyph.
Definition: collapse.php:43
enableNoticeProperties(bool $status)
Provides fluid interface to RBAC services.
Definition: UIServices.php:24
static http()
Fetches the global http state from ILIAS.
static _getCommands()
get commands
getMode()
get output mode
getProperties()
Get item properties.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
createDefaultCommand(array $command)
Get default command link Overwritten for e.g categories,courses => they return a goto link If search ...
static _checkCondition(array $condition, int $a_usr_id=0)
checks wether a single condition is fulfilled every trigger object type must implement a static metho...
enableComments(bool $value, bool $enable_comments_settings=true)
static _lookupTitle(int $obj_id)
getCommandId()
get command id Normally the ref id.
restrictToGoto(bool $value)
Restrict all actions/links to goto.
static calculateEffectiveRequiredTriggers(int $a_target_ref_id, int $a_target_obj_id, string $a_target_obj_type='')
enableLPSettingsCommand(bool $enabled)
setDefaultCommandParameters(array $params)
global $DIC
Definition: shib_login.php:26
getCommandImage(string $cmd)
Get command icon image.
enableProgressInfo(bool $status)
ilCtrlInterface $ctrl
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 getListTagsJSCall(string $a_hash, ?string $a_update_code=null)
getHeaderAction(?ilGlobalTemplateInterface $main_tpl=null)
Manages items in repository clipboard.
isMode(string $mode)
check current output mode
setConditionDepth(int $depth)
set depth for precondition output (stops at level 5)
getIconImageType()
Returns the icon image type.
disableTitleLink(bool $status)
enableRating(bool $value, ?string $text=null, bool $categories=false, ?array $ctrl_path=null, bool $force_rate_parent=false)
$txt
Definition: error.php:31
addSubItemHTML(string $html)
Add HTML for sub item (used for sessions)
isCommentsActivated(string $type, int $ref_id, int $obj_id, bool $header_actions, bool $check_write_access=true)
Check comments status against comments settings and context.
addCustomCommand(string $link, string $lang_var, string $frame='', string $onclick='')
static getListGUIStatus(int $a_obj_id, bool $a_image_only=true)
enableLearningProgress(bool $enabled)
populateCommands(bool $for_header)
insert all commands into html code
getCustomProperties(array $prop)
insertLPCommand()
insert learning progress command
static getTagsForUserAndObject(int $a_obj_id, string $a_obj_type, int $a_sub_obj_id, string $a_sub_obj_type, int $a_user_id)
ILIAS Refinery Factory $refinery
static getListCommentsJSCall(string $a_hash, ?string $a_update_code=null)
Get list comments js call.
addHeaderIcon(string $id, string $img, ?string $tooltip=null, ?string $onclick=null, ?string $status_text=null, ?string $href=null)
insertCutCommand(bool $to_repository=false)
getTitle()
getTitle overwritten in class.ilObjLinkResourceList.php
addHeaderGlyph(string $id, ILIAS\UI\Component\Symbol\Glyph\Glyph $glyph, $onclick=null)
ilAdvancedMDSubstitution $substitutions
expand()
description: > Example for rendering an expand glyph.
Definition: expand.php:41
enableSubstitutions(bool $status)
insertTimingsCommand()
ks, 23 OCT 2023: This function is badly named and it already was before the changes made today...
static prepareJsLinks(string $redraw_url, string $notes_url, string $tags_url, ?ilGlobalTemplateInterface $tpl=null)
Insert js/ajax links into template.
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
__construct(Container $dic, ilPlugin $plugin)
link(string $caption, string $href, bool $new_viewport=false)
enableCheckbox(bool $status)
setItemDetailLinks(array $detail_links, string $intro_txt='')
set items detail links
getCommandLink(string $cmd)
Get command link url.
catch(InvalidArgumentException) if(!ilDAVActivationChecker::_isActive()) $webdav_dic
Definition: webdav.php:57
ILIAS HTTP Wrapper RequestWrapper $request_wrapper
static getEffectiveOptionalConditionsOfTarget(int $a_target_ref_id, int $a_target_obj_id, string $a_obj_type='')
ClipboardManager $clipboard
$info
Definition: entry_point.php:21
ilObjectDefinition $obj_definition
insertCommand(string $href, string $text, string $frame='', string $img='', string $cmd='', string $onclick='')
insert command button
enableItemDetailLinks(bool $status)
enable item detail links E.g Direct links to chapters or pages
getUriToMountInstructionModalByRef(int $a_ref_id)
disabled()
description: > Example showing how to plug a disabled checkbox into a form
Definition: disabled.php:32
Interface for GUI classes (PDGUI, LuceneSearchGUI...) that have to handle administration commands (cu...
insertCommonSocialCommands(bool $header_actions=false)
Insert common social commands (comments, notes, tagging)
static _lookupType(int $id, bool $reference=false)
enableDescription(bool $status)
static array $comments_activation
addHeaderIconHTML(string $id, string $html)
enableDownloadCheckbox(int $ref_id)
enableRepositoryTransfer(bool $value)
Enable copy/move to repository (from personal workspace)
ilLDAPRoleGroupMapping $ldap_mapping
Class ilObjSCORMLearningModule.
modifyTitleLink(string $default_link)
static getListNotesJSCall(string $a_hash, ?string $a_update_code=null)
Get list notes js call.
addCustomProperty(string $property='', string $value='', bool $alert=false, bool $newline=false)
static sortArray(array $array, string $a_array_sortby_key, string $a_array_sortorder="asc", bool $a_numeric=false, bool $a_keep_keys=false)