ILIAS  Release_3_10_x_branch Revision 61812
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilSearch.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 
24 
32 class ilSearch
33 {
39  var $ilias;
40  var $lng;
42  var $user_id; // INTEGER USED FOR SAVED RESULTS
43  var $search_string; // INPUT FROM SEARCH FORM
44  var $parsed_str; // PARSED INPUT
45  var $combination; // STRING 'and' or 'or'
46  var $min_word_length = 3; // Define minimum character length for queries
47  var $search_for; // OBJECT TYPE 'usr','grp','lm','dbk'
48  var $search_in; // STRING SEARCH IN 'content' OR 'meta'
49  var $search_type; // STRING 'new' or 'result'
50  var $result; // RESULT SET array['object_type']['counter']
51  var $perform_update; // UPDATE USER SEARCH HISTORY default is true SEE function setPerformUpdate()
52  var $read_db_result; // READ db result true/false
53 
54  var $allow_empty_search; // ALLOW EMPTY SEARCH TERM use setEmtySearch(true | false) TO SET THIS VALUE DEFAULT (FALSE)
59  function ilSearch($a_user_id = 0,$a_read = false)
60  {
61  global $ilias,$rbacsystem,$lng;
62 
63  // Initiate variables
64  $this->ilias =& $ilias;
65  $this->lng =& $lng;
66  $this->lng->loadLanguageModule("search");
67  $this->rbacsystem =& $rbacsystem;
68  $this->user_id = $a_user_id;
69 
70  $this->setPerformUpdate(true);
71  $this->setEmptySearch(false);
72  $this->read_db_result = $a_read;
73 
74  // READ OLD SEARCH RESULTS FROM DATABASE
75  #$this->__readDBResult();
76  }
77 
78  // SET METHODS
79  function setSearchString($a_search_str)
80  {
81  $this->search_string = trim($a_search_str);
82  }
83  function setCombination($a_combination)
84  {
85  // 'and' or 'or'
86  $this->combination = $a_combination;
87  }
88  function setSearchFor($a_search_for)
89  {
90  $this->search_for = $a_search_for;
91  }
92  function setSearchIn($a_search_in)
93  {
94  $this->search_in = $a_search_in;
95  }
96  function setResult($a_result)
97  {
98  $this->result = $a_result;
99  }
100  function setSearchType($a_type)
101  {
102  $this->search_type = $a_type;
103  }
104  function setPerformUpdate($a_value)
105  {
106  $this->perform_update = $a_value;
107  }
108  function setEmptySearch($a_value)
109  {
110  $this->allow_empty_search = $a_value;
111  }
112 
113  function setMinWordLength($a_min_word_length)
114  {
115  $this->min_word_length = $a_min_word_length;
116  }
117  function getMinWordLength()
118  {
119  return $this->min_word_length;
120  }
121 
122  // GET MEHODS
123  function getUserId()
124  {
125  return $this->user_id;
126  }
127  function getSearchString()
128  {
129  return $this->search_string;
130  }
131  function getCombination()
132  {
133  return $this->combination ? $this->combination : "or";
134  }
135  function getSearchFor()
136  {
137  return $this->search_for ? $this->search_for : array();
138  }
139  function getSearchIn()
140  {
141  return $this->search_in ? $this->search_in : array();
142  }
143  function getSearchInByType($a_type)
144  {
145  if($a_type == 'lm' or $a_type == 'dbk')
146  {
147  return $this->search_in[$a_type];
148  }
149  else
150  {
151  return false;
152  }
153  }
154  function getResults()
155  {
156  return $this->result ? $this->result : array();
157  }
158  function getResultByType($a_type)
159  {
160  return $this->result[$a_type] ? $this->result[$a_type] : array();
161  }
162  function getSearchType()
163  {
164  return $this->search_type;
165  }
166  function getPerformUpdate()
167  {
168  return $this->perform_update;
169  }
170  function getEmptySearch()
171  {
173  }
174 
175 
176  // PUBLIC
178  {
179  $number = count($this->getResultByType("usr")) + count($this->getResultByType("grp")) + count($this->getResultByType("role"));
180 
181  $tmp_res = $this->getResultByType("dbk");
182  $number += count($tmp_res["meta"]) + count($tmp_res["content"]);
183 
184  $tmp_res = $this->getResultByType("lm");
185  $number += count($tmp_res["meta"]) + count($tmp_res["content"]);
186 
187  return $number;
188  }
189 
190  function validate(&$message)
191  {
192  $ok = true;
193 
194  if(!$this->getEmptySearch())
195  {
196  if(!$this->getSearchString())
197  {
198  $message .= $this->lng->txt("search_no_search_term")."<br/>";
199  $ok = false;
200  }
201  $this->__parseSearchString();
202 
203  if(!$this->__validateParsedString($message))
204  {
205  $ok = false;
206  }
207  if(!$this->getSearchFor())
208  {
209  $message .= $this->lng->txt("search_no_category")."<br/>";
210  $ok = false;
211  }
212  }
213  return $ok;
214  }
215 
216  function performSearch()
217  {
218  global $objDefinition, $ilBench;
219 
220  $ilBench->start("Search", "performSearch");
221 
222  $result = array("usr" => array(),
223  "grp" => array(),
224  "lm" => array(),
225  "dbk" => array(),
226  "role"=> array());
227 
228  foreach($this->getSearchFor() as $obj_type)
229  {
230  switch($obj_type)
231  {
232  case "usr":
233  // TODO: NOT NICE BUT USEFUL
234  // THIS VAR IS USED IN __getResultIdsByType()
235  $this->act_type = 'usr';
236  $result["usr"] = ilObjUser::_search($this);
237  break;
238 
239  case "grp":
240  include_once "./Modules/Group/classes/class.ilObjGroup.php";
241 
242  $this->act_type = 'grp';
243  $result["grp"] = ilObjGroup::_search($this);
244  $result["grp"] = $this->__checkAccess($result["grp"],'grp');
245  break;
246 
247  case "lm":
248  include_once "./Modules/LearningModule/classes/class.ilObjContentObject.php";
249  $this->act_type = 'lm';
250  $result["lm"][$this->getSearchInByType("lm")] = ilObjContentObject::_search($this,$this->getSearchInByType("lm"));
251  $result["lm"][$this->getSearchInByType("lm")]
252  = $this->__checkAccess($result["lm"][$this->getSearchInByType("lm")],'lm');
253  break;
254 
255  case "dbk":
256  include_once "./Modules/LearningModule/classes/class.ilObjDlBook.php";
257  $this->act_type = 'dbk';
258  $result["dbk"][$this->getSearchInByType("dbk")] = ilObjDlBook::_search($this,$this->getSearchInByType("dbk"));
259  $result["dbk"][$this->getSearchInByType("dbk")]
260  = $this->__checkAccess($result["dbk"][$this->getSearchInByType("dbk")],'dbk');
261  break;
262 
263  case "role":
264  include_once "./Services/AccessControl/classes/class.ilObjRole.php";
265 
266  $this->act_type = 'role';
267  $result["role"] = ilObjRole::_search($this);
268 
269  #$result["role"] = $this->__checkAccess($result["role"],'role');
270  break;
271  }
272  }
273 
274  $this->setResult($result);
275  $this->__validateResults();
276 
277  if ($this->getPerformUpdate())
278  {
279  $this->__updateDBResult();
280  }
281 
282  $ilBench->stop("Search", "performSearch");
283 
284  return true;
285  }
286 
287  function getWhereCondition($a_type,$a_fields)
288  {
289  switch ($a_type)
290  {
291  case "like":
292  $where = $this->__createLikeCondition($a_fields);
293  break;
294 
295  case "fulltext":
296  $where = $this->__createFulltextCondition($a_fields);
297  break;
298  }
299 
300  return $where;
301  }
302 
303  function getInStatement($a_primary)
304  {
305  $in = '';
306 
307  switch ($this->getSearchType())
308  {
309  case "new":
310  $in .= "";
311  break;
312 
313  case "result":
314 # if(count($this->__getResultIdsByActualType()))
315 # {
316  $in .= "AND $a_primary IN('".implode("','",$this->__getResultIdsByActualType())."') ";
317 # }
318  break;
319 
320  }
321 
322  return $in;
323  }
324 
325  // PRIVATE METHODS
326  function __createLikeCondition($a_fields)
327  {
328  $where = "WHERE (";
329  $concat = "CONCAT(\" \",";
330  $concat .= implode(",\" \",",$a_fields);
331  $concat .= ") ";
332 
333  $where .= "1 ";
334 
335  // AND
336  foreach ($this->parsed_str["and"] as $and)
337  {
338  $where .= "AND ";
339  $where .= $concat;
340  $where .= "LIKE(\"".$and."\") ";
341  }
342 
343  // AND NOT
344  foreach ($this->parsed_str["not"] as $not)
345  {
346  $where .= "AND ";
347  $where .= $concat;
348  $where .= "NOT LIKE(\"".$not."\") ";
349  }
350  // OR
351  if (count($this->parsed_str["or"]) and
352  !count($this->parsed_str["and"]) and
353  !count($this->parsed_str["not"]))
354  {
355  $where .= "AND ( ";
356 
357  foreach ($this->parsed_str["all"] as $or)
358  {
359  $where .= $concat;
360  $where .= "LIKE(\"".$or."\") ";
361  $where .= "OR ";
362  }
363 
364  $where .= "0) ";
365  }
366 
367  $where .= ") ";
368 
369  return $where;
370  }
371  function __createFulltextCondition($a_fields)
372  {
373  $where = "WHERE (";
374  $match = " MATCH(".implode(",",$a_fields).") ";
375 
376  $where .= "1 ";
377  // OR
378  if (count($this->parsed_str["or"]))
379  {
380  $where .= "AND ";
381  $where .= $match;
382  $where .= " AGAINST('".implode(" ",$this->parsed_str["all"])."') ";
383  }
384  // AND
385  foreach ($this->parsed_str["and"] as $and)
386  {
387  $where .= "AND ";
388  $where .= $match;
389  $where .= "AGAINST('".$and."') ";
390  }
391  // AND NOT
392  /*
393  foreach($this->parsed_str["not"] as $and)
394  {
395  $where .= "AND NOT ";
396  $where .= $match;
397  $where .= "AGAINST('".$and."') ";
398  }
399  */
400  $where .= ") ";
401 
402  return $where;
403  }
404 
406  {
407  $tmp_arr = explode(" ",$this->getSearchString());
408  $this->parsed_str["and"] = $this->parsed_str["or"] = $this->parsed_str["not"] = array();
409 
410  foreach ($tmp_arr as $word)
411  {
412  #$word = trim($word);
413  $word = $this->__prepareWord($word);
414  if ($word)
415  {
416  if (substr($word,0,1) == '+')
417  {
418  $this->parsed_str["all"][] = substr($word,1);
419  $this->parsed_str["and"][] = substr($word,1);
420  continue;
421  }
422 
423  if (substr($word,0,1) == '-')
424  {
425  // better parsed_str["allmost_all"] ;-)
426  #$this->parsed_str["all"][] = substr($word,1);
427  $this->parsed_str["not"][] = substr($word,1);
428  continue;
429  }
430 
431  if ($this->getCombination() == 'and')
432  {
433  $this->parsed_str["all"][] = $word;
434  $this->parsed_str["and"][] = $word;
435  continue;
436  }
437 
438  if ($this->getCombination() == 'or')
439  {
440  $this->parsed_str["all"][] = $word;
441  $this->parsed_str["or"][] = $word;
442  continue;
443  }
444  }
445  }
446  }
447 
448  function __validateParsedString(&$message)
449  {
450  foreach ($this->parsed_str as $type)
451  {
452  foreach ($type as $word)
453  {
454  if (strlen($word) < $this->getMinWordLength())
455  {
456  $to_short = true;
457  }
458  }
459  }
460 
461  if ($to_short)
462  {
463  $message .= ($this->lng->txt('search_to_short').'<br />');
464  $message .= ($this->lng->txt('search_minimum_characters').' '.$this->getMinWordLength().'<br />');
465 
466  return false;
467  }
468 
469  return true;
470  }
471 
472  function __updateDBResult()
473  {
474  if ($this->getUserId() != 0 and $this->getUserId() != ANONYMOUS_USER_ID)
475  {
476  $query = "REPLACE INTO usr_search ".
477  "VALUES(".$this->ilias->db->quote($this->getUserId()).",'".addslashes(serialize($this->getResults()))."','0')";
478 
479  $res = $this->ilias->db->query($query);
480 
481  return true;
482  }
483 
484  return false;
485  }
486 
487  function __readDBResult()
488  {
489  if ($this->getUserId() != 0 and $this->getUserId() != ANONYMOUS_USER_ID and $this->read_db_result)
490  {
491  $query = "SELECT search_result FROM usr_search ".
492  "WHERE usr_id = ".$this->ilias->db->quote($this->getUserId())." ";
493 
494  $res = $this->ilias->db->query($query);
495 
496  if ($res->numRows())
497  {
498  $row = $res->fetchRow(DB_FETCHMODE_OBJECT);
499  $this->setResult(unserialize(stripslashes($row->search_result)));
500  }
501  else
502  {
503  $this->setResult(array("usr" => array(),
504  "grp" => array(),
505  "lm" => array(),
506  "dbk" => array()));
507  }
508  }
509  else
510  {
511  $this->setResult(array("usr" => array(),
512  "grp" => array(),
513  "lm" => array(),
514  "dbk" => array()));
515  }
516 
517  $this->__validateResults();
518  $this->__updateDBResult();
519  return true;
520  }
521 
523  {
524  $results = $this->getResultByType($this->act_type);
525 
526  // GET 'content' or 'meta' array
527  switch ($this->act_type)
528  {
529 
530  case "lm":
531  case "dbk":
532  $results = $results[$this->getSearchInByType($this->act_type)];
533  break;
534  }
535 
536  if(is_array($results))
537  {
538  foreach ($results as $result)
539  {
540  $ids[] = $result["id"];
541  }
542  }
543  return $ids ? $ids : array();
544  }
545 
546  function __checkAccess($a_results,$a_type)
547  {
548  global $ilAccess;
549 
550  if (is_array($a_results))
551  {
552  foreach ($a_results as $result)
553  {
554  if($ilAccess->checkAccess('read','',$result['id']))
555  {
556  $checked_result[] = $result;
557  }
558  }
559  }
560  return $checked_result ? $checked_result : array();
561  }
562 
563  // STATIC
564  function _checkParentConditions($a_ref_id)
565  {
566  include_once './payment/classes/class.ilPaymentObject.php';
567  include_once './Modules/Course/classes/class.ilObjCourse.php';
568 
569  global $tree,$ilias;
570 
571  if(!$tree->isInTree($a_ref_id))
572  {
573  return false;
574  }
575  foreach($tree->getPathFull($a_ref_id) as $node_data)
576  {
577  if(!ilPaymentObject::_hasAccess($node_data['child']))
578  {
579  return false;
580  }
581  /*
582  if($node_data['type'] == 'crs')
583  {
584  $tmp_obj =& ilObjectFactory::getInstanceByRefId($node_data['child']);
585  $tmp_obj->initCourseMemberObject();
586 
587  if(!$tmp_obj->members_obj->hasAccess($ilias->account->getId()))
588  {
589  return false;
590  }
591  }
592  */
593  }
594  return true;
595  }
596 
597  function __validateResults()
598  {
599  global $tree;
600 
601  $new_result = array();
602 
603 
604  // check lm meta
605 
606  $this->result['lm']['meta'] = $this->__checkAccess($this->result['lm']['meta'],'lm');
607  if(is_array($this->result['lm']['meta']))
608  {
609  foreach($this->result['lm']['meta'] as $data)
610  {
611  if($tree->isInTree($data['id']))
612  {
613  $new_result['lm']['meta'][] = $data;
614  }
615  }
616  }
617  $this->result['lm']['content'] = $this->__checkAccess($this->result['lm']['content'],'lm');
618  if(is_array($this->result['lm']['content']))
619  {
620  foreach($this->result['lm']['content'] as $data)
621  {
622  if($tree->isInTree($data['id']))
623  {
624  $new_result['lm']['content'][] = $data;
625  }
626  }
627  }
628  $this->result['dbk']['meta'] = $this->__checkAccess($this->result['dbk']['meta'],'dbk');
629  if(is_array($this->result['dbk']['meta']))
630  {
631  foreach($this->result['dbk']['meta'] as $data)
632  {
633  if($tree->isInTree($data['id']))
634  {
635  $new_result['dbk']['meta'][] = $data;
636  }
637  }
638  }
639  $this->result['dbk']['content'] = $this->__checkAccess($this->result['dbk']['content'],'dbk');
640  if(is_array($this->result['dbk']['content']))
641  {
642  foreach($this->result['dbk']['content'] as $data)
643  {
644  if($tree->isInTree($data['id']))
645  {
646  $new_result['dbk']['content'][] = $data;
647  }
648  }
649  }
650  $this->result['grp'] = $this->__checkAccess($this->result['grp'],'grp');
651  if(is_array($this->result['grp']))
652  {
653  foreach($this->result['grp'] as $data)
654  {
655  if($tree->isInTree($data['id']))
656  {
657  $new_result['grp'][] = $data;
658  }
659  }
660  }
661  if(is_array($this->result['usr']))
662  {
663  foreach($this->result['usr'] as $user)
664  {
665  if($tmp_obj =& ilObjectFactory::getInstanceByObjId($user['id'],false))
666  {
667  $new_result['usr'][] = $user;
668  }
669  }
670  }
671  if(is_array($this->result['role']))
672  {
673  foreach($this->result['role'] as $user)
674  {
675  if($tmp_obj =& ilObjectFactory::getInstanceByObjId($user['id'],false))
676  {
677  $new_result['role'][] = $user;
678  }
679  }
680  }
681  $this->setResult($new_result);
682 
683  return true;
684  }
685 
686  function __prepareWord($a_word)
687  {
688  $word = trim($a_word);
689 
690  if(!preg_match('/\*/',$word))
691  {
692  return '%'.$word.'%';
693  }
694  if(preg_match('/^\*/',$word))
695  {
696  return str_replace('*','%',$word);
697  }
698  else
699  {
700  return '% '.str_replace('*','%',$word);
701  }
702  }
703 
704 
705 } // END class.ilSearch
706 ?>