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