ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilMailSearchGUI.php
Go to the documentation of this file.
1<?php
2
19declare(strict_types=1);
20
23use ILIAS\Refinery\Factory as Refinery;
24
30{
32 private readonly ilCtrlInterface $ctrl;
35 private readonly ilLanguage $lng;
36 private readonly ilFormatMail $umail;
37 private readonly GlobalHttpState $http;
38 private readonly Refinery $refinery;
39
43 public function __construct(private $wsp_access_handler = null, private readonly ?int $wsp_node_id = null)
44 {
46 global $DIC;
47
48 $this->tpl = $DIC['tpl'];
49 $this->ctrl = $DIC['ilCtrl'];
50 $this->lng = $DIC['lng'];
51 $this->rbacreview = $DIC['rbacreview'];
52 $this->object_data_cache = $DIC['ilObjDataCache'];
53 $this->http = $DIC->http();
54 $this->refinery = $DIC->refinery();
55
56 $this->ctrl->saveParameter($this, 'mobj_id');
57 $this->ctrl->saveParameter($this, 'ref');
58
59 $this->umail = new ilFormatMail($DIC->user()->getId());
60 }
61
62 public function executeCommand(): bool
63 {
64 if (!($cmd = $this->ctrl->getCmd())) {
65 $cmd = "showResults";
66 }
67
68 $this->$cmd();
69
70 return true;
71 }
72
73 private function isDefaultRequestContext(): bool
74 {
75 return (
76 !$this->http->wrapper()->query()->has('ref') ||
77 $this->http->wrapper()->query()->retrieve('ref', $this->refinery->kindlyTo()->string()) !== 'wsp'
78 );
79 }
80
81 public function adopt(): void
82 {
83 $trafo = $this->refinery->kindlyTo()->int();
84 if ($this->isDefaultRequestContext()) {
85 $trafo = $this->refinery->kindlyTo()->string();
86 }
87
88 $recipients_to = [];
89 foreach (['to', 'cc', 'bcc'] as $recipient_type) {
90 $recipients = [];
91 foreach (['addr', 'usr', 'grp'] as $search_type) {
92 if ($this->http->wrapper()->post()->has('search_name_' . $recipient_type . '_' . $search_type)) {
93 $recipients[] = $this->http->wrapper()->post()->retrieve(
94 'search_name_' . $recipient_type . '_' . $search_type,
95 $this->refinery->kindlyTo()->listOf($trafo)
96 );
97 }
98 }
99
100 $recipients = array_unique(array_merge(...$recipients));
101 ilSession::set('mail_search_results_' . $recipient_type, $recipients);
102
103 if ('to' === $recipient_type) {
104 $recipients_to = $recipients;
105 }
106 }
107
108 if ($this->isDefaultRequestContext()) {
109 $this->saveMailData();
110 } else {
111 $this->addPermission($recipients_to);
112 }
113
114 $this->ctrl->returnToParent($this);
115 }
116
117 private function saveMailData(): void
118 {
119 $mail_data = $this->umail->retrieveFromStage();
120 $this->umail->persistToStage(
121 (int) $mail_data['user_id'],
122 $mail_data['attachments'],
123 $mail_data['rcp_to'],
124 $mail_data['rcp_cc'],
125 $mail_data['rcp_bcc'],
126 $mail_data['m_subject'],
127 $mail_data['m_message'],
128 $mail_data['use_placeholders'],
129 $mail_data['tpl_ctx_id'],
130 $mail_data['tpl_ctx_params']
131 );
132 }
133
134 public function cancel(): void
135 {
136 $this->ctrl->returnToParent($this);
137 }
138
139 public function search(): bool
140 {
141 $search = '';
142 if ($this->http->wrapper()->post()->has('search')) {
143 $search = $this->http->wrapper()->post()->retrieve('search', $this->refinery->kindlyTo()->string());
144 }
145
146 ilSession::set('mail_search_search', trim($search));
147
148 if (ilSession::get('mail_search_search') === '') {
149 $this->tpl->setOnScreenMessage('info', $this->lng->txt('mail_insert_query'));
150 } elseif (strlen((string) ilSession::get('mail_search_search')) < 3) {
151 $this->lng->loadLanguageModule('search');
152 $this->tpl->setOnScreenMessage('info', $this->lng->txt('search_minimum_three'));
153 }
154
155 $this->showResults();
156
157 return true;
158 }
159
160 protected function initSearchForm(): ilPropertyFormGUI
161 {
162 if ($this->isDefaultRequestContext()) {
163 $this->saveMailData();
164 $title = $this->lng->txt('search_recipients');
165 } else {
166 $this->lng->loadLanguageModule('wsp');
167 $title = $this->lng->txt('wsp_share_search_users');
168 }
169
170 $form = new ilPropertyFormGUI();
171 $form->setTitle($title);
172 $form->setId('search_rcp');
173 $form->setFormAction($this->ctrl->getFormAction($this, 'search'));
174
175 $inp = new ilTextInputGUI($this->lng->txt('search_for'), 'search');
176 $inp->setSize(30);
177 $dsDataLink = $this->ctrl->getLinkTarget($this, 'lookupRecipientAsync', '', true, false);
178 $inp->setDataSource($dsDataLink);
179
180 if (
181 ilSession::get('mail_search_search') &&
182 is_string(ilSession::get('mail_search_search')) &&
183 ilSession::get('mail_search_search') !== ''
184 ) {
185 $inp->setValue(
186 ilLegacyFormElementsUtil::prepareFormOutput(trim(ilSession::get('mail_search_search')), true)
187 );
188 }
189 $form->addItem($inp);
190
191 $form->addCommandButton('search', $this->lng->txt('search'));
192 $form->addCommandButton('cancel', $this->lng->txt('cancel'));
193
194 return $form;
195 }
196
197 public function lookupRecipientAsync(): void
198 {
199 $search = '';
200 if ($this->http->wrapper()->query()->has('term')) {
201 $search = $this->http->wrapper()->query()->retrieve(
202 'term',
203 $this->refinery->kindlyTo()->string()
204 );
205 }
206 if ($this->http->wrapper()->post()->has('term')) {
207 $search = $this->http->wrapper()->post()->retrieve(
208 'term',
209 $this->refinery->kindlyTo()->string()
210 );
211 }
212
213 $search = trim($search);
214
215 $result = [];
216 if (ilStr::strLen($search) >= 3) {
217 // #14768
218 $quoted = ilUtil::stripSlashes($search);
219 $quoted = str_replace(['%', '_'], ['\%', '\_'], $quoted);
220
221 $mailFormObj = new ilMailForm();
222 $result = $mailFormObj->getRecipientAsync(
223 "%" . $quoted . "%",
224 ilUtil::stripSlashes($search),
226 );
227 }
228
229 $this->http->saveResponse(
230 $this->http->response()
231 ->withHeader(ResponseHeader::CONTENT_TYPE, 'application/json')
232 ->withBody(\ILIAS\Filesystem\Stream\Streams::ofString(json_encode($result, JSON_THROW_ON_ERROR)))
233 );
234 $this->http->sendResponse();
235 $this->http->close();
236 }
237
241 private function appendRecipientSelection(
242 array &$result,
243 int $index,
244 string $search_type,
245 string $recipient_type,
246 string $value
247 ): void {
248 $result[$index]['check_' . $recipient_type] = ilLegacyFormElementsUtil::formCheckbox(
249 false,
250 'search_name_' . $recipient_type . '_' . $search_type . '[' . $index . ']',
251 $value
252 );
253
254 $result[$index]['id_' . $recipient_type] = 'search_name_' . $search_type . '_' . $index;
255 $result[$index]['txt_' . $recipient_type] = $this->lng->txt('mail_' . $recipient_type);
256 }
257
258 public function showResults(): void
259 {
260 $form = $this->initSearchForm();
261
262 $this->tpl->addBlockFile('ADM_CONTENT', 'adm_content', 'tpl.mail_search.html', 'components/ILIAS/Contact');
263 $this->tpl->setVariable('ACTION', $this->ctrl->getFormAction($this));
264 $this->tpl->setTitle($this->lng->txt('mail'));
265 $this->tpl->setVariable('SEARCHFORM', $form->getHtml());
266
267 // #14109
268 if (
269 !ilSession::get('mail_search_search') ||
270 !is_string(ilSession::get('mail_search_search')) ||
271 strlen(ilSession::get('mail_search_search')) < 3
272 ) {
273 if ($this->isDefaultRequestContext()) {
274 $this->tpl->printToStdout();
275 }
276 return;
277 }
278
279 $relations = ilBuddyList::getInstanceByGlobalUser()->getLinkedRelations();
280 if (count($relations) > 0) {
281 $contacts_search_result = new ilSearchResult();
282
283 $query_parser = new ilQueryParser(addcslashes(ilSession::get('mail_search_search'), '%_'));
284 $query_parser->setCombination(ilQueryParser::QP_COMBINATION_AND);
285 $query_parser->setMinWordLength(3);
286 $query_parser->parse();
287
288 $user_search = ilObjectSearchFactory::_getUserSearchInstance($query_parser);
289 $user_search->enableActiveCheck(true);
290 $user_search->setFields(['login']);
291 $result_obj = $user_search->performSearch();
292 $contacts_search_result->mergeEntries($result_obj);
293
294 $user_search->setFields(['firstname']);
295 $result_obj = $user_search->performSearch();
296 $contacts_search_result->mergeEntries($result_obj);
297
298 $user_search->setFields(['lastname']);
299 $result_obj = $user_search->performSearch();
300 $contacts_search_result->mergeEntries($result_obj);
301
302 $contacts_search_result->setMaxHits(100000);
303 $contacts_search_result->preventOverwritingMaxhits(true);
304 $contacts_search_result->filter(ROOT_FOLDER_ID, true);
305
306 // Filter users (depends on setting in user accounts)
307 $users = ilUserFilter::getInstance()->filter($contacts_search_result->getResultIds());
308 $users = array_intersect($users, $relations->getKeys());
309
310 $tbl_contacts = new ilMailSearchResultsTableGUI($this, 'showResults', 'contacts');
311 $tbl_contacts->setTitle($this->lng->txt('mail_addressbook'));
312 $tbl_contacts->setRowTemplate('tpl.mail_search_addr_row.html', 'components/ILIAS/Contact');
313
314 $has_mail_addr = false;
315 $result = [];
316 $counter = 0;
317 foreach ($users as $user) {
318 $login = ilObjUser::_lookupLogin($user);
319
320 if ($this->isDefaultRequestContext()) {
321 foreach (['to', 'cc', 'bcc'] as $recipient_type) {
322 $this->appendRecipientSelection($result, $counter, 'usr', $recipient_type, $login);
323 }
324 } else {
325 $this->appendRecipientSelection($result, $counter, 'addr', 'to', (string) $user);
326 }
327
328 $result[$counter]['login'] = $login;
329 if (ilObjUser::_lookupPref($user, 'public_email') === 'y') {
330 $has_mail_addr = true;
331 $result[$counter]['email'] = ilObjUser::_lookupEmail($user);
332 }
333
334 if (in_array(ilObjUser::_lookupPref($user, 'public_profile'), ['y', "g"])) {
335 $name = ilObjUser::_lookupName($user);
336 $result[$counter]['firstname'] = $name['firstname'];
337 $result[$counter]['lastname'] = $name['lastname'];
338 } else {
339 $result[$counter]['firstname'] = '';
340 $result[$counter]['lastname'] = '';
341 }
342
343 ++$counter;
344 }
345
346 if ($this->isDefaultRequestContext()) {
347 $tbl_contacts->addColumn(
348 $this->lng->txt('mail_to') . '/' . $this->lng->txt('mail_cc') . '/' . $this->lng->txt('mail_bcc'),
349 'check',
350 '10%'
351 );
352 } else {
353 $tbl_contacts->addColumn('', '', '1%', true);
354 }
355 $tbl_contacts->addColumn($this->lng->txt('login'), 'login', '15%');
356 $tbl_contacts->addColumn($this->lng->txt('firstname'), 'firstname', '15%');
357 $tbl_contacts->addColumn($this->lng->txt('lastname'), 'lastname', '15%');
358 if ($has_mail_addr) {
359 foreach ($result as $key => $val) {
360 if (!isset($val['email']) || $val['email'] === '') {
361 $result[$key]['email'] = '&nbsp;';
362 }
363 }
364
365 $tbl_contacts->addColumn($this->lng->txt('email'), 'email', "15%");
366 }
367 $tbl_contacts->setData($result);
368
369 $tbl_contacts->setDefaultOrderField('login');
370 $tbl_contacts->enable('select_all');
371 $tbl_contacts->setSelectAllCheckbox('search_name_to_addr');
372 $tbl_contacts->setFormName('recipients');
373
374 $this->tpl->setVariable('TABLE_ADDR', $tbl_contacts->getHTML());
375 }
376
377 $all_results = new ilSearchResult();
378
379 $query_parser = new ilQueryParser(addcslashes(ilSession::get('mail_search_search'), '%_'));
380 $query_parser->setCombination(ilQueryParser::QP_COMBINATION_AND);
381 $query_parser->setMinWordLength(3);
382 $query_parser->parse();
383
384 $user_search = ilObjectSearchFactory::_getUserSearchInstance($query_parser);
385 $user_search->enableActiveCheck(true);
386 $user_search->setFields(['login']);
387 $result_obj = $user_search->performSearch();
388 $all_results->mergeEntries($result_obj);
389
390 $user_search->setFields(['firstname']);
391 $result_obj = $user_search->performSearch();
392 $all_results->mergeEntries($result_obj);
393
394 $user_search->setFields(['lastname']);
395 $result_obj = $user_search->performSearch();
396 $all_results->mergeEntries($result_obj);
397
398 $all_results->setMaxHits(100000);
399 $all_results->preventOverwritingMaxhits(true);
400 $all_results->filter(ROOT_FOLDER_ID, true);
401
402 // Filter users (depends on setting in user accounts)
403 $has_mail_usr = false;
404 $users = ilUserFilter::getInstance()->filter($all_results->getResultIds());
405 if ($users !== []) {
406 $tbl_users = new ilMailSearchResultsTableGUI($this, 'showResults', 'usr');
407 $tbl_users->setTitle($this->lng->txt('system') . ': ' . $this->lng->txt('persons'));
408 $tbl_users->setRowTemplate('tpl.mail_search_users_row.html', 'components/ILIAS/Contact');
409
410 $result = [];
411 $counter = 0;
412 foreach ($users as $user) {
413 $login = ilObjUser::_lookupLogin($user);
414
415 if ($this->isDefaultRequestContext()) {
416 foreach (['to', 'cc', 'bcc'] as $recipient_type) {
417 $this->appendRecipientSelection($result, $counter, 'usr', $recipient_type, $login);
418 }
419 } else {
420 $this->appendRecipientSelection($result, $counter, 'usr', 'to', (string) $user);
421 }
422 $result[$counter]['login'] = $login;
423
424 if (in_array(ilObjUser::_lookupPref($user, 'public_profile'), ['y', "g"])) {
425 $name = ilObjUser::_lookupName($user);
426 $result[$counter]['firstname'] = $name['firstname'];
427 $result[$counter]['lastname'] = $name['lastname'];
428 } else {
429 $result[$counter]['firstname'] = '';
430 $result[$counter]['lastname'] = '';
431 }
432
433 if (ilObjUser::_lookupPref($user, 'public_email') === 'y') {
434 $has_mail_usr = true;
435 $result[$counter]['email'] = ilObjUser::_lookupEmail($user);
436 }
437
438 ++$counter;
439 }
440
441 if ($this->isDefaultRequestContext()) {
442 $tbl_users->addColumn(
443 $this->lng->txt('mail_to') . '/' . $this->lng->txt('mail_cc') . '/' . $this->lng->txt('mail_bcc'),
444 'check',
445 '10%'
446 );
447 } else {
448 $tbl_users->addColumn('', '', '1%');
449 }
450 $tbl_users->addColumn($this->lng->txt('login'), 'login', '15%');
451 $tbl_users->addColumn($this->lng->txt('firstname'), 'firstname', '15%');
452 $tbl_users->addColumn($this->lng->txt('lastname'), 'lastname', '15%');
453 if ($has_mail_usr) {
454 foreach ($result as $key => $val) {
455 if (!isset($val['email']) || $val['email'] === '') {
456 $result[$key]['email'] = '&nbsp;';
457 }
458 }
459
460 $tbl_users->addColumn($this->lng->txt('email'), 'email', '15%');
461 }
462 $tbl_users->setData($result);
463
464 $tbl_users->setDefaultOrderField('login');
465 $tbl_users->enable('select_all');
466 $tbl_users->setSelectAllCheckbox('search_name_to_usr');
467 $tbl_users->setFormName('recipients');
468
469 $this->tpl->setVariable('TABLE_USERS', $tbl_users->getHTML());
470 }
471
472 $group_results = new ilSearchResult();
473
474 $query_parser = new ilQueryParser(addcslashes(ilSession::get('mail_search_search'), '%_'));
475 $query_parser->setCombination(ilQueryParser::QP_COMBINATION_AND);
476 $query_parser->setMinWordLength(3);
477 $query_parser->parse();
478
480 $search->setFilter(['grp']);
481 $result = $search->performSearch();
482 $group_results->mergeEntries($result);
483 $group_results->setMaxHits(PHP_INT_MAX);
484 $group_results->preventOverwritingMaxhits(true);
485 $group_results->setRequiredPermission('read');
486 $group_results->filter(ROOT_FOLDER_ID, true);
487
488 $visible_groups = [];
489 if ($group_results->getResults()) {
490 $tbl_grp = new ilMailSearchResultsTableGUI($this, 'showResults', 'grp');
491 $tbl_grp->setTitle($this->lng->txt('system') . ': ' . $this->lng->txt('groups'));
492 $tbl_grp->setRowTemplate('tpl.mail_search_groups_row.html', 'components/ILIAS/Contact');
493
494 $result = [];
495 $counter = 0;
496
497 $this->object_data_cache->preloadReferenceCache(array_keys($group_results->getResults()));
498
499 $groups = $group_results->getResults();
500 foreach ($groups as $grp) {
501 if (!ilParticipants::hasParticipantListAccess($grp['obj_id'])) {
502 continue;
503 }
504
505 if ($this->isDefaultRequestContext()) {
506 $members = [];
507 $roles = $this->rbacreview->getAssignableChildRoles($grp['ref_id']);
508 foreach ($roles as $role) {
509 if (
510 str_starts_with($role['title'], 'il_grp_member_') ||
511 str_starts_with($role['title'], 'il_grp_admin_')
512 ) {
513 // FIX for Mantis: 7523
514 $members[] = '#' . $role['title'];
515 }
516 }
517 $str_members = implode(',', $members);
518
519 foreach (['to', 'cc', 'bcc'] as $recipient_type) {
520 $this->appendRecipientSelection($result, $counter, 'grp', $recipient_type, $str_members);
521 }
522 } else {
523 $this->appendRecipientSelection($result, $counter, 'grp', 'to', (string) $grp['obj_id']);
524 }
525 $result[$counter]['title'] = $this->object_data_cache->lookupTitle((int) $grp['obj_id']);
526 $result[$counter]['description'] = $this->object_data_cache->lookupDescription((int) $grp['obj_id']);
527
528 ++$counter;
529 $visible_groups[] = $grp;
530 }
531
532 if ($visible_groups !== []) {
533 $tbl_grp->setData($result);
534
535 if ($this->isDefaultRequestContext()) {
536 $tbl_grp->addColumn(
537 $this->lng->txt('mail_to') . '/' . $this->lng->txt('mail_cc') . '/' . $this->lng->txt('mail_bcc'),
538 'check',
539 '10%'
540 );
541 } else {
542 $tbl_grp->addColumn('', '', '1%');
543 }
544 $tbl_grp->addColumn($this->lng->txt('title'), 'title', '15%');
545 $tbl_grp->addColumn($this->lng->txt('description'), 'description', '15%');
546
547 $tbl_grp->setDefaultOrderField('title');
548 $tbl_grp->enable('select_all');
549 $tbl_grp->setSelectAllCheckbox('search_name_to_grp');
550 $tbl_grp->setFormName('recipients');
551
552 $this->tpl->setVariable('TABLE_GRP', $tbl_grp->getHTML());
553 }
554 }
555
556 if (count($users) || count($visible_groups) || count($relations)) {
557 $this->tpl->setVariable("IMG_ARROW", ilUtil::getImagePath("nav/arrow_downright.svg"));
558 $this->tpl->setVariable("ALT_ARROW", '');
559 $this->tpl->setVariable("IMG_ARROW_UP", ilUtil::getImagePath("nav/arrow_upright.svg"));
560 $this->tpl->setVariable("ALT_ARROW_UP", '');
561
562 if ($this->isDefaultRequestContext()) {
563 $this->tpl->setVariable('BUTTON_ADOPT', $this->lng->txt('adopt'));
564 } else {
565 $this->tpl->setVariable('BUTTON_ADOPT', $this->lng->txt('wsp_share_with_users'));
566 }
567 } else {
568 $this->lng->loadLanguageModule('search');
569 $this->tpl->setOnScreenMessage('info', $this->lng->txt('search_no_match'));
570 }
571
572 if ($this->isDefaultRequestContext()) {
573 $this->tpl->printToStdout();
574 }
575 }
576
580 protected function addPermission(array $a_obj_ids): void
581 {
582 if (!is_array($a_obj_ids)) {
583 $a_obj_ids = [$a_obj_ids];
584 }
585
586 $added = $this->wsp_access_handler->addMissingPermissionForObjects($this->wsp_node_id, $a_obj_ids);
587
588 if ($added) {
589 $this->tpl->setOnScreenMessage('success', $this->lng->txt('wsp_share_success'), true);
590 }
591 }
592}
Builds data types.
Definition: Factory.php:36
static getInstanceByGlobalUser(?ilObjUser $user=null)
language handling
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static prepareFormOutput($a_str, bool $a_strip=false)
readonly Refinery $refinery
readonly ilLanguage $lng
readonly ilCtrlInterface $ctrl
addPermission(array $a_obj_ids)
appendRecipientSelection(array &$result, int $index, string $search_type, string $recipient_type, string $value)
readonly ilFormatMail $umail
readonly GlobalHttpState $http
ilObjectDataCache $object_data_cache
readonly ilGlobalTemplateInterface $tpl
static _lookupName(int $a_user_id)
static _lookupPref(int $a_usr_id, string $a_keyword)
static _lookupLogin(int $a_user_id)
static _lookupEmail(int $a_user_id)
class ilObjectDataCache
static _getObjectSearchInstance(ilQueryParser $query_parser)
static _getUserSearchInstance(ilQueryParser $query_parser)
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.
class ilRbacReview Contains Review functions of core Rbac.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static get(string $a_var)
static set(string $a_var, $a_val)
Set a value.
static strLen(string $a_string)
Definition: class.ilStr.php:60
This class represents a text property in a property form.
static getImagePath(string $image_name, string $module_path="", string $mode="output", bool $offline=false)
get image path (for images located in a template directory)
static stripSlashes(string $a_str, bool $a_strip_html=true, string $a_allow="")
const ROOT_FOLDER_ID
Definition: constants.php:32
Interface GlobalHttpState.
Interface ResponseHeader.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
static http()
Fetches the global http state from ILIAS.
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
Interface Observer \BackgroundTasks Contains several chained tasks and infos about them.
global $DIC
Definition: shib_login.php:26
$counter