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