ILIAS  trunk Revision v12.0_alpha-1540-g00f839d5fa1
class.ilRepositorySearchGUI.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
24use ILIAS\Refinery\Factory as RefineryFactory;
25
39{
40 private array $search_results = [];
41
42 protected array $add_options = [];
43 protected string $default_option = '';
44 protected bool $object_selection = false;
45
46 protected bool $searchable_check = true;
47 protected string $search_title = '';
48
49 private string $search_type = 'usr';
50 private string $string = '';
51 protected bool $user_limitations = true;
52
53 protected bool $stored = false;
54 protected array $callback = [];
55 protected array $role_callback = [];
56
59 protected ?ilPropertyFormGUI $form = null;
60
64 protected $user_filter = null;
65
67
68 protected ilTree $tree;
71 protected ilCtrl $ctrl;
73 protected ?ilObjUser $user = null;
75 protected ilTabsGUI $tabs;
76 protected ilLanguage $lng;
78 private RefineryFactory $refinery;
79
80 public function __construct()
81 {
82 global $DIC;
83
84
85
86 $this->ctrl = $DIC->ctrl();
87 $this->tpl = $DIC->ui()->mainTemplate();
88 $this->tree = $DIC->repositoryTree();
89 $this->ui_renderer = $DIC->ui()->renderer();
90 $this->ui_factory = $DIC->ui()->factory();
91 $this->lng = $DIC->language();
92 $this->rbacreview = $DIC->rbac()->review();
93 $this->refinery = $DIC->refinery();
94 $this->http = $DIC->http();
95 $this->user = $DIC->user();
96 $this->tabs = $DIC->tabs();
97
98 $this->lng->loadLanguageModule('search');
99 $this->lng->loadLanguageModule('crs');
100
101 $this->setTitle($this->lng->txt('add_members_header'));
102
103 $this->__setSearchType();
104 $this->__loadQueries();
105
106 $this->result_obj = new ilSearchResult();
107 $this->result_obj->setMaxHits(1000000);
108 $this->settings = new ilSearchSettings();
109 }
110
111 protected function initUserTypeFromQuery(): string
112 {
113 if ($this->http->wrapper()->query()->has('user_type')) {
114 return $this->http->wrapper()->query()->retrieve(
115 'user_type',
116 $this->refinery->kindlyTo()->string()
117 );
118 }
119 return '';
120 }
121
122 protected function initUserTypeFromPost(): string
123 {
124 if ($this->http->wrapper()->post()->has('user_type')) {
125 return $this->http->wrapper()->post()->retrieve(
126 'user_type',
127 $this->refinery->kindlyTo()->string()
128 );
129 }
130 return '';
131 }
132
141 public function addUserAccessFilterCallable(callable $user_filter): void
142 {
143 $this->user_filter = $user_filter;
144 }
145
146 public function setTitle(string $a_title): void
147 {
148 $this->search_title = $a_title;
149 }
150
151 public function getTitle(): string
152 {
153 return $this->search_title;
154 }
155
156 public function enableSearchableCheck(bool $a_status): void
157 {
158 $this->searchable_check = $a_status;
159 }
160
161 public function isSearchableCheckEnabled(): bool
162 {
164 }
165
166 public function setPrivacyMode(int $privacy_mode): void
167 {
168 $this->privacy_mode = $privacy_mode;
169 }
170
171 public function getPrivacyMode(): int
172 {
173 return $this->privacy_mode;
174 }
175
176 public function getSearchType(): string
177 {
178 return $this->search_type;
179 }
180
181 public function getRoleCallback(): array
182 {
184 }
185
186
195 public static function fillAutoCompleteToolbar(
196 object $parent_object,
197 ?ilToolbarGUI $toolbar = null,
198 array $a_options = [],
199 bool $a_sticky = false
200 ): ilToolbarGUI {
201 global $DIC;
202
203 $ilToolbar = $DIC->toolbar();
204 $lng = $DIC->language();
205 $ilCtrl = $DIC->ctrl();
206 $tree = $DIC->repositoryTree();
207 $user = $DIC->user();
208 $ui_factory = $DIC->ui()->factory();
209 $ui_renderer = $DIC->ui()->renderer();
210
211 if (!$toolbar instanceof ilToolbarGUI) {
212 $toolbar = $ilToolbar;
213 }
214
215 // Fill default options
216 if (!isset($a_options['auto_complete_name'])) {
217 $a_options['auto_complete_name'] = $lng->txt('obj_user');
218 }
219 if (!isset($a_options['auto_complete_size'])) {
220 $a_options['auto_complete_size'] = 15;
221 }
222 if (!isset($a_options['submit_name'])) {
223 $a_options['submit_name'] = $lng->txt('btn_add');
224 }
225 if (!isset($a_options['user_type_default'])) {
226 $a_options['user_type_default'] = null;
227 }
228
229 if (!isset($a_options['add_search'])) {
230 $a_options['add_search'] = false;
231 }
232 if (!isset($a_options['add_from_container'])) {
233 $a_options['add_from_container'] = null;
234 }
235
236 $ajax_url = $ilCtrl->getLinkTargetByClass(
237 array(get_class($parent_object),'ilRepositorySearchGUI'),
238 'doUserAutoComplete',
239 '',
240 true,
241 false
242 );
243
244 $ul = new ilTextInputGUI($a_options['auto_complete_name'], 'user_login');
245 $ul->setDataSource($ajax_url);
246 $ul->setSize($a_options['auto_complete_size']);
247 if (!$a_sticky) {
248 $toolbar->addInputItem($ul, true);
249 } else {
250 $toolbar->addStickyItem($ul, true);
251 }
252
253 if (isset($a_options['user_type']) && count((array) $a_options['user_type'])) {
254 $si = new ilSelectInputGUI("", "user_type");
255 $si->setOptions($a_options['user_type']);
256 $si->setValue($a_options['user_type_default']);
257 if (!$a_sticky) {
258 $toolbar->addInputItem($si);
259 } else {
260 $toolbar->addStickyItem($si);
261 }
262 }
263
265
266 $add_button = ilSubmitButton::getInstance();
267 $add_button->setCaption($a_options['submit_name'], false);
268 $add_button->setCommand('addUserFromAutoComplete');
269
270 if (!$a_sticky || $clip->hasContent()) {
271 $toolbar->addButtonInstance($add_button);
272 } else {
273 $toolbar->addStickyItem($add_button);
274 }
275
276 if ($clip->hasContent()) {
277 $clip_button = ilSubmitButton::getInstance();
278 $clip_button->addCSSClass('btn btndefault');
279 $lng->loadLanguageModule('user');
280 $clip_button->setCaption($lng->txt('clipboard_add_from_btn'), false);
281 $clip_button->setCommand('showClipboard');
282
283 $toolbar->addButtonInstance($clip_button);
284 }
285
286 if ($a_options['add_search'] ||
287 is_numeric($a_options['add_from_container'])) {
288 $lng->loadLanguageModule("search");
289
290 $toolbar->addSeparator();
291
292 if ($a_options['add_search']) {
293 $button = $ui_factory->button()->standard(
294 $lng->txt('search_users'),
295 $ilCtrl->getLinkTargetByClass(strtolower(self::class), '')
296 );
297 $toolbar->addComponent($button);
298 }
299
300 if (is_numeric($a_options['add_from_container'])) {
301 $parent_ref_id = (int) $a_options['add_from_container'];
302 $parent_container_ref_id = $tree->checkForParentType($parent_ref_id, "grp");
303 $parent_container_type = "grp";
304 if (!$parent_container_ref_id) {
305 $parent_container_ref_id = $tree->checkForParentType($parent_ref_id, "crs");
306 $parent_container_type = "crs";
307 }
308 if ($parent_container_ref_id) {
309 if ($a_options['add_search']) {
310 $toolbar->addSpacer();
311 }
312
313 $ilCtrl->setParameterByClass('ilRepositorySearchGUI', "list_obj", ilObject::_lookupObjId($parent_container_ref_id));
314
315 $button = $ui_factory->button()->standard(
316 $lng->txt('search_add_members_from_container_' . $parent_container_type),
317 $ilCtrl->getLinkTargetByClass(array(get_class($parent_object),'ilRepositorySearchGUI'), 'listUsers')
318 );
319 $toolbar->addComponent($button);
320 }
321 }
322 }
323
324 $toolbar->setFormAction(
325 $ilCtrl->getFormActionByClass(
326 array(
327 get_class($parent_object),
328 'ilRepositorySearchGUI')
329 )
330 );
331 return $toolbar;
332 }
333
334 protected function doUserAutoComplete(): ?string
335 {
336 // hide anonymout request
337 if ($this->user->getId() == ANONYMOUS_USER_ID) {
338 echo json_encode(new stdClass(), JSON_THROW_ON_ERROR);
339 exit;
340 }
341 if (!$this->http->wrapper()->query()->has('autoCompleteField')) {
342 $a_fields = [
343 'login',
344 'firstname',
345 'lastname',
346 'email'
347 ];
348 $result_field = 'login';
349 } else {
350 $auto_complete_field = $this->http->wrapper()->query()->retrieve(
351 'autoCompleteField',
352 $this->refinery->kindlyTo()->string()
353 );
354 $a_fields = [$auto_complete_field];
355 $result_field = $auto_complete_field;
356 }
357 $auto = new ilUserAutoComplete();
358 $auto->setPrivacyMode($this->getPrivacyMode());
359
360 if ($this->http->wrapper()->query()->has('fetchall')) {
361 $auto->setLimit(ilUserAutoComplete::MAX_ENTRIES);
362 }
363
364 $auto->setMoreLinkAvailable(true);
365 $auto->setSearchFields($a_fields);
366 $auto->setResultField($result_field);
367 $auto->enableFieldSearchableCheck(true);
368 $auto->setUserLimitations($this->getUserLimitations());
369 if (is_callable($this->user_filter)) { // #0024249
370 $auto->addUserAccessFilterCallable(Closure::fromCallable($this->user_filter));
371 }
372
373 $query = '';
374 if ($this->http->wrapper()->post()->has('term')) {
375 $query = $this->http->wrapper()->post()->retrieve(
376 'term',
377 $this->refinery->kindlyTo()->string()
378 );
379 }
380 if ($query === "") {
381 if ($this->http->wrapper()->query()->has('term')) {
382 $query = $this->http->wrapper()->query()->retrieve(
383 'term',
384 $this->refinery->kindlyTo()->string()
385 );
386 }
387 }
388 echo $auto->getList($query);
389 exit;
390 }
391
392
393 public function setString(string $a_str): void
394 {
395 $search = ilSession::get('search');
396 $search['string'] = $this->string = $a_str;
397 ilSession::set('search', $search);
398 }
399 public function getString(): string
400 {
401 return $this->string;
402 }
403
404 public function executeCommand(): bool
405 {
406 $next_class = $this->ctrl->getNextClass($this);
407 $cmd = $this->ctrl->getCmd();
408 switch ($next_class) {
409 default:
410 if (!$cmd) {
411 $cmd = "showSearch";
412 }
413 $this->$cmd();
414 break;
415 }
416 return true;
417 }
418
419 public function __clearSession(): void
420 {
421 ilSession::clear('rep_search');
422 ilSession::clear('append_results');
423 ilSession::clear('rep_query');
424 ilSession::clear('rep_search_type');
425 }
426
427 public function cancel(): void
428 {
429 $this->ctrl->returnToParent($this);
430 }
431
432 public function start(): bool
433 {
434 // delete all session info
435 $this->__clearSession();
436 $this->showSearch();
437
438 return true;
439 }
440
441
442 public function addRole(): void
443 {
444 $class = $this->role_callback['class'];
445 $method = $this->role_callback['method'];
446
447 // call callback if that function does give a return value => show error message
448 // listener redirects if everything is ok.
449 $obj_ids = [];
450 if ($this->http->wrapper()->post()->has('obj')) {
451 $obj_ids = $this->http->wrapper()->post()->retrieve(
452 'obj',
453 $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int())
454 );
455 }
456 $role_ids = array();
457 foreach ($obj_ids as $id) {
458 $obj_type = ilObject::_lookupType($id);
459 if ($obj_type == "crs" || $obj_type == "grp") {
461 $ref_id = end($refs);
463 $role_ids[] = $mem_role;
464 } else {
465 $role_ids[] = $id;
466 }
467 }
468 $class->$method($role_ids);
469
470 $this->showSearchResults();
471 }
472
473 public function addUser(): void
474 {
475 $class = $this->callback['class'];
476 $method = $this->callback['method'];
477
478 $users = [];
479 if ($this->http->wrapper()->post()->has('user')) {
480 $users = $this->http->wrapper()->post()->retrieve(
481 'user',
482 $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int())
483 );
484 }
485
486 // call callback if that function does give a return value => show error message
487 // listener redirects if everything is ok.
488 $class->$method($users);
489
490 $this->showSearchResults();
491 }
492
493
494 protected function addUserFromAutoComplete(): void
495 {
496 $class = $this->callback['class'];
497 $method = $this->callback['method'];
498
499 $post_users = '';
500 if ($this->http->wrapper()->post()->has('user_login')) {
501 $post_users = $this->http->wrapper()->post()->retrieve(
502 'user_login',
503 $this->refinery->kindlyTo()->string()
504 );
505 }
506
507 $users = explode(',', $post_users);
508 $user_ids = array();
509 foreach ($users as $user) {
511 if ($user_id) {
512 $user_ids[] = $user_id;
513 }
514 }
515
516 $user_type = $this->initUserTypeFromPost();
517 if (!$class->$method($user_ids, $user_type)) {
518 $this->ctrl->returnToParent($this);
519 }
520 }
521
522 protected function showClipboard(): void
523 {
524 $user_type = $this->initUserTypeFromQuery();
525 if ($user_type === '') {
526 $user_type = $this->initUserTypeFromPost();
527 }
528 $this->ctrl->setParameter($this, 'user_type', $user_type);
529 $this->tabs->clearTargets();
530 $this->tabs->setBackTarget(
531 $this->lng->txt('back'),
532 $this->ctrl->getParentReturn($this)
533 );
534
535 $clip = new ilUserClipboardTableGUI($this, 'showClipboard', $this->user->getId());
536 $clip->setFormAction($this->ctrl->getFormAction($this));
537 $clip->init();
538 $clip->parse();
539
540 $this->tpl->setContent($clip->getHTML());
541 }
542
543
544 protected function addFromClipboard(): void
545 {
546 $user_type = $this->initUserTypeFromPost();
547 if ($user_type === '') {
548 $user_type = $this->initUserTypeFromQuery();
549 }
550 $this->ctrl->setParameter($this, 'user_type', $user_type);
551
552 $users = [];
553 if ($this->http->wrapper()->post()->has('uids')) {
554 $users = $this->http->wrapper()->post()->retrieve(
555 'uids',
556 $this->refinery->kindlyTo()->dictOf(
557 $this->refinery->kindlyTo()->int()
558 )
559 );
560 }
561 if (!count($users)) {
562 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'), true);
563 $this->ctrl->redirect($this, 'showClipboard');
564 }
565 $class = $this->callback['class'];
566 $method = $this->callback['method'];
567 if (!$class->$method($users, $user_type)) {
568 $this->ctrl->returnToParent($this);
569 }
570 }
571
572
573 protected function removeFromClipboard(): void
574 {
575 $users = [];
576 if ($this->http->wrapper()->post()->has('uids')) {
577 $users = $this->http->wrapper()->post()->retrieve(
578 'uids',
579 $this->refinery->kindlyTo()->listOf(
580 $this->refinery->kindlyTo()->int()
581 )
582 );
583 }
584
585 $this->ctrl->setParameter($this, 'user_type', $this->initUserTypeFromQuery());
586 if (!count($users)) {
587 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'), true);
588 $this->ctrl->redirect($this, 'showClipboard');
589 }
590
591 $clip = ilUserClipboard::getInstance($this->user->getId());
592 $clip->delete($users);
593 $clip->save();
594
595 $this->tpl->setOnScreenMessage('success', $this->lng->txt('settings_saved'), true);
596 $this->ctrl->redirect($this, 'showClipboard');
597 }
598
599
600 protected function emptyClipboard(): void
601 {
602 $clip = ilUserClipboard::getInstance($this->user->getId());
603 $clip->clear();
604 $clip->save();
605
606 $this->tpl->setOnScreenMessage('success', $this->lng->txt('settings_saved'), true);
607 $this->ctrl->returnToParent($this);
608 }
609
610
611 protected function handleMultiCommand(): void
612 {
613 $class = $this->callback['class'];
614 $method = $this->callback['method'];
615
616 $post_user = $this->http->wrapper()->post()->retrieve(
617 'user',
618 $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int())
619 );
620 $post_selected_command = '';
621 if (
622 $this->http->wrapper()->post()->has('table_top_cmd') &&
623 $this->http->wrapper()->post()->has('selectedCommand_2')
624 ) {
625 $post_selected_command = $this->http->wrapper()->post()->retrieve(
626 'selectedCommand_2',
627 $this->refinery->kindlyTo()->string()
628 );
629 } elseif ($this->http->wrapper()->post()->has('selectedCommand')) {
630 $post_selected_command = $this->http->wrapper()->post()->retrieve(
631 'selectedCommand',
632 $this->refinery->kindlyTo()->string()
633 );
634 }
635 // Redirects if everything is ok
636 if (!$class->$method($post_user, $post_selected_command)) {
637 $this->showSearchResults();
638 }
639 }
640
644 public function setCallback(
645 object $class,
646 string $method,
647 array $a_add_options = [],
648 string $default_option = ''
649 ): void {
650 $this->callback = array('class' => $class,'method' => $method);
651 $this->add_options = $a_add_options;
652 $this->default_option = $default_option;
653 }
654
658 public function setRoleCallback(
659 object $class,
660 string $method,
661 array $a_add_options = [],
662 string $default_option = ''
663 ): void {
664 $this->role_callback = array('class' => $class,'method' => $method);
665 $this->add_options = $a_add_options;
666 $this->default_option = $default_option;
667 }
668
669
670 public function setPermissionQueryCallback(object $class, string $method): void
671 {
672 }
673
674 public function showSearch(): void
675 {
676 // only autocomplete input field, no search form if user privay should be respected
677 // see bug 25481
678 if ($this->getPrivacyMode() == ilUserAutoComplete::PRIVACY_MODE_RESPECT_USER_SETTING) {
679 return;
680 }
681 $this->initFormSearch();
682 $this->tpl->setContent($this->form->getHTML());
683 }
684
685 public function showSearchSelected(): void
686 {
687 $selected = [];
688 if ($this->http->wrapper()->query()->has('selected_id')) {
689 $selected = $this->http->wrapper()->query()->retrieve(
690 'selected_id',
691 $this->refinery->kindlyTo()->int()
692 );
693 }
694 $this->tpl->addBlockFile('ADM_CONTENT', 'adm_content', 'tpl.rep_search_result.html', 'components/ILIAS/Search');
695 $this->addNewSearchButton();
696 $this->showSearchUserTable([$selected], 'showSearchResults');
697 }
698
699 public function initFormSearch(?ilObjUser $user = null): void
700 {
701 $this->form = new ilPropertyFormGUI();
702 $this->form->setFormAction($this->ctrl->getFormAction($this, 'showSearch'));
703 $this->form->setTitle($this->getTitle());
704 $this->form->addCommandButton('performSearch', $this->lng->txt('search'));
705 $this->form->addCommandButton('cancel', $this->lng->txt('cancel'));
706
707
708 $kind = new ilRadioGroupInputGUI($this->lng->txt('search_type'), 'search_for');
709 $kind->setValue($this->search_type);
710 $this->form->addItem($kind);
711
712 // Users
713 $users = new ilRadioOption($this->lng->txt('search_for_users'), 'usr');
714
715 // UDF
716 foreach (ilUserSearchOptions::_getSearchableFieldsInfo(!$this->isSearchableCheckEnabled()) as $info) {
720
721 $sel = new ilSelectInputGUI($info['lang'], "rep_query[usr][" . $info['db'] . "]");
722 $sel->setOptions($info['values']);
723 $users->addSubItem($sel);
724 break;
725
729
730 if (isset($info['autoComplete']) and $info['autoComplete']) {
731 $this->ctrl->setParameterByClass(get_class($this), 'autoCompleteField', $info['db']);
732 $ul = new ilTextInputGUI($info['lang'], "rep_query[usr][" . $info['db'] . "]");
733 $ul->setDataSourceSubmitOnSelection(true);
734 $ul->setDataSourceSubmitUrl(
735 $this->ctrl->getLinkTarget(
736 $this,
737 'showSearchSelected',
738 '',
739 false,
740 false
741 )
742 );
743 $ul->setDataSource($this->ctrl->getLinkTarget(
744 $this,
745 "doUserAutoComplete",
746 "",
747 true
748 ));
749 $ul->setSize(30);
750 $ul->setMaxLength(120);
751
752 if ($user instanceof ilObjUser) {
753 switch ($info['db']) {
754 case 'firstname':
755 $ul->setValue($user->getFirstname());
756 break;
757 case 'lastname':
758 $ul->setValue($user->getLastname());
759 break;
760 case 'login':
761 $ul->setValue($user->getLogin());
762 break;
763 }
764 }
765
766
767
768 $users->addSubItem($ul);
769 } else {
770 $txt = new ilTextInputGUI($info['lang'], "rep_query[usr][" . $info['db'] . "]");
771 $txt->setSize(30);
772 $txt->setMaxLength(120);
773 $users->addSubItem($txt);
774 }
775 break;
776 }
777 }
778 $kind->addOption($users);
779
780
781
782 // Role
783 $roles = new ilRadioOption($this->lng->txt('search_for_role_members'), 'role');
784 $role = new ilTextInputGUI($this->lng->txt('search_role_title'), 'rep_query[role][title]');
785 $role->setSize(30);
786 $role->setMaxLength(120);
787 $roles->addSubItem($role);
788 $kind->addOption($roles);
789
790 // Course
791 $groups = new ilRadioOption($this->lng->txt('search_for_crs_members'), 'crs');
792 $group = new ilTextInputGUI($this->lng->txt('search_crs_title'), 'rep_query[crs][title]');
793 $group->setSize(30);
794 $group->setMaxLength(120);
795 $groups->addSubItem($group);
796 $kind->addOption($groups);
797
798 // Group
799 $groups = new ilRadioOption($this->lng->txt('search_for_grp_members'), 'grp');
800 $group = new ilTextInputGUI($this->lng->txt('search_grp_title'), 'rep_query[grp][title]');
801 $group->setSize(30);
802 $group->setMaxLength(120);
803 $groups->addSubItem($group);
804 $kind->addOption($groups);
805
806 // Orgus
807 if (ilUserSearchOptions::_isEnabled("org_units")) {
808 $orgus = new ilRadioOption($this->lng->txt('search_for_orgu_members'), 'orgu');
810 $this->lng->txt('select_orgu'),
811 'rep_query_orgu',
812 true,
813 $this->form
814 );
815 $orgu->getExplorerGUI()->setSelectableTypes(["orgu"]);
816 $orgu->getExplorerGUI()->setTypeWhiteList(["root", "orgu"]);
817 $orgu->getExplorerGUI()->setRootId(ilObjOrgUnit::getRootOrgRefId());
818 $orgu->getExplorerGUI()->setAjax(false);
819 $orgus->addSubItem($orgu);
820 $kind->addOption($orgus);
821 }
822 }
823
824
825 public function show(): void
826 {
827 $this->showSearchResults();
828 }
829
830 public function appendSearch(): void
831 {
832 ilSession::set('search_append', true);
833 $this->performSearch();
834 }
835
836 public function performSearch(): bool
837 {
838 // only autocomplete input field, no search form if user privay should be respected
839 // see bug 25481
840 if ($this->getPrivacyMode() == ilUserAutoComplete::PRIVACY_MODE_RESPECT_USER_SETTING) {
841 return false;
842 }
843 $found_query = false;
844
845 $post_rep_query = (array) ($this->http->request()->getParsedBody()['rep_query'] ?? []);
846 $post_search_for = (string) ($this->http->request()->getParsedBody()['search_for'] ?? '');
847 if (isset($post_rep_query[$post_search_for])) {
848 foreach ((array) $post_rep_query[$post_search_for] as $field => $value) {
849 if (trim(ilUtil::stripSlashes($value))) {
850 $found_query = true;
851 break;
852 }
853 }
854 }
855 if ($this->http->wrapper()->post()->has('rep_query_orgu')) {
856 $found_query = true;
857 }
858 if (!$found_query) {
859 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('msg_no_search_string'));
860 $this->start();
861 return false;
862 }
863
864 $post_cmd = (array) ($this->http->request()->getParsedBody()['cmd'] ?? []);
865 // unset search_append if called directly
866 if (isset($post_cmd['performSearch'])) {
867 ilSession::clear('search_append');
868 }
869
870 switch ($this->search_type) {
871 case 'usr':
872 $this->__performUserSearch();
873 break;
874
875 case 'grp':
876 $this->__performGroupSearch();
877 break;
878
879 case 'crs':
880 $this->__performCourseSearch();
881 break;
882
883 case 'role':
884 $this->__performRoleSearch();
885 break;
886 case 'orgu':
887 $post_rep_query_orgu = (array) ($this->http->request()->getParsedBody()['rep_query_orgu'] ?? []);
888 $selected_objects = array_map(
889 function ($ref_id) {
890 return ilObject::_lookupObjId((int) $ref_id);
891 },
892 $post_rep_query_orgu
893 );
894 return $this->listUsers($selected_objects);
895 default:
896 echo 'not defined';
897 }
898
899 $this->result_obj->setRequiredPermission('read');
900 $this->result_obj->addObserver($this, 'searchResultFilterListener');
901 $this->result_obj->filter(ROOT_FOLDER_ID, true);
902
903 // User access filter
904 if ($this->search_type == 'usr') {
905 $callable_name = '';
906 if (is_callable($this->user_filter, true, $callable_name)) {
907 $result_ids = call_user_func_array($this->user_filter, [$this->result_obj->getResultIds()]);
908 } else {
909 $result_ids = $this->result_obj->getResultIds();
910 }
911
912 $this->search_results = array_intersect(
913 $result_ids,
914 ilUserFilter::getInstance()->filter($result_ids)
915 );
916 } else {
917 $this->search_results = array();
918 foreach ($this->result_obj->getResults() as $res) {
919 $this->search_results[] = $res['obj_id'];
920 }
921 }
922
923 if (!count($this->search_results)) {
924 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('search_no_match'));
925 $this->showSearch();
926 return true;
927 }
928 $this->__updateResults();
929 if ($this->result_obj->isLimitReached()) {
930 $message = sprintf($this->lng->txt('search_limit_reached'), $this->settings->getMaxHits());
931 $this->tpl->setOnScreenMessage('info', $message);
932 return true;
933 }
934 // show results
935 $this->show();
936 return true;
937 }
938
939 public function __performUserSearch(): bool
940 {
941 foreach (ilUserSearchOptions::_getSearchableFieldsInfo(!$this->isSearchableCheckEnabled()) as $info) {
942 $name = $info['db'];
943
944 $rep_query = ilSession::get('rep_query');
945 $query_string = $rep_query['usr'][$name] ?? '';
946 // continue if no query string is given
947 if (!$query_string) {
948 continue;
949 }
950
951 if (!is_object($query_parser = $this->__parseQueryString($query_string, true, ($info['type'] == ilUserSearchOptions::FIELD_TYPE_SELECT)))) {
952 $this->tpl->setOnScreenMessage('info', $query_parser);
953 return false;
954 }
955 switch ($info['type']) {
957 $query_parser = $this->__parseQueryString($query_string);
958
959 // no break
962 $udf_search->setFields(array($name));
963 $result_obj = $udf_search->performSearch();
964
965 // Store entries
966 $this->__storeEntries($result_obj);
967 break;
968
970
971 if ($info['db'] == 'org_units') {
973 $result_obj = $user_search->performSearch();
974 $this->__storeEntries($result_obj);
975 break;
976 }
977 $query_parser = $this->__parseQueryString($query_string, true, true);
978
979 // no break
981 $user_search = ilObjectSearchFactory::_getUserSearchInstance($query_parser);
982 $user_search->setFields(array($name));
983 $result_obj = $user_search->performSearch();
984
985 // store entries
986 $this->__storeEntries($result_obj);
987 break;
988
990 $multi_search = ilObjectSearchFactory::getUserMultiFieldSearchInstance($query_parser);
991 $multi_search->setFields(array($name));
992 $result_obj = $multi_search->performSearch();
993 $this->__storeEntries($result_obj);
994 break;
995 }
996 }
997 return true;
998 }
999
1000 public function __performGroupSearch(): bool
1001 {
1002 $rep_query = ilSession::get('rep_query');
1003 $query_string = $rep_query['grp']['title'] ?? '';
1004 if (!is_object($query_parser = $this->__parseQueryString($query_string))) {
1005 $this->tpl->setOnScreenMessage('info', $query_parser, true);
1006 return false;
1007 }
1008
1009 $object_search = new ilLikeObjectSearch($query_parser);
1010 $object_search->setFilter(array('grp'));
1011 $this->__storeEntries($object_search->performSearch());
1012
1013 return true;
1014 }
1015
1016 protected function __performCourseSearch(): bool
1017 {
1018 $rep_query = ilSession::get('rep_query');
1019 $query_string = $rep_query['crs']['title'] ?? '';
1020 if (!is_object($query_parser = $this->__parseQueryString($query_string))) {
1021 $this->tpl->setOnScreenMessage('info', $query_parser, true);
1022 return false;
1023 }
1024
1025 $object_search = new ilLikeObjectSearch($query_parser);
1026 $object_search->setFilter(array('crs'));
1027 $this->__storeEntries($object_search->performSearch());
1028
1029 return true;
1030 }
1031
1032 public function __performRoleSearch(): bool
1033 {
1034 $rep_query = ilSession::get('rep_query');
1035 $query_string = $rep_query['role']['title'] ?? '';
1036 if (!is_object($query_parser = $this->__parseQueryString($query_string))) {
1037 $this->tpl->setOnScreenMessage('info', $query_parser, true);
1038 return false;
1039 }
1040
1041 // Perform like search
1042 $object_search = new ilLikeObjectSearch($query_parser);
1043 $object_search->setFilter(array('role'));
1044 $this->__storeEntries($object_search->performSearch());
1045
1046 return true;
1047 }
1048
1052 public function __parseQueryString(string $a_string, bool $a_combination_or = true, bool $a_ignore_length = false)
1053 {
1054 $query_parser = new ilQueryParser(ilUtil::stripSlashes($a_string));
1055 $query_parser->setCombination($a_combination_or ? ilQueryParser::QP_COMBINATION_OR : ilQueryParser::QP_COMBINATION_AND);
1056 $query_parser->setMinWordLength(1);
1057
1058 // #17502
1059 if (!$a_ignore_length) {
1060 $query_parser->setGlobalMinLength(3); // #14768
1061 }
1062
1063 $query_parser->parse();
1064
1065 if (!$query_parser->validate()) {
1066 return $query_parser->getMessage();
1067 }
1068 return $query_parser;
1069 }
1070
1071 // Private
1072 public function __loadQueries(): void
1073 {
1074 if ($this->http->wrapper()->post()->has('rep_query')) {
1076 'rep_query',
1077 $this->http->request()->getParsedBody()['rep_query']
1078 );
1079 }
1080 }
1081
1082
1083 public function __setSearchType(): bool
1084 {
1085 // Update search type. Default to user search
1086 if ($this->http->wrapper()->post()->has('search_for')) {
1088 'rep_search_type',
1089 $this->http->request()->getParsedBody()['search_for']
1090 );
1091 } elseif (!ilSession::get('rep_search_type')) {
1092 ilSession::set('rep_search_type', 'usr');
1093 }
1094 $this->search_type = (string) ilSession::get('rep_search_type');
1095 return true;
1096 }
1097
1098
1099 public function __updateResults(): bool
1100 {
1101 if (!ilSession::get('search_append')) {
1102 ilSession::set('rep_search', []);
1103 }
1104 $rep_search = ilSession::get('rep_search') ?? [];
1105 foreach ($this->search_results as $result) {
1106 $rep_search[$this->search_type][] = $result;
1107 }
1108 if (!$rep_search[$this->search_type]) {
1109 $rep_search[$this->search_type] = [];
1110 } else {
1111 $rep_search[$this->search_type] = array_unique($rep_search[$this->search_type]);
1112 }
1113 ilSession::set('rep_search', $rep_search);
1114 return true;
1115 }
1116
1120 public function __appendToStoredResults(array $a_usr_ids): array
1121 {
1122 if (!ilSession::get('search_append')) {
1123 $rep_search = ilSession::get('rep_search') ?? [];
1124 $rep_search['usr'] = $a_usr_ids;
1125 ilSession::set('rep_search', $rep_search);
1126 return $a_usr_ids;
1127 }
1128 $rep_search = ilSession::get('rep_search') ?? [];
1129 foreach ($a_usr_ids as $usr_id) {
1130 $rep_search['usr'][] = $usr_id;
1131 }
1132 $rep_search['usr'] = array_unique($rep_search['usr'] ?? []);
1133 ilSession::set('rep_search', $rep_search);
1134 return $rep_search['usr'];
1135 }
1136
1137 public function __storeEntries(ilSearchResult $new_res): bool
1138 {
1139 if ($this->stored == false) {
1140 $this->result_obj->mergeEntries($new_res);
1141 $this->stored = true;
1142 return true;
1143 } else {
1144 $this->result_obj->intersectEntries($new_res);
1145 return true;
1146 }
1147 }
1148
1149 protected function addNewSearchButton(): void
1150 {
1151 $toolbar = new ilToolbarGUI();
1152 $toolbar->addButton(
1153 $this->lng->txt('search_new'),
1154 $this->ctrl->getLinkTarget($this, 'showSearch')
1155 );
1156 $this->tpl->setVariable('ACTION_BUTTONS', $toolbar->getHTML());
1157 }
1158
1159 public function showSearchResults(): void
1160 {
1161 $counter = 0;
1162 $f_result = array();
1163
1164 $this->tpl->addBlockFile('ADM_CONTENT', 'adm_content', 'tpl.rep_search_result.html', 'components/ILIAS/Search');
1165 $this->addNewSearchButton();
1166
1167 $rep_search = ilSession::get('rep_search');
1168
1169 switch ($this->search_type) {
1170 case "usr":
1171 $this->showSearchUserTable($rep_search['usr'] ?? [], 'showSearchResults');
1172 break;
1173
1174 case 'grp':
1175 $this->showSearchGroupTable($rep_search['grp'] ?? []);
1176 break;
1177
1178 case 'crs':
1179 $this->showSearchCourseTable($rep_search['crs'] ?? []);
1180 break;
1181
1182 case 'role':
1183 $this->showSearchRoleTable($rep_search['role'] ?? []);
1184 break;
1185 }
1186 }
1187
1188 protected function showSearchUserTable(array $a_usr_ids, string $a_parent_cmd): void
1189 {
1190 $base_class = '';
1191 if ($this->http->wrapper()->query()->has('baseClass')) {
1192 $base_class = $this->http->wrapper()->query()->retrieve(
1193 'baseClass',
1194 $this->refinery->kindlyTo()->string()
1195 );
1196 }
1197
1198 // String value of 'baseClass' is in lower case
1199 $is_in_admin = ($base_class === strtolower(ilAdministrationGUI::class));
1200
1201 if ($is_in_admin) {
1202 // remember link target to admin search gui (this)
1203 ilSession::set('usr_search_link', $this->ctrl->getLinkTarget($this, 'show'));
1204 }
1205
1206 $table = new ilRepositoryUserResultTableGUI($this, $a_parent_cmd, $is_in_admin);
1207 if (count($this->add_options)) {
1208 $table->addMultiItemSelectionButton(
1209 'selectedCommand',
1210 $this->add_options,
1211 'handleMultiCommand',
1212 $this->lng->txt('execute'),
1213 $this->default_option
1214 );
1215 } else {
1216 $table->addMultiCommand('addUser', $this->lng->txt('btn_add'));
1217 }
1218 $table->setUserLimitations($this->getUserLimitations());
1219 $table->parseUserIds($a_usr_ids);
1220
1221 $this->tpl->setVariable('RES_TABLE', $table->getHTML());
1222 }
1223
1224 protected function showSearchRoleTable(array $a_obj_ids): void
1225 {
1226 $table = new ilRepositoryObjectResultTableGUI($this, 'showSearchResults', $this->object_selection);
1227 $table->parseObjectIds($a_obj_ids);
1228
1229 $this->tpl->setVariable('RES_TABLE', $table->getHTML());
1230 }
1231
1232 protected function showSearchGroupTable(array $a_obj_ids): void
1233 {
1234 $table = new ilRepositoryObjectResultTableGUI($this, 'showSearchResults', $this->object_selection);
1235 $table->parseObjectIds($a_obj_ids);
1236
1237 $this->tpl->setVariable('RES_TABLE', $table->getHTML());
1238 }
1239
1240 protected function showSearchCourseTable(array $a_obj_ids): void
1241 {
1242 $table = new ilRepositoryObjectResultTableGUI($this, 'showSearchResults', $this->object_selection);
1243 $table->parseObjectIds($a_obj_ids);
1244
1245 $this->tpl->setVariable('RES_TABLE', $table->getHTML());
1246 }
1247
1248 protected function listUsers(array $selected_entries = []): bool
1249 {
1250 // get parameter is used e.g. in exercises to provide
1251 // "add members of course" link
1252 if (
1253 $this->http->wrapper()->post()->has('obj') &&
1254 !count($selected_entries)
1255 ) {
1256 $selected_entries = $this->http->wrapper()->post()->retrieve(
1257 'obj',
1258 $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int())
1259 );
1260 }
1261 if (
1262 $this->http->wrapper()->query()->has('list_obj') &&
1263 !count($selected_entries)
1264 ) {
1265 $selected_entries[] = $this->http->wrapper()->query()->retrieve(
1266 'list_obj',
1267 $this->refinery->kindlyTo()->int()
1268 );
1269 }
1270 if (!count($selected_entries)) {
1271 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
1272 $this->showSearchResults();
1273 return false;
1274 }
1275 $rep_search = ilSession::get('rep_search') ?? [];
1276 $rep_search['objs'] = $selected_entries;
1277 ilSession::set('rep_search', $rep_search);
1278
1279 // Get all members
1280 $members = array();
1281 foreach ($selected_entries as $obj_id) {
1282 $type = ilObject::_lookupType($obj_id);
1283 switch ($type) {
1284 case 'crs':
1285 case 'grp':
1287 $part = [];
1288 if (is_callable($this->user_filter)) {
1289 $part = call_user_func_array(
1290 $this->user_filter,
1291 [
1292 ilParticipants::getInstanceByObjId($obj_id)->getParticipants()
1293 ]
1294 );
1295 } else {
1296 $part = ilParticipants::getInstanceByObjId($obj_id)->getParticipants();
1297 }
1298
1299 $members = array_merge((array) $members, $part);
1300 }
1301 break;
1302
1303 case 'role':
1304 $assigned = [];
1305 if (is_callable($this->user_filter)) {
1306 $assigned = call_user_func_array(
1307 $this->user_filter,
1308 [
1309 $this->rbacreview->assignedUsers($obj_id)
1310 ]
1311 );
1312 } else {
1313 $assigned = $this->rbacreview->assignedUsers($obj_id);
1314 }
1315
1316 $members = array_merge($members, ilUserFilter::getInstance()->filter($assigned));
1317 break;
1318 case 'orgu':
1319 if ($ref_ids = ilObject::_getAllReferences($obj_id)) {
1321 ->getUserIdsOfOrgUnit(array_shift($ref_ids));
1322 if (is_callable($this->user_filter)) {
1323 $assigned = call_user_func_array(
1324 $this->user_filter,
1325 [$assigned]
1326 );
1327 }
1328
1329 $members = array_merge(
1330 $members,
1331 $assigned
1332 );
1333 }
1334 break;
1335 }
1336 }
1337 $members = array_unique($members);
1338 $this->__appendToStoredResults($members);
1339
1340 $this->tpl->addBlockFile('ADM_CONTENT', 'adm_content', 'tpl.rep_search_result.html', 'components/ILIAS/Search');
1341
1342 $this->addNewSearchButton();
1343 $rep_search = ilSession::get('rep_search');
1344 $this->showSearchUserTable($rep_search['usr'] ?? [], 'storedUserList');
1345 return true;
1346 }
1347
1348 protected function storedUserList(): bool
1349 {
1350 $rep_search = ilSession::get('rep_search');
1351 $objects = $rep_search['objs'] ?? [];
1352 $this->listUsers($objects);
1353 return true;
1354 }
1355
1361 public function searchResultFilterListener(int $a_ref_id, array $a_data): bool
1362 {
1363 if ($a_data['type'] == 'usr') {
1364 if ($a_data['obj_id'] == ANONYMOUS_USER_ID) {
1365 return false;
1366 }
1367 }
1368 return true;
1369 }
1370
1371 public function allowObjectSelection(bool $a_value = false): void
1372 {
1373 $this->object_selection = $a_value;
1374 }
1375
1379 protected function selectObject(): bool
1380 {
1381 // get parameter is used e.g. in exercises to provide
1382 // "add members of course"
1383 $selected_entries = [];
1384 if ($this->http->wrapper()->post()->has('obj')) {
1385 $selected_entries = $this->http->wrapper()->post()->retrieve(
1386 'obj',
1387 $this->refinery->kindlyTo()->listOf($this->refinery->kindlyTo()->int())
1388 );
1389 }
1390 if (
1391 $this->http->wrapper()->query()->has('list_obj') &&
1392 !count($selected_entries)
1393 ) {
1394 $selected_entries[] = $this->http->wrapper()->query()->retrieve(
1395 'list_obj',
1396 $this->refinery->kindlyTo()->int()
1397 );
1398 }
1399
1400 if (!count($selected_entries)) {
1401 $this->tpl->setOnScreenMessage('failure', $this->lng->txt('select_one'));
1402 $this->showSearchResults();
1403 return false;
1404 }
1405 $this->ctrl->setParameter($this->callback["class"], "obj", implode(";", $selected_entries));
1406 $this->ctrl->redirect($this->callback["class"], $this->callback["method"]);
1407 return true;
1408 }
1409
1413 public function setUserLimitations(bool $a_limitations): void
1414 {
1415 $this->user_limitations = $a_limitations;
1416 }
1417
1421 public function getUserLimitations(): bool
1422 {
1423 return $this->user_limitations;
1424 }
1425}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
Builds a Color from either hex- or rgb values.
Definition: Factory.php:31
Builds data types.
Definition: Factory.php:36
show()
returns the content of IniFile
Class ilCtrl provides processing control methods.
language handling
loadLanguageModule(string $a_module)
Load language module.
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
static getRootOrgRefId()
User class.
static _lookupId(string|array $a_user_str)
static _getUserDefinedFieldSearchInstance(ilQueryParser $query_parser)
static getUserOrgUnitAssignmentInstance(ilQueryParser $query_parser)
static _getUserSearchInstance(ilQueryParser $query_parser)
static getUserMultiFieldSearchInstance(ilQueryParser $query_parser)
static _lookupType(int $id, bool $reference=false)
static _getAllReferences(int $id)
get all reference ids for object ID
static _lookupObjId(int $ref_id)
static getInstanceByObjId(int $a_obj_id)
Get instance by obj type.
static getDefaultMemberRole(int $a_ref_id)
static hasParticipantListAccess(int $a_obj_id, ?int $a_usr_id=null)
Check if (current) user has access to the participant list.
This class represents a property form user interface.
This class represents a property in a property form.
This class represents an option in a radio group.
class ilRbacReview Contains Review functions of core Rbac.
TableGUI class object (course,group and role) search results Used in member search.
selectObject()
Return selection of course/group/roles to calling script.
setPermissionQueryCallback(object $class, string $method)
showSearchUserTable(array $a_usr_ids, string $a_parent_cmd)
listUsers(array $selected_entries=[])
setRoleCallback(object $class, string $method, array $a_add_options=[], string $default_option='')
allowObjectSelection(bool $a_value=false)
searchResultFilterListener(int $a_ref_id, array $a_data)
Listener called from ilSearchResult Id is obj_id for role, usr Id is ref_id for crs grp.
initFormSearch(?ilObjUser $user=null)
addUserAccessFilterCallable(callable $user_filter)
Closure for filtering users e.g $rep_search_gui->addUserAccessFilterCallable(function($user_ids) use(...
static fillAutoCompleteToolbar(object $parent_object, ?ilToolbarGUI $toolbar=null, array $a_options=[], bool $a_sticky=false)
array( auto_complete_name = $lng->txt('user'), auto_complete_size = 15, user_type = array(ilCoursePar...
ilGlobalTemplateInterface $tpl
__storeEntries(ilSearchResult $new_res)
setCallback(object $class, string $method, array $a_add_options=[], string $default_option='')
getUserLimitations()
allow user limitations like inactive and access limitations
setUserLimitations(bool $a_limitations)
allow user limitations like inactive and access limitations
__parseQueryString(string $a_string, bool $a_combination_or=true, bool $a_ignore_length=false)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This class represents a selection list property in a property form.
static get(string $a_var)
static clear(string $a_var)
static set(string $a_var, $a_val)
Set a value.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This class represents a text property in a property form.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco...
checkForParentType(int $a_ref_id, string $a_type, bool $a_exclude_source_check=false)
Check for parent type e.g check if a folder (ref_id 3) is in a parent course obj => checkForParentTyp...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static getInstance(int $a_usr_id)
static _getSearchableFieldsInfo(bool $a_admin=false)
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
const ANONYMOUS_USER_ID
Definition: constants.php:27
const ROOT_FOLDER_ID
Definition: constants.php:32
exit
$info
Definition: entry_point.php:21
Interface GlobalHttpState.
This is how the factory for UI elements looks.
Definition: Factory.php:38
An entity that renders components to a string output.
Definition: Renderer.php:31
$ref_id
Definition: ltiauth.php:66
$res
Definition: ltiservices.php:69
static http()
Fetches the global http state from ILIAS.
form(?array $class_path, string $cmd, string $submit_caption="")
filter(string $filter_id, array $class_path, string $cmd, bool $activated=true, bool $expanded=true)
global $DIC
Definition: shib_login.php:26
$counter