00001 <?php
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00033 class ilSearch
00034 {
00040 var $ilias;
00041 var $lng;
00042 var $rbacsystem;
00043 var $user_id;
00044 var $search_string;
00045 var $parsed_str;
00046 var $combination;
00047 var $min_word_length = 3;
00048 var $search_for;
00049 var $search_in;
00050 var $search_type;
00051 var $result;
00052 var $perform_update;
00053 var $read_db_result;
00054
00055 var $allow_empty_search;
00060 function ilSearch($a_user_id = 0,$a_read = false)
00061 {
00062 global $ilias,$rbacsystem,$lng;
00063
00064
00065 $this->ilias =& $ilias;
00066 $this->lng =& $lng;
00067 $this->lng->loadLanguageModule("search");
00068 $this->rbacsystem =& $rbacsystem;
00069 $this->user_id = $a_user_id;
00070
00071 $this->setPerformUpdate(true);
00072 $this->setEmptySearch(false);
00073 $this->read_db_result = $a_read;
00074
00075
00076 #$this->__readDBResult();
00077 }
00078
00079
00080 function setSearchString($a_search_str)
00081 {
00082 $this->search_string = trim($a_search_str);
00083 }
00084 function setCombination($a_combination)
00085 {
00086
00087 $this->combination = $a_combination;
00088 }
00089 function setSearchFor($a_search_for)
00090 {
00091 $this->search_for = $a_search_for;
00092 }
00093 function setSearchIn($a_search_in)
00094 {
00095 $this->search_in = $a_search_in;
00096 }
00097 function setResult($a_result)
00098 {
00099 $this->result = $a_result;
00100 }
00101 function setSearchType($a_type)
00102 {
00103 $this->search_type = $a_type;
00104 }
00105 function setPerformUpdate($a_value)
00106 {
00107 $this->perform_update = $a_value;
00108 }
00109 function setEmptySearch($a_value)
00110 {
00111 $this->allow_empty_search = $a_value;
00112 }
00113
00114 function setMinWordLength($a_min_word_length)
00115 {
00116 $this->min_word_length = $a_min_word_length;
00117 }
00118 function getMinWordLength()
00119 {
00120 return $this->min_word_length;
00121 }
00122
00123
00124 function getUserId()
00125 {
00126 return $this->user_id;
00127 }
00128 function getSearchString()
00129 {
00130 return $this->search_string;
00131 }
00132 function getCombination()
00133 {
00134 return $this->combination ? $this->combination : "or";
00135 }
00136 function getSearchFor()
00137 {
00138 return $this->search_for ? $this->search_for : array();
00139 }
00140 function getSearchIn()
00141 {
00142 return $this->search_in ? $this->search_in : array();
00143 }
00144 function getSearchInByType($a_type)
00145 {
00146 if($a_type == 'lm' or $a_type == 'dbk')
00147 {
00148 return $this->search_in[$a_type];
00149 }
00150 else
00151 {
00152 return false;
00153 }
00154 }
00155 function getResults()
00156 {
00157 return $this->result ? $this->result : array();
00158 }
00159 function getResultByType($a_type)
00160 {
00161 return $this->result[$a_type] ? $this->result[$a_type] : array();
00162 }
00163 function getSearchType()
00164 {
00165 return $this->search_type;
00166 }
00167 function getPerformUpdate()
00168 {
00169 return $this->perform_update;
00170 }
00171 function getEmptySearch()
00172 {
00173 return $this->allow_empty_search;
00174 }
00175
00176
00177
00178 function getNumberOfResults()
00179 {
00180 $number = count($this->getResultByType("usr")) + count($this->getResultByType("grp")) + count($this->getResultByType("role"));
00181
00182 $tmp_res = $this->getResultByType("dbk");
00183 $number += count($tmp_res["meta"]) + count($tmp_res["content"]);
00184
00185 $tmp_res = $this->getResultByType("lm");
00186 $number += count($tmp_res["meta"]) + count($tmp_res["content"]);
00187
00188 return $number;
00189 }
00190
00191 function validate(&$message)
00192 {
00193 $ok = true;
00194
00195 if(!$this->getEmptySearch())
00196 {
00197 if(!$this->getSearchString())
00198 {
00199 $message .= $this->lng->txt("search_no_search_term")."<br/>";
00200 $ok = false;
00201 }
00202 $this->__parseSearchString();
00203
00204 if(!$this->__validateParsedString($message))
00205 {
00206 $ok = false;
00207 }
00208 if(!$this->getSearchFor())
00209 {
00210 $message .= $this->lng->txt("search_no_category")."<br/>";
00211 $ok = false;
00212 }
00213 }
00214 return $ok;
00215 }
00216
00217 function performSearch()
00218 {
00219 global $objDefinition, $ilBench;
00220
00221 $ilBench->start("Search", "performSearch");
00222
00223 $result = array("usr" => array(),
00224 "grp" => array(),
00225 "lm" => array(),
00226 "dbk" => array(),
00227 "role"=> array());
00228
00229 foreach($this->getSearchFor() as $obj_type)
00230 {
00231 switch($obj_type)
00232 {
00233 case "usr":
00234
00235
00236 $this->act_type = 'usr';
00237 $result["usr"] = ilObjUser::_search($this);
00238 break;
00239
00240 case "grp":
00241 include_once "./classes/class.ilObjGroup.php";
00242
00243 $this->act_type = 'grp';
00244 $result["grp"] = ilObjGroup::_search($this);
00245 $result["grp"] = $this->__checkAccess($result["grp"],'grp');
00246 break;
00247
00248 case "lm":
00249 include_once "./content/classes/class.ilObjContentObject.php";
00250 $this->act_type = 'lm';
00251 $result["lm"][$this->getSearchInByType("lm")] = ilObjContentObject::_search($this,$this->getSearchInByType("lm"));
00252 $result["lm"][$this->getSearchInByType("lm")]
00253 = $this->__checkAccess($result["lm"][$this->getSearchInByType("lm")],'lm');
00254 break;
00255
00256 case "dbk":
00257 include_once "./content/classes/class.ilObjDlBook.php";
00258 $this->act_type = 'dbk';
00259 $result["dbk"][$this->getSearchInByType("dbk")] = ilObjDlBook::_search($this,$this->getSearchInByType("dbk"));
00260 $result["dbk"][$this->getSearchInByType("dbk")]
00261 = $this->__checkAccess($result["dbk"][$this->getSearchInByType("dbk")],'dbk');
00262 break;
00263
00264 case "role":
00265 include_once "./classes/class.ilObjRole.php";
00266
00267 $this->act_type = 'role';
00268 $result["role"] = ilObjRole::_search($this);
00269
00270 #$result["role"] = $this->__checkAccess($result["role"],'role');
00271 break;
00272 }
00273 }
00274
00275 $this->setResult($result);
00276 $this->__validateResults();
00277
00278 if ($this->getPerformUpdate())
00279 {
00280 $this->__updateDBResult();
00281 }
00282
00283 $ilBench->stop("Search", "performSearch");
00284
00285 return true;
00286 }
00287
00288 function getWhereCondition($a_type,$a_fields)
00289 {
00290 switch ($a_type)
00291 {
00292 case "like":
00293 $where = $this->__createLikeCondition($a_fields);
00294 break;
00295
00296 case "fulltext":
00297 $where = $this->__createFulltextCondition($a_fields);
00298 break;
00299 }
00300
00301 return $where;
00302 }
00303
00304 function getInStatement($a_primary)
00305 {
00306 $in = '';
00307
00308 switch ($this->getSearchType())
00309 {
00310 case "new":
00311 $in .= "";
00312 break;
00313
00314 case "result":
00315 # if(count($this->__getResultIdsByActualType()))
00316 # {
00317 $in .= "AND $a_primary IN('".implode("','",$this->__getResultIdsByActualType())."') ";
00318 # }
00319 break;
00320
00321 }
00322
00323 return $in;
00324 }
00325
00326
00327 function __createLikeCondition($a_fields)
00328 {
00329 $where = "WHERE (";
00330 $concat = "CONCAT(\" \",";
00331 $concat .= implode(",\" \",",$a_fields);
00332 $concat .= ") ";
00333
00334 $where .= "1 ";
00335
00336
00337 foreach ($this->parsed_str["and"] as $and)
00338 {
00339 $where .= "AND ";
00340 $where .= $concat;
00341 $where .= "LIKE(\"".$and."\") ";
00342 }
00343
00344
00345 foreach ($this->parsed_str["not"] as $not)
00346 {
00347 $where .= "AND ";
00348 $where .= $concat;
00349 $where .= "NOT LIKE(\"".$not."\") ";
00350 }
00351
00352 if (count($this->parsed_str["or"]) and
00353 !count($this->parsed_str["and"]) and
00354 !count($this->parsed_str["not"]))
00355 {
00356 $where .= "AND ( ";
00357
00358 foreach ($this->parsed_str["all"] as $or)
00359 {
00360 $where .= $concat;
00361 $where .= "LIKE(\"".$or."\") ";
00362 $where .= "OR ";
00363 }
00364
00365 $where .= "0) ";
00366 }
00367
00368 $where .= ") ";
00369
00370 return $where;
00371 }
00372 function __createFulltextCondition($a_fields)
00373 {
00374 $where = "WHERE (";
00375 $match = " MATCH(".implode(",",$a_fields).") ";
00376
00377 $where .= "1 ";
00378
00379 if (count($this->parsed_str["or"]))
00380 {
00381 $where .= "AND ";
00382 $where .= $match;
00383 $where .= " AGAINST('".implode(" ",$this->parsed_str["all"])."') ";
00384 }
00385
00386 foreach ($this->parsed_str["and"] as $and)
00387 {
00388 $where .= "AND ";
00389 $where .= $match;
00390 $where .= "AGAINST('".$and."') ";
00391 }
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401 $where .= ") ";
00402
00403 return $where;
00404 }
00405
00406 function __parseSearchString()
00407 {
00408 $tmp_arr = explode(" ",$this->getSearchString());
00409 $this->parsed_str["and"] = $this->parsed_str["or"] = $this->parsed_str["not"] = array();
00410
00411 foreach ($tmp_arr as $word)
00412 {
00413 #$word = trim($word);
00414 $word = $this->__prepareWord($word);
00415 if ($word)
00416 {
00417 if (substr($word,0,1) == '+')
00418 {
00419 $this->parsed_str["all"][] = substr($word,1);
00420 $this->parsed_str["and"][] = substr($word,1);
00421 continue;
00422 }
00423
00424 if (substr($word,0,1) == '-')
00425 {
00426
00427 #$this->parsed_str["all"][] = substr($word,1);
00428 $this->parsed_str["not"][] = substr($word,1);
00429 continue;
00430 }
00431
00432 if ($this->getCombination() == 'and')
00433 {
00434 $this->parsed_str["all"][] = $word;
00435 $this->parsed_str["and"][] = $word;
00436 continue;
00437 }
00438
00439 if ($this->getCombination() == 'or')
00440 {
00441 $this->parsed_str["all"][] = $word;
00442 $this->parsed_str["or"][] = $word;
00443 continue;
00444 }
00445 }
00446 }
00447 }
00448
00449 function __validateParsedString(&$message)
00450 {
00451 foreach ($this->parsed_str as $type)
00452 {
00453 foreach ($type as $word)
00454 {
00455 if (strlen($word) < $this->getMinWordLength())
00456 {
00457 $to_short = true;
00458 }
00459 }
00460 }
00461
00462 if ($to_short)
00463 {
00464 $message .= ($this->lng->txt('search_to_short').'<br />');
00465 $message .= ($this->lng->txt('search_minimum_characters').' '.$this->getMinWordLength().'<br />');
00466
00467 return false;
00468 }
00469
00470 return true;
00471 }
00472
00473 function __updateDBResult()
00474 {
00475 if ($this->getUserId() != 0 and $this->getUserId() != ANONYMOUS_USER_ID)
00476 {
00477 $query = "REPLACE INTO usr_search ".
00478 "VALUES('".$this->getUserId()."','".addslashes(serialize($this->getResults()))."','0')";
00479
00480 $res = $this->ilias->db->query($query);
00481
00482 return true;
00483 }
00484
00485 return false;
00486 }
00487
00488 function __readDBResult()
00489 {
00490 if ($this->getUserId() != 0 and $this->getUserId() != ANONYMOUS_USER_ID and $this->read_db_result)
00491 {
00492 $query = "SELECT search_result FROM usr_search ".
00493 "WHERE usr_id = '".$this->getUserId()."'";
00494
00495 $res = $this->ilias->db->query($query);
00496
00497 if ($res->numRows())
00498 {
00499 $row = $res->fetchRow(DB_FETCHMODE_OBJECT);
00500 $this->setResult(unserialize(stripslashes($row->search_result)));
00501 }
00502 else
00503 {
00504 $this->setResult(array("usr" => array(),
00505 "grp" => array(),
00506 "lm" => array(),
00507 "dbk" => array()));
00508 }
00509 }
00510 else
00511 {
00512 $this->setResult(array("usr" => array(),
00513 "grp" => array(),
00514 "lm" => array(),
00515 "dbk" => array()));
00516 }
00517
00518 $this->__validateResults();
00519 $this->__updateDBResult();
00520 return true;
00521 }
00522
00523 function __getResultIdsByActualType()
00524 {
00525 $results = $this->getResultByType($this->act_type);
00526
00527
00528 switch ($this->act_type)
00529 {
00530
00531 case "lm":
00532 case "dbk":
00533 $results = $results[$this->getSearchInByType($this->act_type)];
00534 break;
00535 }
00536
00537 if(is_array($results))
00538 {
00539 foreach ($results as $result)
00540 {
00541 $ids[] = $result["id"];
00542 }
00543 }
00544 return $ids ? $ids : array();
00545 }
00546
00547 function __checkAccess($a_results,$a_type)
00548 {
00549 global $ilAccess;
00550
00551 if (is_array($a_results))
00552 {
00553 foreach ($a_results as $result)
00554 {
00555 if($ilAccess->checkAccess('read','',$result['id']))
00556 {
00557 $checked_result[] = $result;
00558 }
00559 }
00560 }
00561 return $checked_result ? $checked_result : array();
00562 }
00563
00564
00565 function _checkParentConditions($a_ref_id)
00566 {
00567 include_once './payment/classes/class.ilPaymentObject.php';
00568 include_once './course/classes/class.ilObjCourse.php';
00569
00570 global $tree,$ilias;
00571
00572 if(!$tree->isInTree($a_ref_id))
00573 {
00574 return false;
00575 }
00576 foreach($tree->getPathFull($a_ref_id) as $node_data)
00577 {
00578 if(!ilPaymentObject::_hasAccess($node_data['child']))
00579 {
00580 return false;
00581 }
00582
00583
00584
00585
00586
00587
00588
00589
00590
00591
00592
00593
00594 }
00595 return true;
00596 }
00597
00598 function __validateResults()
00599 {
00600 global $tree;
00601
00602 $new_result = array();
00603
00604
00605
00606
00607 $this->result['lm']['meta'] = $this->__checkAccess($this->result['lm']['meta'],'lm');
00608 if(is_array($this->result['lm']['meta']))
00609 {
00610 foreach($this->result['lm']['meta'] as $data)
00611 {
00612 if($tree->isInTree($data['id']))
00613 {
00614 $new_result['lm']['meta'][] = $data;
00615 }
00616 }
00617 }
00618 $this->result['lm']['content'] = $this->__checkAccess($this->result['lm']['content'],'lm');
00619 if(is_array($this->result['lm']['content']))
00620 {
00621 foreach($this->result['lm']['content'] as $data)
00622 {
00623 if($tree->isInTree($data['id']))
00624 {
00625 $new_result['lm']['content'][] = $data;
00626 }
00627 }
00628 }
00629 $this->result['dbk']['meta'] = $this->__checkAccess($this->result['dbk']['meta'],'dbk');
00630 if(is_array($this->result['dbk']['meta']))
00631 {
00632 foreach($this->result['dbk']['meta'] as $data)
00633 {
00634 if($tree->isInTree($data['id']))
00635 {
00636 $new_result['dbk']['meta'][] = $data;
00637 }
00638 }
00639 }
00640 $this->result['dbk']['content'] = $this->__checkAccess($this->result['dbk']['content'],'dbk');
00641 if(is_array($this->result['dbk']['content']))
00642 {
00643 foreach($this->result['dbk']['content'] as $data)
00644 {
00645 if($tree->isInTree($data['id']))
00646 {
00647 $new_result['dbk']['content'][] = $data;
00648 }
00649 }
00650 }
00651 $this->result['grp'] = $this->__checkAccess($this->result['grp'],'grp');
00652 if(is_array($this->result['grp']))
00653 {
00654 foreach($this->result['grp'] as $data)
00655 {
00656 if($tree->isInTree($data['id']))
00657 {
00658 $new_result['grp'][] = $data;
00659 }
00660 }
00661 }
00662 if(is_array($this->result['usr']))
00663 {
00664 foreach($this->result['usr'] as $user)
00665 {
00666 if($tmp_obj =& ilObjectFactory::getInstanceByObjId($user['id'],false))
00667 {
00668 $new_result['usr'][] = $user;
00669 }
00670 }
00671 }
00672 if(is_array($this->result['role']))
00673 {
00674 foreach($this->result['role'] as $user)
00675 {
00676 if($tmp_obj =& ilObjectFactory::getInstanceByObjId($user['id'],false))
00677 {
00678 $new_result['role'][] = $user;
00679 }
00680 }
00681 }
00682 $this->setResult($new_result);
00683
00684 return true;
00685 }
00686
00687 function __prepareWord($a_word)
00688 {
00689 $word = trim($a_word);
00690
00691 if(!preg_match('/\*/',$word))
00692 {
00693 return '%'.$word.'%';
00694 }
00695 if(preg_match('/^\*/',$word))
00696 {
00697 return str_replace('*','%',$word);
00698 }
00699 else
00700 {
00701 return '% '.str_replace('*','%',$word);
00702 }
00703 }
00704
00705
00706 }
00707 ?>