ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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 {
69
70 $this->ilAccess = $ilAccess;
71 if ($a_user_id) {
72 $this->user_id = $a_user_id;
73 } else {
74 $this->user_id = $ilUser->getId();
75 }
77 $this->initUserSearchCache();
78
79 $this->db = $ilDB;
80 }
81
85 public function setRequiredPermission($a_permission)
86 {
87 $this->permission = $a_permission;
88 }
89
90 public function getRequiredPermission()
91 {
92 return $this->permission;
93 }
94
95
96 public function setUserId($a_user_id)
97 {
98 $this->user_id = $a_user_id;
99 }
100 public function getUserId()
101 {
102 return $this->user_id;
103 }
104
105 public function getEntries()
106 {
107 return $this->entries ? $this->entries : array();
108 }
109
110 public function isLimitReached()
111 {
112 return $this->limit_reached ? true : false;
113 }
114
115 public function setMaxHits($a_max_hits)
116 {
117 $this->max_hits = $a_max_hits;
118 }
119 public function getMaxHits()
120 {
121 return $this->max_hits;
122 }
123
131 public function isOffsetReached($a_counter)
132 {
133 return ($a_counter < $this->offset) ? false : true;
134 }
135
146 public function addEntry($a_obj_id, $a_type, $found, $a_child_id = 0)
147 {
148 // Create new entry if it not exists
149 if (!$this->entries[$a_obj_id]) {
150 $this->entries[$a_obj_id]['obj_id'] = $a_obj_id;
151 $this->entries[$a_obj_id]['type'] = $a_type;
152 $this->entries[$a_obj_id]['found'] = $found;
153 $this->entries[$a_obj_id]['child'] = [];
154
155 if ($a_child_id and $a_child_id != $a_obj_id) {
156 $this->entries[$a_obj_id]['child'][$a_child_id] = $a_child_id;
157 }
158 } else {
159 // replace or add child ('pg','st') id
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
164 // UPDATE FOUND
165 $counter = 0;
166 foreach ($found as $position) {
167 if ($position) {
168 $this->entries[$a_obj_id]['found'][$counter] = $position;
169 }
170 $counter++;
171 }
172 }
173 return true;
174 }
175
181 public function numEntries()
182 {
183 return count($this->getEntries());
184 }
185
192 public function mergeEntries(&$result_obj)
193 {
194 foreach ($result_obj->getEntries() as $entry) {
195 $this->addEntry($entry['obj_id'], $entry['type'], $entry['found']);
196 $this->__updateEntryChilds($entry['obj_id'], $entry['child']);
197 }
198 return true;
199 }
200
208 public function diffEntriesFromResult(&$result_obj)
209 {
210 $new_entries = $this->getEntries();
211 $this->entries = array();
212
213 // Get all checked objects
214 foreach ($this->search_cache->getCheckedItems() as $ref_id => $obj_id) {
215 if (isset($new_entries[$obj_id])) {
216 $this->addEntry(
217 $new_entries[$obj_id]['obj_id'],
218 $new_entries[$obj_id]['type'],
219 $new_entries[$obj_id]['found']
220 );
221 $this->__updateEntryChilds(
222 $new_entries[$obj_id]['obj_id'],
223 $new_entries[$obj_id]['child']
224 );
225 }
226 }
227 }
228
235 public function intersectEntries(&$result_obj)
236 {
237 $new_entries = $this->getEntries();
238 $this->entries = array();
239
240 foreach ($result_obj->getEntries() as $entry) {
241 $obj_id = $entry['obj_id'];
242 if (isset($new_entries[$obj_id])) {
243 $this->addEntry(
244 $new_entries[$obj_id]['obj_id'],
245 $new_entries[$obj_id]['type'],
246 $new_entries[$obj_id]['found']
247 );
248
249 $this->__updateEntryChilds(
250 $new_entries[$obj_id]['obj_id'],
251 $new_entries[$obj_id]['child']
252 );
253 }
254 }
255 }
256
257
267 public function addResult($a_ref_id, $a_obj_id, $a_type)
268 {
269 $this->results[$a_ref_id]['ref_id'] = $a_ref_id;
270 $this->results[$a_ref_id]['obj_id'] = $a_obj_id;
271 $this->results[$a_ref_id]['type'] = $a_type;
272 }
273
274 public function getResults()
275 {
276 return $this->results ? $this->results : array();
277 }
278
285 public function getResultIds()
286 {
287 foreach ($this->getResults() as $id => $tmp) {
288 $ids[] = $id;
289 }
290 return $ids ? $ids : array();
291 }
292
293 public function getResultsByObjId()
294 {
295 $tmp_res = array();
296 foreach ($this->getResults() as $ref_id => $res_data) {
297 $tmp_res[$res_data['obj_id']][] = $ref_id;
298 }
299 return $tmp_res ? $tmp_res : array();
300 }
301
302
309 public function getUniqueResults()
310 {
311 $obj_ids = array();
312 foreach ($this->results as $result) {
313 if (in_array($result['obj_id'], $obj_ids)) {
314 continue;
315 }
316 $obj_ids[] = $result['obj_id'];
317 $objects[] = $result;
318 }
319 return $objects ? $objects : array();
320 }
321
323 {
324 $res = array();
325
326 foreach ($this->getResults() as $result) {
327 $res[$result['ref_id']] = $result['obj_id'];
328 }
329 return $res;
330 }
331
332 public function getSubitemIds()
333 {
334 $res = array();
335 foreach ($this->getResults() as $row) {
336 $res[$row['obj_id']] = $row['child'];
337 }
338 return $res ? $res : array();
339 }
340
341
342
355 public function filter($a_root_node, $check_and)
356 {
357 global $tree;
358
359 // get ref_ids and check access
360 $counter = 0;
361 $offset_counter = 0;
362 foreach ($this->getEntries() as $entry) {
363 // boolean and failed continue
364 if ($check_and and in_array(0, $entry['found'])) {
365 continue;
366 }
367 // Types like role, rolt, user do not need rbac checks
368 $type = ilObject::_lookupType($entry['obj_id']);
369 if ($type == 'rolt' or $type == 'usr' or $type == 'role') {
370 if ($this->callListeners($entry['obj_id'], $entry)) {
371 $this->addResult($entry['obj_id'], $entry['obj_id'], $type);
372 if (is_array($entry['child'])) {
373 $counter += count($entry['child']);
374 }
375 // Stop if maximum of hits is reached
376 if (++$counter > $this->getMaxHits()) {
377 $this->limit_reached = true;
378 return true;
379 }
380 }
381 continue;
382 }
383 // Check referenced objects
384 foreach (ilObject::_getAllReferences($entry['obj_id']) as $ref_id) {
385 // Failed check: if ref id check is failed by previous search
386 if ($this->search_cache->isFailed($ref_id)) {
387 continue;
388 }
389 // Offset check
390 if ($this->search_cache->isChecked($ref_id) and !$this->isOffsetReached($offset_counter)) {
391 ++$offset_counter;
392 continue;
393 }
394
395 if (!$this->callListeners($ref_id, $entry)) {
396 continue;
397 }
398
399
400
401 // RBAC check
402 $type = ilObject::_lookupType($ref_id, true);
403 if ($this->ilAccess->checkAccessOfUser(
404 $this->getUserId(),
405 $this->getRequiredPermission(),
406 '',
407 $ref_id,
408 $type,
409 $entry['obj_id']
410 )) {
411 if ($a_root_node == ROOT_FOLDER_ID or $tree->isGrandChild($a_root_node, $ref_id)) {
412 // Call listeners
413 #if($this->callListeners($ref_id,$entry))
414 if (1) {
415 $this->addResult($ref_id, $entry['obj_id'], $type);
416 $this->search_cache->appendToChecked($ref_id, $entry['obj_id']);
417 $this->__updateResultChilds($ref_id, $entry['child']);
418
419 $counter++;
420 $offset_counter++;
421 // Stop if maximum of hits is reached
422
423 if ($counter >= $this->getMaxHits()) {
424 $this->limit_reached = true;
425 $this->search_cache->setResults($this->results);
426 return true;
427 }
428 }
429 }
430 continue;
431 }
432 $this->search_cache->appendToFailed($ref_id);
433 }
434 }
435 $this->search_cache->setResults($this->results);
436 return false;
437 }
438
444 public function filterResults($a_root_node)
445 {
446 global $tree;
447
448 $tmp_results = $this->getResults();
449 $this->results = array();
450 foreach ($tmp_results as $result) {
451 if ($tree->isGrandChild($a_root_node, $result['ref_id']) and $tree->isInTree($result['ref_id'])) {
452 $this->addResult($result['ref_id'], $result['obj_id'], $result['type']);
453 $this->__updateResultChilds($result['ref_id'], $result['child']);
454 }
455 }
456
457 return true;
458 }
459
460
467 public function save($a_type = DEFAULT_SEARCH)
468 {
469 $this->search_cache->save();
470 return false;
471 }
478 public function read($a_type = DEFAULT_SEARCH)
479 {
480 $this->results = $this->search_cache->getResults();
481 }
482
483 // PRIVATE
491 public function __updateEntryChilds($a_obj_id, $a_childs)
492 {
493 if ($this->entries[$a_obj_id] and is_array($a_childs)) {
494 foreach ($a_childs as $child_id) {
495 if ($child_id) {
496 $this->entries[$a_obj_id]['child'][$child_id] = $child_id;
497 }
498 }
499 return true;
500 }
501 return false;
502 }
510 public function __updateResultChilds($a_ref_id, $a_childs)
511 {
512 if ($this->results[$a_ref_id] and is_array($a_childs)) {
513 foreach ($a_childs as $child_id) {
514 $this->results[$a_ref_id]['child'][$child_id] = $child_id;
515 }
516 return true;
517 }
518 return false;
519 }
520
521
522
524 {
525 include_once 'Services/Search/classes/class.ilSearchSettings.php';
526
527 $this->search_settings = new ilSearchSettings();
528 if (!$this->preventOverwritingMaxhits()) {
529 $this->setMaxHits($this->search_settings->getMaxHits());
530 }
531 }
532
539 protected function initUserSearchCache()
540 {
541 include_once('Services/Search/classes/class.ilUserSearchCache.php');
542 $this->search_cache = ilUserSearchCache::_getInstance($this->getUserId());
543 $this->offset = $this->getMaxHits() * ($this->search_cache->getResultPageNumber() - 1) ;
544 }
545
555 public function preventOverwritingMaxhits($a_flag = null)
556 {
557 if (null === $a_flag) {
559 }
560
561 $this->preventOverwritingMaxhits = $a_flag;
562
563 return $this;
564 }
565
575 public function addObserver(&$a_class, $a_method)
576 {
577 $this->observers[] = array('class' => $a_class,
578 'method' => $a_method);
579 return true;
580 }
581 public function callListeners($a_ref_id, &$a_data)
582 {
583 foreach ($this->observers as $observer) {
584 $class =&$observer['class'];
585 $method = $observer['method'];
586
587 if (!$class->$method($a_ref_id, $a_data)) {
588 return false;
589 }
590 }
591 return true;
592 }
593} // 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.
$counter
if(!array_key_exists('StateId', $_REQUEST)) $id
$type
foreach($_POST as $key=> $value) $res
global $ilDB
$ilUser
Definition: imgupload.php:18
$a_type
Definition: workflow.php:92