ILIAS  release_6 Revision v6.24-5-g0c8bfefb3b8
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
66 public function __construct($a_user_id = 0)
67 {
68 global $DIC;
69
70 $ilias = $DIC['ilias'];
71 $ilAccess = $DIC['ilAccess'];
72 $ilDB = $DIC['ilDB'];
73 $ilUser = $DIC['ilUser'];
74
75 $this->ilAccess = $ilAccess;
76 if ($a_user_id) {
77 $this->user_id = $a_user_id;
78 } else {
79 $this->user_id = $ilUser->getId();
80 }
82 $this->initUserSearchCache();
83
84 $this->db = $ilDB;
85 }
86
90 public function setRequiredPermission($a_permission)
91 {
92 $this->permission = $a_permission;
93 }
94
95 public function getRequiredPermission()
96 {
97 return $this->permission;
98 }
99
100
101 public function setUserId($a_user_id)
102 {
103 $this->user_id = $a_user_id;
104 }
105 public function getUserId()
106 {
107 return $this->user_id;
108 }
109
110 public function getEntries()
111 {
112 return $this->entries ? $this->entries : array();
113 }
114
115 public function isLimitReached()
116 {
117 return $this->limit_reached ? true : false;
118 }
119
120 public function setMaxHits($a_max_hits)
121 {
122 $this->max_hits = $a_max_hits;
123 }
124 public function getMaxHits()
125 {
126 return $this->max_hits;
127 }
128
136 public function isOffsetReached($a_counter)
137 {
138 return ($a_counter < $this->offset) ? false : true;
139 }
140
151 public function addEntry($a_obj_id, $a_type, $found, $a_child_id = 0)
152 {
153 // Create new entry if it not exists
154 if (!$this->entries[$a_obj_id]) {
155 $this->entries[$a_obj_id]['obj_id'] = $a_obj_id;
156 $this->entries[$a_obj_id]['type'] = $a_type;
157 $this->entries[$a_obj_id]['found'] = $found;
158 $this->entries[$a_obj_id]['child'] = [];
159
160 if ($a_child_id and $a_child_id != $a_obj_id) {
161 $this->entries[$a_obj_id]['child'][$a_child_id] = $a_child_id;
162 }
163 } else {
164 // replace or add child ('pg','st') id
165 if ($a_child_id and $a_child_id != $a_obj_id) {
166 $this->entries[$a_obj_id]['child'][$a_child_id] = $a_child_id;
167 }
168
169 // UPDATE FOUND
170 $counter = 0;
171 foreach ($found as $position) {
172 if ($position) {
173 $this->entries[$a_obj_id]['found'][$counter] = $position;
174 }
175 $counter++;
176 }
177 }
178 return true;
179 }
180
186 public function numEntries()
187 {
188 return count($this->getEntries());
189 }
190
197 public function mergeEntries(&$result_obj)
198 {
199 foreach ($result_obj->getEntries() as $entry) {
200 $this->addEntry($entry['obj_id'], $entry['type'], $entry['found']);
201 $this->__updateEntryChilds($entry['obj_id'], $entry['child']);
202 }
203 return true;
204 }
205
213 public function diffEntriesFromResult(&$result_obj)
214 {
215 $new_entries = $this->getEntries();
216 $this->entries = array();
217
218 // Get all checked objects
219 foreach ($this->search_cache->getCheckedItems() as $ref_id => $obj_id) {
220 if (isset($new_entries[$obj_id])) {
221 $this->addEntry(
222 $new_entries[$obj_id]['obj_id'],
223 $new_entries[$obj_id]['type'],
224 $new_entries[$obj_id]['found']
225 );
226 $this->__updateEntryChilds(
227 $new_entries[$obj_id]['obj_id'],
228 $new_entries[$obj_id]['child']
229 );
230 }
231 }
232 }
233
240 public function intersectEntries(&$result_obj)
241 {
242 $new_entries = $this->getEntries();
243 $this->entries = array();
244
245 foreach ($result_obj->getEntries() as $entry) {
246 $obj_id = $entry['obj_id'];
247 if (isset($new_entries[$obj_id])) {
248 $this->addEntry(
249 $new_entries[$obj_id]['obj_id'],
250 $new_entries[$obj_id]['type'],
251 $new_entries[$obj_id]['found']
252 );
253
254 $this->__updateEntryChilds(
255 $new_entries[$obj_id]['obj_id'],
256 $new_entries[$obj_id]['child']
257 );
258 }
259 }
260 }
261
262
272 public function addResult($a_ref_id, $a_obj_id, $a_type)
273 {
274 $this->results[$a_ref_id]['ref_id'] = $a_ref_id;
275 $this->results[$a_ref_id]['obj_id'] = $a_obj_id;
276 $this->results[$a_ref_id]['type'] = $a_type;
277 }
278
279 public function getResults()
280 {
281 return $this->results ? $this->results : array();
282 }
283
290 public function getResultIds()
291 {
292 foreach ($this->getResults() as $id => $tmp) {
293 $ids[] = $id;
294 }
295 return $ids ? $ids : array();
296 }
297
298 public function getResultsByObjId()
299 {
300 $tmp_res = array();
301 foreach ($this->getResults() as $ref_id => $res_data) {
302 $tmp_res[$res_data['obj_id']][] = $ref_id;
303 }
304 return $tmp_res ? $tmp_res : array();
305 }
306
307
314 public function getUniqueResults()
315 {
316 $obj_ids = array();
317 foreach ($this->results as $result) {
318 if (in_array($result['obj_id'], $obj_ids)) {
319 continue;
320 }
321 $obj_ids[] = $result['obj_id'];
322 $objects[] = $result;
323 }
324 return $objects ? $objects : array();
325 }
326
328 {
329 $res = array();
330
331 foreach ($this->getResults() as $result) {
332 $res[$result['ref_id']] = $result['obj_id'];
333 }
334 return $res;
335 }
336
337 public function getSubitemIds()
338 {
339 $res = array();
340 foreach ($this->getResults() as $row) {
341 $res[$row['obj_id']] = $row['child'];
342 }
343 return $res ? $res : array();
344 }
345
346
347
360 public function filter($a_root_node, $check_and)
361 {
362 global $DIC;
363
364 $tree = $DIC['tree'];
365
366 // get ref_ids and check access
367 $counter = 0;
368 $offset_counter = 0;
369 foreach ($this->getEntries() as $entry) {
370 // boolean and failed continue
371 if ($check_and and in_array(0, $entry['found'])) {
372 continue;
373 }
374 // Types like role, rolt, user do not need rbac checks
375 $type = ilObject::_lookupType($entry['obj_id']);
376 if ($type == 'rolt' or $type == 'usr' or $type == 'role') {
377 if ($this->callListeners($entry['obj_id'], $entry)) {
378 $this->addResult($entry['obj_id'], $entry['obj_id'], $type);
379 if (is_array($entry['child'])) {
380 $counter += count($entry['child']);
381 }
382 // Stop if maximum of hits is reached
383 if (++$counter > $this->getMaxHits()) {
384 $this->limit_reached = true;
385 return true;
386 }
387 }
388 continue;
389 }
390 // Check referenced objects
391 foreach (ilObject::_getAllReferences($entry['obj_id']) as $ref_id) {
392 // Failed check: if ref id check is failed by previous search
393 if ($this->search_cache->isFailed($ref_id)) {
394 continue;
395 }
396 // Offset check
397 if ($this->search_cache->isChecked($ref_id) and !$this->isOffsetReached($offset_counter)) {
398 ++$offset_counter;
399 continue;
400 }
401
402 if (!$this->callListeners($ref_id, $entry)) {
403 continue;
404 }
405
406
407
408 // RBAC check
409 $type = ilObject::_lookupType($ref_id, true);
410 if ($this->ilAccess->checkAccessOfUser(
411 $this->getUserId(),
412 $this->getRequiredPermission(),
413 '',
414 $ref_id,
415 $type,
416 $entry['obj_id']
417 )) {
418 if ($a_root_node == ROOT_FOLDER_ID or $tree->isGrandChild($a_root_node, $ref_id)) {
419 // Call listeners
420 #if($this->callListeners($ref_id,$entry))
421 if (1) {
422 $this->addResult($ref_id, $entry['obj_id'], $type);
423 $this->search_cache->appendToChecked($ref_id, $entry['obj_id']);
424 $this->__updateResultChilds($ref_id, $entry['child']);
425
426 $counter++;
427 $offset_counter++;
428 // Stop if maximum of hits is reached
429
430 if ($counter >= $this->getMaxHits()) {
431 $this->limit_reached = true;
432 $this->search_cache->setResults($this->results);
433 return true;
434 }
435 }
436 }
437 continue;
438 }
439 $this->search_cache->appendToFailed($ref_id);
440 }
441 }
442 $this->search_cache->setResults($this->results);
443 return false;
444 }
445
451 public function filterResults($a_root_node)
452 {
453 global $DIC;
454
455 $tree = $DIC['tree'];
456
457 $tmp_results = $this->getResults();
458 $this->results = array();
459 foreach ($tmp_results as $result) {
460 if ($tree->isGrandChild($a_root_node, $result['ref_id']) and $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 return true;
467 }
468
469
476 public function save($a_type = DEFAULT_SEARCH)
477 {
478 $this->search_cache->save();
479 return false;
480 }
487 public function read($a_type = DEFAULT_SEARCH)
488 {
489 $this->results = $this->search_cache->getResults();
490 }
491
492 // PRIVATE
500 public function __updateEntryChilds($a_obj_id, $a_childs)
501 {
502 if ($this->entries[$a_obj_id] and is_array($a_childs)) {
503 foreach ($a_childs as $child_id) {
504 if ($child_id) {
505 $this->entries[$a_obj_id]['child'][$child_id] = $child_id;
506 }
507 }
508 return true;
509 }
510 return false;
511 }
519 public function __updateResultChilds($a_ref_id, $a_childs)
520 {
521 if ($this->results[$a_ref_id] and is_array($a_childs)) {
522 foreach ($a_childs as $child_id) {
523 $this->results[$a_ref_id]['child'][$child_id] = $child_id;
524 }
525 return true;
526 }
527 return false;
528 }
529
530
531
533 {
534 include_once 'Services/Search/classes/class.ilSearchSettings.php';
535
536 $this->search_settings = new ilSearchSettings();
537 if (!$this->preventOverwritingMaxhits()) {
538 $this->setMaxHits($this->search_settings->getMaxHits());
539 }
540 }
541
548 protected function initUserSearchCache()
549 {
550 include_once('Services/Search/classes/class.ilUserSearchCache.php');
551 $this->search_cache = ilUserSearchCache::_getInstance($this->getUserId());
552 $this->offset = $this->getMaxHits() * ($this->search_cache->getResultPageNumber() - 1) ;
553 }
554
564 public function preventOverwritingMaxhits($a_flag = null)
565 {
566 if (null === $a_flag) {
568 }
569
570 $this->preventOverwritingMaxhits = $a_flag;
571
572 return $this;
573 }
574
584 public function addObserver(&$a_class, $a_method)
585 {
586 $this->observers[] = array('class' => $a_class,
587 'method' => $a_method);
588 return true;
589 }
590 public function callListeners($a_ref_id, &$a_data)
591 {
592 foreach ($this->observers as $observer) {
593 $class = &$observer['class'];
594 $method = $observer['method'];
595
596 if (!$class->$method($a_ref_id, $a_data)) {
597 return false;
598 }
599 }
600 return true;
601 }
602} // END class.Search
An exception for terminatinating execution or to throw for unit testing.
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.
$type
foreach($_POST as $key=> $value) $res
global $ilDB
$ilUser
Definition: imgupload.php:18
$a_type
Definition: workflow.php:92
$DIC
Definition: xapitoken.php:46