ILIAS  trunk Revision v11.0_alpha-3011-gc6b235a2e85
class.ilSearchResult.php
Go to the documentation of this file.
1<?php
2
27{
28 private string $permission = 'visible';
29
30 private int $user_id;
31 private array $entries = array();
32 private array $results = array();
33 private array $observers = array();
34 private int $max_hits = 0;
35
37 protected int $offset = 0;
38
39 // OBJECT VARIABLES
41 protected ilDBInterface $db;
42 protected ilTree $tree;
43 protected ilObjUser $user;
45
46 // Stores info if MAX HITS is reached or not
47 public bool $limit_reached = false;
48
49 protected bool $preventOverwritingMaxhits = false;
50
51 protected ilLogger $logger;
52
53 public function __construct(int $a_user_id = 0)
54 {
55 global $DIC;
56
57 $this->logger = $DIC->logger()->src();
58 $this->ilAccess = $DIC->access();
59 $this->db = $DIC->database();
60 $this->tree = $DIC->repositoryTree();
61 $this->user = $DIC->user();
62
63 if ($a_user_id) {
64 $this->user_id = $a_user_id;
65 } else {
66 $this->user_id = $this->user->getId();
67 }
69 $this->initUserSearchCache();
70 }
71
75 public function setRequiredPermission(string $a_permission): void
76 {
77 $this->permission = $a_permission;
78 }
79
80 public function getRequiredPermission(): string
81 {
82 return $this->permission;
83 }
84
85 public function setUserId(int $a_user_id): void
86 {
87 $this->user_id = $a_user_id;
88 }
89 public function getUserId(): int
90 {
91 return $this->user_id;
92 }
93
94 public function getEntries(): array
95 {
96 return $this->entries;
97 }
98
99 public function isLimitReached(): bool
100 {
102 }
103
104 public function setMaxHits(int $a_max_hits): void
105 {
106 $this->max_hits = $a_max_hits;
107 }
108 public function getMaxHits(): int
109 {
110 return $this->max_hits;
111 }
112
116 public function isOffsetReached(int $a_counter): bool
117 {
118 return !($a_counter < $this->offset);
119 }
120
131 public function addEntry(int $a_obj_id, string $a_type, array $found, int $a_child_id = 0): void
132 {
133 // Create new entry if it not exists
134 if (!isset($this->entries[$a_obj_id])) {
135 $this->entries[$a_obj_id]['obj_id'] = $a_obj_id;
136 $this->entries[$a_obj_id]['type'] = $a_type;
137 $this->entries[$a_obj_id]['found'] = $found;
138 $this->entries[$a_obj_id]['child'] = [];
139
140 if ($a_child_id and $a_child_id != $a_obj_id) {
141 $this->entries[$a_obj_id]['child'][$a_child_id] = $a_child_id;
142 }
143 } else {
144 // replace or add child ('pg','st') id
145 if ($a_child_id and $a_child_id != $a_obj_id) {
146 $this->entries[$a_obj_id]['child'][$a_child_id] = $a_child_id;
147 }
148 $counter = 0;
149 foreach ($found as $position) {
150 if ($position) {
151 $this->entries[$a_obj_id]['found'][$counter] = $position;
152 }
153 $counter++;
154 }
155 }
156 }
157
158 public function numEntries(): int
159 {
160 return count($this->getEntries());
161 }
162
167 public function mergeEntries(ilSearchResult $result_obj): void
168 {
169 foreach ($result_obj->getEntries() as $obj_id => $entry) {
170 $this->addEntry($entry['obj_id'], $entry['type'], $entry['found']);
171 $this->__updateEntryChilds($entry['obj_id'], $entry['child']);
172 }
173 }
174
179 public function diffEntriesFromResult(): void
180 {
181 $new_entries = $this->getEntries();
182 $this->entries = array();
183
184 // Get all checked objects
185 foreach ($this->search_cache->getCheckedItems() as $ref_id => $obj_id) {
186 if (isset($new_entries[$obj_id])) {
187 $this->addEntry(
188 $new_entries[$obj_id]['obj_id'],
189 $new_entries[$obj_id]['type'],
190 $new_entries[$obj_id]['found']
191 );
192 $this->__updateEntryChilds(
193 $new_entries[$obj_id]['obj_id'],
194 $new_entries[$obj_id]['child']
195 );
196 }
197 }
198 }
199
203 public function intersectEntries(ilSearchResult $result_obj): void
204 {
205 $new_entries = $this->getEntries();
206 $this->entries = [];
207 foreach ($result_obj->getEntries() as $entry) {
208 $obj_id = $entry['obj_id'];
209 if (isset($new_entries[$obj_id])) {
210 $this->addEntry(
211 $new_entries[$obj_id]['obj_id'],
212 $new_entries[$obj_id]['type'],
213 $new_entries[$obj_id]['found']
214 );
215
216 $this->__updateEntryChilds(
217 $new_entries[$obj_id]['obj_id'],
218 $new_entries[$obj_id]['child']
219 );
220 }
221 }
222 }
223
224 public function addResult(int $a_ref_id, int $a_obj_id, string $a_type): void
225 {
226 $this->results[$a_ref_id]['ref_id'] = $a_ref_id;
227 $this->results[$a_ref_id]['obj_id'] = $a_obj_id;
228 $this->results[$a_ref_id]['type'] = $a_type;
229 }
230
231 public function getResults(): array
232 {
233 return $this->results;
234 }
235
239 public function getResultIds(): array
240 {
241 $ids = [];
242 foreach ($this->getResults() as $id => $tmp) {
243 $ids[] = $id;
244 }
245 return $ids;
246 }
247
248 public function getResultsByObjId(): array
249 {
250 $tmp_res = [];
251 foreach ($this->getResults() as $ref_id => $res_data) {
252 $tmp_res[$res_data['obj_id']][] = $ref_id;
253 }
254 return $tmp_res;
255 }
256
261 public function getUniqueResults(): array
262 {
263 $obj_ids = [];
264 $objects = [];
265 foreach ($this->results as $result) {
266 if (in_array($result['obj_id'], $obj_ids)) {
267 continue;
268 }
269 $obj_ids[] = $result['obj_id'];
270 $objects[] = $result;
271 }
272 return $objects;
273 }
274
275 public function getResultsForPresentation(): array
276 {
277 $res = [];
278 foreach ($this->getResults() as $result) {
279 if (!is_array($result)) {
280 continue;
281 }
282
283 $res[(int) $result['ref_id']] = (int) $result['obj_id'];
284 }
285 return $res;
286 }
287
288 public function getSubitemIds(): array
289 {
290 $res = array();
291 foreach ($this->getResults() as $row) {
292 $res[$row['obj_id']] = $row['child'] ?? [];
293 }
294 return $res;
295 }
296
302 public function filter(
303 int $a_root_node,
304 bool $check_and,
305 ?ilDate $creation_filter_date_start = null,
306 ?ilDate $creation_filter_date_end = null
307 ): bool {
308 // get ref_ids and check access
309 $counter = 0;
310 $offset_counter = 0;
311 foreach ($this->getEntries() as $entry) {
312 // boolean and failed continue
313 if ($check_and and in_array(0, $entry['found'])) {
314 continue;
315 }
316 // Types like role, rolt, user do not need rbac checks
317 $type = ilObject::_lookupType($entry['obj_id']);
318 if ($type == 'rolt' or $type == 'usr' or $type == 'role') {
319 if ($this->callListeners($entry['obj_id'], $entry)) {
320 $this->addResult($entry['obj_id'], $entry['obj_id'], $type);
321 if (is_array($entry['child'])) {
322 $counter += count($entry['child']);
323 }
324 // Stop if maximum of hits is reached
325 if (++$counter > $this->getMaxHits()) {
326 $this->limit_reached = true;
327 return true;
328 }
329 }
330 continue;
331 }
332
333 /*
334 * (Re-)check creation date, needed for searches on other tables than obj_data (35275)
335 * Before- and after-operators also allow matching datetimes, see ilObjectSearch::performSearch.
336 */
337 if (!is_null($creation_filter_date_start) || !is_null($creation_filter_date_end)) {
338 if (
339 !ilObject::_exists($entry['obj_id']) ||
340 ($creation_date_string = ilObject::_lookupCreationDate($entry['obj_id'])) === ''
341 ) {
342 continue;
343 }
344 $creation_date = new ilDate(
345 date('Y-m-d', strtotime($creation_date_string)),
347 );
348
349 if ($creation_filter_date_start && is_null($creation_filter_date_end)) {
350 if (!ilDate::_after($creation_date, $creation_filter_date_start)) {
351 continue;
352 }
353 } elseif ($creation_filter_date_end && is_null($creation_filter_date_start)) {
354 if (!ilDate::_before($creation_date, $creation_filter_date_end)) {
355 continue;
356 }
357 } elseif (!ilDate::_within($creation_date, $creation_filter_date_start, $creation_filter_date_end)) {
358 continue;
359 }
360 }
361
362 // Check referenced objects
363 foreach (ilObject::_getAllReferences((int) $entry['obj_id']) as $ref_id) {
364 // Failed check: if ref id check is failed by previous search
365 if ($this->search_cache->isFailed($ref_id)) {
366 continue;
367 }
368 // Offset check
369 if ($this->search_cache->isChecked($ref_id) and !$this->isOffsetReached($offset_counter)) {
370 ++$offset_counter;
371 continue;
372 }
373
374 if (!$this->callListeners($ref_id, $entry)) {
375 continue;
376 }
377
378
379
380 // RBAC check
381 $type = ilObject::_lookupType($ref_id, true);
382 if ($this->ilAccess->checkAccessOfUser(
383 $this->getUserId(),
384 $this->getRequiredPermission(),
385 '',
386 $ref_id,
387 $type,
388 $entry['obj_id']
389 )) {
390 if ($a_root_node == ROOT_FOLDER_ID or $this->tree->isGrandChild($a_root_node, $ref_id)) {
391 // Call listeners
392 #if($this->callListeners($ref_id,$entry))
393 if (1) {
394 $this->addResult($ref_id, $entry['obj_id'], $type);
395 $this->search_cache->appendToChecked($ref_id, $entry['obj_id']);
396 $this->__updateResultChilds($ref_id, $entry['child']);
397
398 $counter++;
399 $offset_counter++;
400 // Stop if maximum of hits is reached
401
402 if ($counter >= $this->getMaxHits()) {
403 $this->limit_reached = true;
404 $this->search_cache->setResults($this->results);
405 return true;
406 }
407 }
408 }
409 continue;
410 }
411 $this->search_cache->appendToFailed($ref_id);
412 }
413 }
414 $this->search_cache->setResults($this->results);
415 return false;
416 }
417
421 public function filterResults(int $a_root_node): void
422 {
423 $tmp_results = $this->getResults();
424 $this->results = array();
425 foreach ($tmp_results as $result) {
426 if (isset($result['ref_id']) && $this->tree->isGrandChild($a_root_node, $result['ref_id']) && $this->tree->isInTree($result['ref_id'])) {
427 $this->addResult($result['ref_id'], $result['obj_id'], $result['type']);
428 $this->__updateResultChilds($result['ref_id'], $result['child'] ?? []);
429 }
430 }
431 }
432
433 public function save(int $a_type = ilUserSearchCache::DEFAULT_SEARCH): void
434 {
435 $this->search_cache->save();
436 }
437
438 public function read(int $a_type = ilUserSearchCache::DEFAULT_SEARCH): void
439 {
440 $this->results = $this->search_cache->getResults();
441 }
442
448 public function __updateEntryChilds(int $a_obj_id, array $a_childs): bool
449 {
450 if ($this->entries[$a_obj_id] and is_array($a_childs)) {
451 foreach ($a_childs as $child_id) {
452 if ($child_id) {
453 $this->entries[$a_obj_id]['child'][$child_id] = $child_id;
454 }
455 }
456 return true;
457 }
458 return false;
459 }
460
464 public function __updateResultChilds(int $a_ref_id, array $a_childs): bool
465 {
466 if ($this->results[$a_ref_id] and is_array($a_childs)) {
467 foreach ($a_childs as $child_id) {
468 $this->results[$a_ref_id]['child'][$child_id] = $child_id;
469 }
470 return true;
471 }
472 return false;
473 }
474
475 public function __initSearchSettingsObject(): void
476 {
477 $this->search_settings = new ilSearchSettings();
478 if (!$this->preventOverwritingMaxhits()) {
479 $this->setMaxHits($this->search_settings->getMaxHits());
480 }
481 }
482
483 protected function initUserSearchCache(): void
484 {
485 $this->search_cache = ilUserSearchCache::_getInstance($this->getUserId());
486 $this->offset = $this->getMaxHits() * ($this->search_cache->getResultPageNumber() - 1) ;
487 }
488
496 public function preventOverwritingMaxhits(?bool $a_flag = null)
497 {
498 if (null === $a_flag) {
499 return $this->preventOverwritingMaxhits;
500 }
501
502 $this->preventOverwritingMaxhits = $a_flag;
503
504 return $this;
505 }
506
515 public function addObserver(object $a_class, string $a_method): bool
516 {
517 $this->observers[] = array('class' => $a_class,
518 'method' => $a_method);
519 return true;
520 }
521
522
523 public function callListeners(int $a_ref_id, array $a_data): bool
524 {
525 foreach ($this->observers as $observer) {
526 $class = &$observer['class'];
527 $method = $observer['method'];
528
529 if (!$class->$method($a_ref_id, $a_data)) {
530 return false;
531 }
532 }
533 return true;
534 }
535}
$id
plugin.php for ilComponentBuildPluginInfoObjectiveTest::testAddPlugins
Definition: plugin.php:23
const IL_CAL_DATE
Class ilAccessHandler Checks access for ILIAS objects.
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 _within(ilDateTime $dt, ilDateTime $start, ilDateTime $end, string $a_compare_field='', string $a_tz='')
Check whether an date is within a date duration given by start and end.
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)
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
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)
addResult(int $a_ref_id, int $a_obj_id, string $a_type)
__construct(int $a_user_id=0)
__updateEntryChilds(int $a_obj_id, array $a_childs)
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
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
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)
__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.
filter(int $a_root_node, bool $check_and, ?ilDate $creation_filter_date_start=null, ?ilDate $creation_filter_date_end=null)
Filter search result.
Tree class data representation in hierachical trees using the Nested Set Model with Gaps by Joe Celco...
Class for storing search result.
static _getInstance(int $a_usr_id)
const ROOT_FOLDER_ID
Definition: constants.php:32
Interface ilDBInterface.
$ref_id
Definition: ltiauth.php:66
$res
Definition: ltiservices.php:69
global $DIC
Definition: shib_login.php:26
$counter