ILIAS  release_8 Revision v8.24
class.ilSearchResult.php
Go to the documentation of this file.
1<?php
2
3declare(strict_types=1);
32{
33 private string $permission = 'visible';
34
35 private int $user_id;
36 private array $entries = array();
37 private array $results = array();
38 private array $observers = array();
39 private int $max_hits = 0;
40
42 protected int $offset = 0;
43
44 // OBJECT VARIABLES
46 protected ilDBInterface $db;
47 protected ilTree $tree;
48 protected ilObjUser $user;
50
51 // Stores info if MAX HITS is reached or not
52 public bool $limit_reached = false;
53
54 protected bool $preventOverwritingMaxhits = false;
55
56 protected ilLogger $logger;
57
58
59
64 public function __construct(int $a_user_id = 0)
65 {
66 global $DIC;
67
68 $this->logger = $DIC->logger()->src();
69 $this->ilAccess = $DIC->access();
70 $this->db = $DIC->database();
71 $this->tree = $DIC->repositoryTree();
72 $this->user = $DIC->user();
73
74 if ($a_user_id) {
75 $this->user_id = $a_user_id;
76 } else {
77 $this->user_id = $this->user->getId();
78 }
80 $this->initUserSearchCache();
81 }
82
86 public function setRequiredPermission(string $a_permission): void
87 {
88 $this->permission = $a_permission;
89 }
90
91 public function getRequiredPermission(): string
92 {
93 return $this->permission;
94 }
95
96
97 public function setUserId(int $a_user_id): void
98 {
99 $this->user_id = $a_user_id;
100 }
101 public function getUserId(): int
102 {
103 return $this->user_id;
104 }
105
106 public function getEntries(): array
107 {
108 return $this->entries;
109 }
110
111 public function isLimitReached(): bool
112 {
114 }
115
116 public function setMaxHits(int $a_max_hits): void
117 {
118 $this->max_hits = $a_max_hits;
119 }
120 public function getMaxHits(): int
121 {
122 return $this->max_hits;
123 }
124
128 public function isOffsetReached(int $a_counter): bool
129 {
130 return !($a_counter < $this->offset);
131 }
132
143 public function addEntry(int $a_obj_id, string $a_type, array $found, int $a_child_id = 0): void
144 {
145 // Create new entry if it not exists
146 if (!isset($this->entries[$a_obj_id])) {
147 $this->entries[$a_obj_id]['obj_id'] = $a_obj_id;
148 $this->entries[$a_obj_id]['type'] = $a_type;
149 $this->entries[$a_obj_id]['found'] = $found;
150 $this->entries[$a_obj_id]['child'] = [];
151
152 if ($a_child_id and $a_child_id != $a_obj_id) {
153 $this->entries[$a_obj_id]['child'][$a_child_id] = $a_child_id;
154 }
155 } else {
156 // replace or add child ('pg','st') id
157 if ($a_child_id and $a_child_id != $a_obj_id) {
158 $this->entries[$a_obj_id]['child'][$a_child_id] = $a_child_id;
159 }
160 $counter = 0;
161 foreach ($found as $position) {
162 if ($position) {
163 $this->entries[$a_obj_id]['found'][$counter] = $position;
164 }
165 $counter++;
166 }
167 }
168 }
169
175 public function numEntries(): int
176 {
177 return count($this->getEntries());
178 }
179
186 public function mergeEntries(ilSearchResult $result_obj): void
187 {
188 foreach ($result_obj->getEntries() as $obj_id => $entry) {
189 $this->addEntry($entry['obj_id'], $entry['type'], $entry['found']);
190 $this->__updateEntryChilds($entry['obj_id'], $entry['child']);
191 }
192 }
193
198 public function diffEntriesFromResult(): void
199 {
200 $new_entries = $this->getEntries();
201 $this->entries = array();
202
203 // Get all checked objects
204 foreach ($this->search_cache->getCheckedItems() as $ref_id => $obj_id) {
205 if (isset($new_entries[$obj_id])) {
206 $this->addEntry(
207 $new_entries[$obj_id]['obj_id'],
208 $new_entries[$obj_id]['type'],
209 $new_entries[$obj_id]['found']
210 );
211 $this->__updateEntryChilds(
212 $new_entries[$obj_id]['obj_id'],
213 $new_entries[$obj_id]['child']
214 );
215 }
216 }
217 }
218
222 public function intersectEntries(ilSearchResult $result_obj): void
223 {
224 $new_entries = $this->getEntries();
225 $this->entries = [];
226 foreach ($result_obj->getEntries() as $entry) {
227 $obj_id = $entry['obj_id'];
228 if (isset($new_entries[$obj_id])) {
229 $this->addEntry(
230 $new_entries[$obj_id]['obj_id'],
231 $new_entries[$obj_id]['type'],
232 $new_entries[$obj_id]['found']
233 );
234
235 $this->__updateEntryChilds(
236 $new_entries[$obj_id]['obj_id'],
237 $new_entries[$obj_id]['child']
238 );
239 }
240 }
241 }
242
243 public function addResult(int $a_ref_id, int $a_obj_id, string $a_type): void
244 {
245 $this->results[$a_ref_id]['ref_id'] = $a_ref_id;
246 $this->results[$a_ref_id]['obj_id'] = $a_obj_id;
247 $this->results[$a_ref_id]['type'] = $a_type;
248 }
249
250 public function getResults(): array
251 {
252 return $this->results;
253 }
254
259 public function getResultIds(): array
260 {
261 $ids = [];
262 foreach ($this->getResults() as $id => $tmp) {
263 $ids[] = $id;
264 }
265 return $ids;
266 }
267
268 public function getResultsByObjId(): array
269 {
270 $tmp_res = [];
271 foreach ($this->getResults() as $ref_id => $res_data) {
272 $tmp_res[$res_data['obj_id']][] = $ref_id;
273 }
274 return $tmp_res;
275 }
276
277
282 public function getUniqueResults(): array
283 {
284 $obj_ids = [];
285 $objects = [];
286 foreach ($this->results as $result) {
287 if (in_array($result['obj_id'], $obj_ids)) {
288 continue;
289 }
290 $obj_ids[] = $result['obj_id'];
291 $objects[] = $result;
292 }
293 return $objects;
294 }
295
296 public function getResultsForPresentation(): array
297 {
298 $res = [];
299 foreach ($this->getResults() as $result) {
300 if (!is_array($result)) {
301 continue;
302 }
303
304 $res[(int) $result['ref_id']] = (int) $result['obj_id'];
305 }
306 return $res;
307 }
308
309 public function getSubitemIds(): array
310 {
311 $res = array();
312 foreach ($this->getResults() as $row) {
313 $res[$row['obj_id']] = $row['child'] ?? [];
314 }
315 return $res;
316 }
317
318
319
325 public function filter(
326 int $a_root_node,
327 bool $check_and,
328 ilDate $creation_filter_date = null,
329 int $creation_filter_operator = null
330 ): bool {
331
332 // get ref_ids and check access
333 $counter = 0;
334 $offset_counter = 0;
335 foreach ($this->getEntries() as $entry) {
336 // boolean and failed continue
337 if ($check_and and in_array(0, $entry['found'])) {
338 continue;
339 }
340 // Types like role, rolt, user do not need rbac checks
341 $type = ilObject::_lookupType($entry['obj_id']);
342 if ($type == 'rolt' or $type == 'usr' or $type == 'role') {
343 if ($this->callListeners($entry['obj_id'], $entry)) {
344 $this->addResult($entry['obj_id'], $entry['obj_id'], $type);
345 if (is_array($entry['child'])) {
346 $counter += count($entry['child']);
347 }
348 // Stop if maximum of hits is reached
349 if (++$counter > $this->getMaxHits()) {
350 $this->limit_reached = true;
351 return true;
352 }
353 }
354 continue;
355 }
356
357 /*
358 * (Re-)check creation date, needed for searches on other tables than obj_data (35275)
359 * Before- and after-operators also allow matching datetimes, see ilObjectSearch::performSearch.
360 */
361 if (!is_null($creation_filter_date) && !is_null($creation_filter_operator)) {
362 if (
363 !ilObject::_exists($entry['obj_id']) ||
364 ($creation_date_string = ilObject::_lookupCreationDate($entry['obj_id'])) === ''
365 ) {
366 continue;
367 }
368 $creation_date = new ilDate(
369 date('Y-m-d', strtotime($creation_date_string)),
371 );
372
373 switch ($creation_filter_operator) {
375 if (ilDate::_before($creation_date, $creation_filter_date)) {
376 continue 2;
377 }
378 break;
379
381 if (ilDate::_after($creation_date, $creation_filter_date)) {
382 continue 2;
383 }
384 break;
385
387 if (!ilDate::_equals($creation_date, $creation_filter_date)) {
388 continue 2;
389 }
390 break;
391 }
392 }
393
394 // Check referenced objects
395 foreach (ilObject::_getAllReferences((int) $entry['obj_id']) as $ref_id) {
396 // Failed check: if ref id check is failed by previous search
397 if ($this->search_cache->isFailed($ref_id)) {
398 continue;
399 }
400 // Offset check
401 if ($this->search_cache->isChecked($ref_id) and !$this->isOffsetReached($offset_counter)) {
402 ++$offset_counter;
403 continue;
404 }
405
406 if (!$this->callListeners($ref_id, $entry)) {
407 continue;
408 }
409
410
411
412 // RBAC check
414 if ($this->ilAccess->checkAccessOfUser(
415 $this->getUserId(),
416 $this->getRequiredPermission(),
417 '',
418 $ref_id,
419 $type,
420 $entry['obj_id']
421 )) {
422 if ($a_root_node == ROOT_FOLDER_ID or $this->tree->isGrandChild($a_root_node, $ref_id)) {
423 // Call listeners
424 #if($this->callListeners($ref_id,$entry))
425 if (1) {
426 $this->addResult($ref_id, $entry['obj_id'], $type);
427 $this->search_cache->appendToChecked($ref_id, $entry['obj_id']);
428 $this->__updateResultChilds($ref_id, $entry['child']);
429
430 $counter++;
431 $offset_counter++;
432 // Stop if maximum of hits is reached
433
434 if ($counter >= $this->getMaxHits()) {
435 $this->limit_reached = true;
436 $this->search_cache->setResults($this->results);
437 return true;
438 }
439 }
440 }
441 continue;
442 }
443 $this->search_cache->appendToFailed($ref_id);
444 }
445 }
446 $this->search_cache->setResults($this->results);
447 return false;
448 }
449
455 public function filterResults(int $a_root_node): void
456 {
457 $tmp_results = $this->getResults();
458 $this->results = array();
459 foreach ($tmp_results as $result) {
460 if ($this->tree->isGrandChild($a_root_node, $result['ref_id']) && $this->tree->isInTree($result['ref_id'])) {
461 $this->addResult($result['ref_id'], $result['obj_id'], $result['type']);
462 $this->__updateResultChilds($result['ref_id'], $result['child'] ?? []);
463 }
464 }
465 }
466
467
473 public function save(int $a_type = ilUserSearchCache::DEFAULT_SEARCH): void
474 {
475 $this->search_cache->save();
476 }
483 public function read(int $a_type = ilUserSearchCache::DEFAULT_SEARCH): void
484 {
485 $this->results = $this->search_cache->getResults();
486 }
487
488 // PRIVATE
496 public function __updateEntryChilds(int $a_obj_id, array $a_childs): bool
497 {
498 if ($this->entries[$a_obj_id] and is_array($a_childs)) {
499 foreach ($a_childs as $child_id) {
500 if ($child_id) {
501 $this->entries[$a_obj_id]['child'][$child_id] = $child_id;
502 }
503 }
504 return true;
505 }
506 return false;
507 }
511 public function __updateResultChilds(int $a_ref_id, array $a_childs): bool
512 {
513 if ($this->results[$a_ref_id] and is_array($a_childs)) {
514 foreach ($a_childs as $child_id) {
515 $this->results[$a_ref_id]['child'][$child_id] = $child_id;
516 }
517 return true;
518 }
519 return false;
520 }
521
522
523
524 public function __initSearchSettingsObject(): void
525 {
526 $this->search_settings = new ilSearchSettings();
527 if (!$this->preventOverwritingMaxhits()) {
528 $this->setMaxHits($this->search_settings->getMaxHits());
529 }
530 }
531
538 protected function initUserSearchCache(): void
539 {
540 $this->search_cache = ilUserSearchCache::_getInstance($this->getUserId());
541 $this->offset = $this->getMaxHits() * ($this->search_cache->getResultPageNumber() - 1) ;
542 }
543
551 public function preventOverwritingMaxhits(?bool $a_flag = null)
552 {
553 if (null === $a_flag) {
554 return $this->preventOverwritingMaxhits;
555 }
556
557 $this->preventOverwritingMaxhits = $a_flag;
558
559 return $this;
560 }
561
570 public function addObserver(object $a_class, string $a_method): bool
571 {
572 $this->observers[] = array('class' => $a_class,
573 'method' => $a_method);
574 return true;
575 }
576
577
578 public function callListeners(int $a_ref_id, array $a_data): bool
579 {
580 foreach ($this->observers as $observer) {
581 $class = &$observer['class'];
582 $method = $observer['method'];
583
584 if (!$class->$method($a_ref_id, $a_data)) {
585 return false;
586 }
587 }
588 return true;
589 }
590} // END class.Search
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
const IL_CAL_DATE
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
checkAccessOfUser(int $a_user_id, string $a_permission, string $a_cmd, int $a_ref_id, string $a_type="", ?int $a_obj_id=0, ?int $a_tree_id=0)
check access for an object (provide $a_type and $a_obj_id if available for better performance)
static _after(ilDateTime $start, ilDateTime $end, string $a_compare_field='', string $a_tz='')
compare two dates and check start is after end This method does not consider tz offsets.
static _equals(ilDateTime $start, ilDateTime $end, string $a_compare_field='', string $a_tz='')
Check if two date are equal.
static _before(ilDateTime $start, ilDateTime $end, string $a_compare_field='', string $a_tz='')
compare two dates and check start is before end This method does not consider tz offsets.
Class for single dates.
Component logger with individual log levels by component id.
User class.
static _lookupType(int $id, bool $reference=false)
static _getAllReferences(int $id)
get all reference ids for object ID
static _exists(int $id, bool $reference=false, ?string $type=null)
checks if an object exists in object_data
static _lookupCreationDate(int $obj_id)
setUserId(int $a_user_id)
isOffsetReached(int $a_counter)
Check if offset is reached.
setRequiredPermission(string $a_permission)
Set the required permission for the rbac checks in function 'filter()'.
getUniqueResults()
Get unique results.
callListeners(int $a_ref_id, array $a_data)
read(int $a_type=ilUserSearchCache::DEFAULT_SEARCH)
read search results
filter(int $a_root_node, bool $check_and, ilDate $creation_filter_date=null, int $creation_filter_operator=null)
Filter search result.
addResult(int $a_ref_id, int $a_obj_id, string $a_type)
__construct(int $a_user_id=0)
Constructor @access public.
initUserSearchCache()
Init user search cache.
__updateEntryChilds(int $a_obj_id, array $a_childs)
Update childs for a specific entry.
addEntry(int $a_obj_id, string $a_type, array $found, int $a_child_id=0)
add search result entry Entries are stored with 'obj_id'.
setMaxHits(int $a_max_hits)
diffEntriesFromResult()
diff entries of this instance and another result object Used for search in results
preventOverwritingMaxhits(?bool $a_flag=null)
If you call this function and pass "true" the maxhits setting will not be overwritten in __initSearch...
ilUserSearchCache $search_cache
numEntries()
Check number of entries @access public.
intersectEntries(ilSearchResult $result_obj)
Build intersection of entries (all entries that are present in both result sets)
mergeEntries(ilSearchResult $result_obj)
merge entries of this instance and another result object
getResultIds()
get result ids
addObserver(object $a_class, string $a_method)
The observer is used to call functions for filtering result.
ilSearchSettings $search_settings
save(int $a_type=ilUserSearchCache::DEFAULT_SEARCH)
Save search results.
__updateResultChilds(int $a_ref_id, array $a_childs)
Update child ids for a specific result.
filterResults(int $a_root_node)
Filter search area of result set @access public.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
Class for storing search result.
static _getInstance(int $a_usr_id)
const ROOT_FOLDER_ID
Definition: constants.php:32
global $DIC
Definition: feed.php:28
Interface ilDBInterface.
$ref_id
Definition: ltiauth.php:67
$res
Definition: ltiservices.php:69
$type