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 include_once './classes/class.ilRepositoryExplorer.php';
00550
00551 if (is_array($a_results))
00552 {
00553
00554 foreach ($a_results as $result)
00555 {
00556 $obj_id = ilObject::_lookupObjId($result['id']);
00557
00558 if(!$this->_checkParentConditions($result['id']))
00559 {
00560 continue;
00561 }
00562
00563 if(ilRepositoryExplorer::isClickable($a_type,$result['id'],$obj_id) and
00564 ilRepositoryExplorer::isVisible($result['id'],$a_type))
00565 {
00566 $checked_result[] = $result;
00567 }
00568 }
00569
00570 return $checked_result ? $checked_result : array();
00571 }
00572
00573 return false;
00574 }
00575
00576
00577 function _checkParentConditions($a_ref_id)
00578 {
00579 include_once './payment/classes/class.ilPaymentObject.php';
00580 include_once './course/classes/class.ilObjCourse.php';
00581
00582 global $tree,$ilias;
00583
00584 if(!$tree->isInTree($a_ref_id))
00585 {
00586 return false;
00587 }
00588 foreach($tree->getPathFull($a_ref_id) as $node_data)
00589 {
00590 if(!ilPaymentObject::_hasAccess($node_data['child']))
00591 {
00592 return false;
00593 }
00594
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606 }
00607 return true;
00608 }
00609
00610 function __validateResults()
00611 {
00612 global $tree;
00613
00614 $new_result = array();
00615
00616
00617
00618
00619 $this->result['lm']['meta'] = $this->__checkAccess($this->result['lm']['meta'],'lm');
00620 if(is_array($this->result['lm']['meta']))
00621 {
00622 foreach($this->result['lm']['meta'] as $data)
00623 {
00624 if($tree->isInTree($data['id']))
00625 {
00626 $new_result['lm']['meta'][] = $data;
00627 }
00628 }
00629 }
00630 $this->result['lm']['content'] = $this->__checkAccess($this->result['lm']['content'],'lm');
00631 if(is_array($this->result['lm']['content']))
00632 {
00633 foreach($this->result['lm']['content'] as $data)
00634 {
00635 if($tree->isInTree($data['id']))
00636 {
00637 $new_result['lm']['content'][] = $data;
00638 }
00639 }
00640 }
00641 $this->result['dbk']['meta'] = $this->__checkAccess($this->result['dbk']['meta'],'dbk');
00642 if(is_array($this->result['dbk']['meta']))
00643 {
00644 foreach($this->result['dbk']['meta'] as $data)
00645 {
00646 if($tree->isInTree($data['id']))
00647 {
00648 $new_result['dbk']['meta'][] = $data;
00649 }
00650 }
00651 }
00652 $this->result['dbk']['content'] = $this->__checkAccess($this->result['dbk']['content'],'dbk');
00653 if(is_array($this->result['dbk']['content']))
00654 {
00655 foreach($this->result['dbk']['content'] as $data)
00656 {
00657 if($tree->isInTree($data['id']))
00658 {
00659 $new_result['dbk']['content'][] = $data;
00660 }
00661 }
00662 }
00663 $this->result['grp'] = $this->__checkAccess($this->result['grp'],'grp');
00664 if(is_array($this->result['grp']))
00665 {
00666 foreach($this->result['grp'] as $data)
00667 {
00668 if($tree->isInTree($data['id']))
00669 {
00670 $new_result['grp'][] = $data;
00671 }
00672 }
00673 }
00674 if(is_array($this->result['usr']))
00675 {
00676 foreach($this->result['usr'] as $user)
00677 {
00678 if($tmp_obj =& ilObjectFactory::getInstanceByObjId($user['id'],false))
00679 {
00680 $new_result['usr'][] = $user;
00681 }
00682 }
00683 }
00684 if(is_array($this->result['role']))
00685 {
00686 foreach($this->result['role'] as $user)
00687 {
00688 if($tmp_obj =& ilObjectFactory::getInstanceByObjId($user['id'],false))
00689 {
00690 $new_result['role'][] = $user;
00691 }
00692 }
00693 }
00694 $this->setResult($new_result);
00695
00696 return true;
00697 }
00698
00699 function __prepareWord($a_word)
00700 {
00701 $word = trim($a_word);
00702
00703 if(!preg_match('/\*/',$word))
00704 {
00705 return '%'.$word.'%';
00706 }
00707 if(preg_match('/^\*/',$word))
00708 {
00709 return str_replace('*','%',$word);
00710 }
00711 else
00712 {
00713 return '% '.str_replace('*','%',$word);
00714 }
00715 }
00716
00717
00718 }
00719 ?>