ILIAS  release_7 Revision v7.30-3-g800a261c036
class.ilSearchResult.php
Go to the documentation of this file.
1<?php
2/*
3 +-----------------------------------------------------------------------------+
4 | ILIAS open source |
5 +-----------------------------------------------------------------------------+
6 | Copyright (c) 1998-2001 ILIAS open source, University of Cologne |
7 | |
8 | This program is free software; you can redistribute it and/or |
9 | modify it under the terms of the GNU General Public License |
10 | as published by the Free Software Foundation; either version 2 |
11 | of the License, or (at your option) any later version. |
12 | |
13 | This program is distributed in the hope that it will be useful, |
14 | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16 | GNU General Public License for more details. |
17 | |
18 | You should have received a copy of the GNU General Public License |
19 | along with this program; if not, write to the Free Software |
20 | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21 +-----------------------------------------------------------------------------+
22*/
23
34include_once('Services/Search/classes/class.ilUserSearchCache.php');
35
36define('DEFAULT_SEARCH', 0);
37define('ADVANCED_SEARCH', 1);
38define('ADVANCED_MD_SEARCH', 4);
39
41{
42 public $permission = 'visible';
43
44 public $user_id;
45 public $entries = array();
46 public $results = array();
47 public $observers = array();
48
49 protected $search_cache = null;
50 protected $offset = 0;
51
52 // OBJECT VARIABLES
53 public $ilias;
54 public $ilAccess;
55
56 // Stores info if MAX HITS is reached or not
57 public $limit_reached = false;
58 public $result;
59
60 protected $preventOverwritingMaxhits = false;
61
65 private $logger;
66
71 public function __construct($a_user_id = 0)
72 {
73 global $DIC;
74
75 $ilias = $DIC['ilias'];
76 $ilAccess = $DIC['ilAccess'];
77 $ilDB = $DIC['ilDB'];
78 $ilUser = $DIC['ilUser'];
79
80 $this->logger = $DIC->logger()->src();
81
82 $this->ilAccess = $ilAccess;
83 if ($a_user_id) {
84 $this->user_id = $a_user_id;
85 } else {
86 $this->user_id = $ilUser->getId();
87 }
89 $this->initUserSearchCache();
90
91 $this->db = $ilDB;
92 }
93
97 public function setRequiredPermission($a_permission)
98 {
99 $this->permission = $a_permission;
100 }
101
102 public function getRequiredPermission()
103 {
104 return $this->permission;
105 }
106
107
108 public function setUserId($a_user_id)
109 {
110 $this->user_id = $a_user_id;
111 }
112 public function getUserId()
113 {
114 return $this->user_id;
115 }
116
117 public function getEntries()
118 {
119 return $this->entries ? $this->entries : array();
120 }
121
122 public function isLimitReached()
123 {
124 return $this->limit_reached ? true : false;
125 }
126
127 public function setMaxHits($a_max_hits)
128 {
129 $this->max_hits = $a_max_hits;
130 }
131 public function getMaxHits()
132 {
133 return $this->max_hits;
134 }
135
143 public function isOffsetReached($a_counter)
144 {
145 return ($a_counter < $this->offset) ? false : true;
146 }
147
158 public function addEntry($a_obj_id, $a_type, $found, $a_child_id = 0)
159 {
160 // Create new entry if it not exists
161 if (!$this->entries[$a_obj_id]) {
162 $this->entries[$a_obj_id]['obj_id'] = $a_obj_id;
163 $this->entries[$a_obj_id]['type'] = $a_type;
164 $this->entries[$a_obj_id]['found'] = $found;
165 $this->entries[$a_obj_id]['child'] = [];
166
167 if ($a_child_id and $a_child_id != $a_obj_id) {
168 $this->entries[$a_obj_id]['child'][$a_child_id] = $a_child_id;
169 }
170 } else {
171 // replace or add child ('pg','st') id
172 if ($a_child_id and $a_child_id != $a_obj_id) {
173 $this->entries[$a_obj_id]['child'][$a_child_id] = $a_child_id;
174 }
175
176 // UPDATE FOUND
177 $counter = 0;
178 foreach ($found as $position) {
179 if ($position) {
180 $this->entries[$a_obj_id]['found'][$counter] = $position;
181 }
182 $counter++;
183 }
184 }
185 return true;
186 }
187
193 public function numEntries()
194 {
195 return count($this->getEntries());
196 }
197
204 public function mergeEntries(&$result_obj)
205 {
206 foreach ($result_obj->getEntries() as $entry) {
207 $this->addEntry($entry['obj_id'], $entry['type'], $entry['found']);
208 $this->__updateEntryChilds($entry['obj_id'], $entry['child']);
209 }
210 return true;
211 }
212
220 public function diffEntriesFromResult(&$result_obj)
221 {
222 $new_entries = $this->getEntries();
223 $this->entries = array();
224
225 // Get all checked objects
226 foreach ($this->search_cache->getCheckedItems() as $ref_id => $obj_id) {
227 if (isset($new_entries[$obj_id])) {
228 $this->addEntry(
229 $new_entries[$obj_id]['obj_id'],
230 $new_entries[$obj_id]['type'],
231 $new_entries[$obj_id]['found']
232 );
233 $this->__updateEntryChilds(
234 $new_entries[$obj_id]['obj_id'],
235 $new_entries[$obj_id]['child']
236 );
237 }
238 }
239 }
240
247 public function intersectEntries(&$result_obj)
248 {
249 $new_entries = $this->getEntries();
250 $this->entries = array();
251
252 foreach ($result_obj->getEntries() as $entry) {
253 $obj_id = $entry['obj_id'];
254 if (isset($new_entries[$obj_id])) {
255 $this->addEntry(
256 $new_entries[$obj_id]['obj_id'],
257 $new_entries[$obj_id]['type'],
258 $new_entries[$obj_id]['found']
259 );
260
261 $this->__updateEntryChilds(
262 $new_entries[$obj_id]['obj_id'],
263 $new_entries[$obj_id]['child']
264 );
265 }
266 }
267 }
268
269
279 public function addResult($a_ref_id, $a_obj_id, $a_type)
280 {
281 $this->results[$a_ref_id]['ref_id'] = $a_ref_id;
282 $this->results[$a_ref_id]['obj_id'] = $a_obj_id;
283 $this->results[$a_ref_id]['type'] = $a_type;
284 }
285
286 public function getResults()
287 {
288 return $this->results ? $this->results : array();
289 }
290
297 public function getResultIds()
298 {
299 foreach ($this->getResults() as $id => $tmp) {
300 $ids[] = $id;
301 }
302 return $ids ? $ids : array();
303 }
304
305 public function getResultsByObjId()
306 {
307 $tmp_res = array();
308 foreach ($this->getResults() as $ref_id => $res_data) {
309 $tmp_res[$res_data['obj_id']][] = $ref_id;
310 }
311 return $tmp_res ? $tmp_res : array();
312 }
313
314
321 public function getUniqueResults()
322 {
323 $obj_ids = array();
324 foreach ($this->results as $result) {
325 if (in_array($result['obj_id'], $obj_ids)) {
326 continue;
327 }
328 $obj_ids[] = $result['obj_id'];
329 $objects[] = $result;
330 }
331 return $objects ? $objects : array();
332 }
333
335 {
336 $res = array();
337
338 foreach ($this->getResults() as $result) {
339 $res[$result['ref_id']] = $result['obj_id'];
340 }
341 return $res;
342 }
343
344 public function getSubitemIds()
345 {
346 $res = array();
347 foreach ($this->getResults() as $row) {
348 $res[$row['obj_id']] = $row['child'];
349 }
350 return $res ? $res : array();
351 }
352
353
354
367 public function filter($a_root_node, $check_and)
368 {
369 global $DIC;
370
371 $tree = $DIC['tree'];
372
373 // get ref_ids and check access
374 $counter = 0;
375 $offset_counter = 0;
376 foreach ($this->getEntries() as $entry) {
377 // boolean and failed continue
378 if ($check_and and in_array(0, $entry['found'])) {
379 continue;
380 }
381 // Types like role, rolt, user do not need rbac checks
382 $type = ilObject::_lookupType($entry['obj_id']);
383 if ($type == 'rolt' or $type == 'usr' or $type == 'role') {
384 if ($this->callListeners($entry['obj_id'], $entry)) {
385 $this->addResult($entry['obj_id'], $entry['obj_id'], $type);
386 if (is_array($entry['child'])) {
387 $counter += count($entry['child']);
388 }
389 // Stop if maximum of hits is reached
390 if (++$counter > $this->getMaxHits()) {
391 $this->limit_reached = true;
392 return true;
393 }
394 }
395 continue;
396 }
397 // Check referenced objects
398 foreach (ilObject::_getAllReferences($entry['obj_id']) as $ref_id) {
399 // Failed check: if ref id check is failed by previous search
400 if ($this->search_cache->isFailed($ref_id)) {
401 continue;
402 }
403 // Offset check
404 if ($this->search_cache->isChecked($ref_id) and !$this->isOffsetReached($offset_counter)) {
405 ++$offset_counter;
406 continue;
407 }
408
409 if (!$this->callListeners($ref_id, $entry)) {
410 continue;
411 }
412
413
414
415 // RBAC check
416 $type = ilObject::_lookupType($ref_id, true);
417 if ($this->ilAccess->checkAccessOfUser(
418 $this->getUserId(),
419 $this->getRequiredPermission(),
420 '',
421 $ref_id,
422 $type,
423 $entry['obj_id']
424 )) {
425 if ($a_root_node == ROOT_FOLDER_ID or $tree->isGrandChild($a_root_node, $ref_id)) {
426 // Call listeners
427 #if($this->callListeners($ref_id,$entry))
428 if (1) {
429 $this->addResult($ref_id, $entry['obj_id'], $type);
430 $this->search_cache->appendToChecked($ref_id, $entry['obj_id']);
431 $this->__updateResultChilds($ref_id, $entry['child']);
432
433 $counter++;
434 $offset_counter++;
435 // Stop if maximum of hits is reached
436
437 if ($counter >= $this->getMaxHits()) {
438 $this->limit_reached = true;
439 $this->search_cache->setResults($this->results);
440 return true;
441 }
442 }
443 }
444 continue;
445 }
446 $this->search_cache->appendToFailed($ref_id);
447 }
448 }
449 $this->search_cache->setResults($this->results);
450 return false;
451 }
452
458 public function filterResults($a_root_node)
459 {
460 global $DIC;
461
462 $tree = $DIC['tree'];
463
464 $tmp_results = $this->getResults();
465 $this->results = array();
466 foreach ($tmp_results as $result) {
467 if ($tree->isGrandChild($a_root_node, $result['ref_id']) and $tree->isInTree($result['ref_id'])) {
468 $this->addResult($result['ref_id'], $result['obj_id'], $result['type']);
469 $this->__updateResultChilds($result['ref_id'], $result['child']);
470 }
471 }
472
473 return true;
474 }
475
476
483 public function save($a_type = DEFAULT_SEARCH)
484 {
485 $this->search_cache->save();
486 return false;
487 }
494 public function read($a_type = DEFAULT_SEARCH)
495 {
496 $this->results = $this->search_cache->getResults();
497 }
498
499 // PRIVATE
507 public function __updateEntryChilds($a_obj_id, $a_childs)
508 {
509 if ($this->entries[$a_obj_id] and is_array($a_childs)) {
510 foreach ($a_childs as $child_id) {
511 if ($child_id) {
512 $this->entries[$a_obj_id]['child'][$child_id] = $child_id;
513 }
514 }
515 return true;
516 }
517 return false;
518 }
526 public function __updateResultChilds($a_ref_id, $a_childs)
527 {
528 if ($this->results[$a_ref_id] and is_array($a_childs)) {
529 foreach ($a_childs as $child_id) {
530 $this->results[$a_ref_id]['child'][$child_id] = $child_id;
531 }
532 return true;
533 }
534 return false;
535 }
536
537
538
540 {
541 include_once 'Services/Search/classes/class.ilSearchSettings.php';
542
543 $this->search_settings = new ilSearchSettings();
544 if (!$this->preventOverwritingMaxhits()) {
545 $this->setMaxHits($this->search_settings->getMaxHits());
546 }
547 }
548
555 protected function initUserSearchCache()
556 {
557 include_once('Services/Search/classes/class.ilUserSearchCache.php');
558 $this->search_cache = ilUserSearchCache::_getInstance($this->getUserId());
559 $this->offset = $this->getMaxHits() * ($this->search_cache->getResultPageNumber() - 1) ;
560 }
561
571 public function preventOverwritingMaxhits($a_flag = null)
572 {
573 if (null === $a_flag) {
575 }
576
577 $this->preventOverwritingMaxhits = $a_flag;
578
579 return $this;
580 }
581
591 public function addObserver(&$a_class, $a_method)
592 {
593 $this->observers[] = array('class' => $a_class,
594 'method' => $a_method);
595 return true;
596 }
597 public function callListeners($a_ref_id, &$a_data)
598 {
599 foreach ($this->observers as $observer) {
600 $class = &$observer['class'];
601 $method = $observer['method'];
602
603 if (!$class->$method($a_ref_id, $a_data)) {
604 return false;
605 }
606 }
607 return true;
608 }
609} // END class.Search
An exception for terminatinating execution or to throw for unit testing.
return true
Flag indicating whether or not HTTP headers will be sent when outputting captcha image/audio.
const DEFAULT_SEARCH
Class ilAccessHandler.
checkAccessOfUser($a_user_id, $a_permission, $a_cmd, $a_ref_id, $a_type="", $a_obj_id="", $a_tree_id="")
check access for an object (provide $a_type and $a_obj_id if available for better performance)
static _getAllReferences($a_id)
get all reference ids of object
static _lookupType($a_id, $a_reference=false)
lookup object type
addObserver(&$a_class, $a_method)
The observer is used to call functions for filtering result.
setRequiredPermission($a_permission)
Set the required permission for the rbac checks in function 'filter()'.
__construct($a_user_id=0)
Constructor @access public.
getUniqueResults()
Get unique results.
mergeEntries(&$result_obj)
merge entries of this instance and another result object
save($a_type=DEFAULT_SEARCH)
Save search results.
isOffsetReached($a_counter)
Check if offset is reached.
initUserSearchCache()
Init user search cache.
filterResults($a_root_node)
Filter search area of result set @access public.
diffEntriesFromResult(&$result_obj)
diff entries of this instance and another result object Used for search in results
filter($a_root_node, $check_and)
Filter search result.
numEntries()
Check number of entries @access public.
callListeners($a_ref_id, &$a_data)
addEntry($a_obj_id, $a_type, $found, $a_child_id=0)
add search result entry Entries are stored with 'obj_id'.
getResultIds()
get result ids
addResult($a_ref_id, $a_obj_id, $a_type)
add search result Results are stored with 'ref_id'.
__updateResultChilds($a_ref_id, $a_childs)
Update childs for a specific result.
read($a_type=DEFAULT_SEARCH)
read search results
__updateEntryChilds($a_obj_id, $a_childs)
Update childs for a specific entry.
preventOverwritingMaxhits($a_flag=null)
If you call this function and pass "true" the maxhits setting will not be overwritten in __initSearch...
intersectEntries(&$result_obj)
Build intersection of entries (all entries that are present in both result sets)
static _getInstance($a_usr_id)
Get singleton instance.
const ROOT_FOLDER_ID
Definition: constants.php:30
global $DIC
Definition: goto.php:24
$ilUser
Definition: imgupload.php:18
$type
foreach($_POST as $key=> $value) $res
global $ilDB