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 
34 include_once('Services/Search/classes/class.ilUserSearchCache.php');
35 
36 define('DEFAULT_SEARCH', 0);
37 define('ADVANCED_SEARCH', 1);
38 define('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 
322  public function getResultsForPresentation()
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 
523  public function __initSearchSettingsObject()
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
read($a_type=DEFAULT_SEARCH)
read search results
isOffsetReached($a_counter)
Check if offset is reached.
const DEFAULT_SEARCH
getResultIds()
get result ids
$type
addEntry($a_obj_id, $a_type, $found, $a_child_id=0)
add search result entry Entries are stored with &#39;obj_id&#39;.
filterResults($a_root_node)
Filter search area of result set public.
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)(option...
if(!array_key_exists('StateId', $_REQUEST)) $id
initUserSearchCache()
Init user search cache.
addObserver(&$a_class, $a_method)
The observer is used to call functions for filtering result.
getUniqueResults()
Get unique results.
Class ilAccessHandler.
static _getAllReferences($a_id)
get all reference ids of object
__construct($a_user_id=0)
Constructor public.
diffEntriesFromResult(&$result_obj)
diff entries of this instance and another result object Used for search in results ...
$counter
$a_type
Definition: workflow.php:92
static _getInstance($a_usr_id)
Get singleton instance.
foreach($_POST as $key=> $value) $res
$ilUser
Definition: imgupload.php:18
__updateResultChilds($a_ref_id, $a_childs)
Update childs for a specific result.
addResult($a_ref_id, $a_obj_id, $a_type)
add search result Results are stored with &#39;ref_id&#39;.
__updateEntryChilds($a_obj_id, $a_childs)
Update childs for a specific entry.
Create styles array
The data for the language used.
static _lookupType($a_id, $a_reference=false)
lookup object type
intersectEntries(&$result_obj)
Build intersection of entries (all entries that are present in both result sets)
setRequiredPermission($a_permission)
Set the required permission for the rbac checks in function &#39;filter()&#39;.
mergeEntries(&$result_obj)
merge entries of this instance and another result object
global $ilDB
numEntries()
Check number of entries public.
filter($a_root_node, $check_and)
Filter search result.
callListeners($a_ref_id, &$a_data)
save($a_type=DEFAULT_SEARCH)
Save search results.
preventOverwritingMaxhits($a_flag=null)
If you call this function and pass "true" the maxhits setting will not be overwritten in __initSearch...