• Main Page
  • Related Pages
  • Modules
  • Namespaces
  • Data Structures
  • Files
  • File List
  • Globals

classes/class.ilSearch.php

Go to the documentation of this file.
00001 <?php
00002 /*
00003         +-----------------------------------------------------------------------------+
00004         | ILIAS open source                                                           |
00005         +-----------------------------------------------------------------------------+
00006         | Copyright (c) 1998-2001 ILIAS open source, University of Cologne            |
00007         |                                                                             |
00008         | This program is free software; you can redistribute it and/or               |
00009         | modify it under the terms of the GNU General Public License                 |
00010         | as published by the Free Software Foundation; either version 2              |
00011         | of the License, or (at your option) any later version.                      |
00012         |                                                                             |
00013         | This program is distributed in the hope that it will be useful,             |
00014         | but WITHOUT ANY WARRANTY; without even the implied warranty of              |
00015         | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the               |
00016         | GNU General Public License for more details.                                |
00017         |                                                                             |
00018         | You should have received a copy of the GNU General Public License           |
00019         | along with this program; if not, write to the Free Software                 |
00020         | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA. |
00021         +-----------------------------------------------------------------------------+
00022 */
00023 
00024 
00032 class ilSearch
00033 {
00039         var $ilias;
00040         var $lng;
00041         var $rbacsystem;
00042         var $user_id;                           // INTEGER USED FOR SAVED RESULTS
00043         var $search_string;                     // INPUT FROM SEARCH FORM
00044         var $parsed_str;                        // PARSED INPUT
00045         var $combination;                       // STRING 'and' or 'or'
00046         var $min_word_length = 3;       // Define minimum character length for queries
00047         var $search_for;                        // OBJECT TYPE 'usr','grp','lm','dbk'
00048         var $search_in;                         // STRING SEARCH IN 'content' OR 'meta'
00049         var $search_type;                       // STRING 'new' or 'result'
00050         var $result;                            // RESULT SET array['object_type']['counter']
00051         var $perform_update;            // UPDATE USER SEARCH HISTORY default is true SEE function setPerformUpdate()
00052         var $read_db_result;            // READ db result true/false
00053 
00054         var $allow_empty_search;                // ALLOW EMPTY SEARCH TERM use setEmtySearch(true | false) TO SET THIS VALUE DEFAULT (FALSE)
00059         function ilSearch($a_user_id = 0,$a_read = false)
00060         {
00061                 global $ilias,$rbacsystem,$lng;
00062                 
00063                 // Initiate variables
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                 // READ OLD SEARCH RESULTS FROM DATABASE
00075                 #$this->__readDBResult();
00076         }
00077 
00078         // SET METHODS
00079         function setSearchString($a_search_str)
00080         {
00081                 $this->search_string = trim($a_search_str);
00082         }
00083         function setCombination($a_combination)
00084         {
00085                 // 'and' or 'or'
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         // GET MEHODS
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         // PUBLIC
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                                         // TODO: NOT NICE BUT USEFUL
00234                                         // THIS VAR IS USED IN __getResultIdsByType()
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         // PRIVATE METHODS
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                 // AND
00336                 foreach ($this->parsed_str["and"] as $and)
00337                 {
00338                         $where .= "AND ";
00339                         $where .= $concat;
00340                         $where .= "LIKE(\"".$and."\") ";
00341                 }
00342                 
00343                 // AND NOT
00344                 foreach ($this->parsed_str["not"] as $not)
00345                 {
00346                         $where .= "AND ";
00347                         $where .= $concat;
00348                         $where .= "NOT LIKE(\"".$not."\") ";
00349                 }
00350                 // OR
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                 // OR
00378                 if (count($this->parsed_str["or"]))
00379                 {
00380                         $where .= "AND ";
00381                         $where .= $match;
00382                         $where .= " AGAINST('".implode(" ",$this->parsed_str["all"])."') ";
00383                 }
00384                 // AND  
00385                 foreach ($this->parsed_str["and"] as $and)
00386                 {
00387                         $where .= "AND ";
00388                         $where .= $match;
00389                         $where .= "AGAINST('".$and."') ";
00390                 }
00391                 // AND NOT
00392                 /*
00393                 foreach($this->parsed_str["not"] as $and)
00394                 {
00395                         $where .= "AND NOT ";
00396                         $where .= $match;
00397                         $where .= "AGAINST('".$and."') ";
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                                         // better parsed_str["allmost_all"] ;-)
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                 // GET 'content' or 'meta' array
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         // STATIC
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                         if($node_data['type'] == 'crs')
00583                         {
00584                                 $tmp_obj =& ilObjectFactory::getInstanceByRefId($node_data['child']);
00585                                 $tmp_obj->initCourseMemberObject();
00586 
00587                                 if(!$tmp_obj->members_obj->hasAccess($ilias->account->getId()))
00588                                 {
00589                                         return false;
00590                                 }
00591                         }
00592                         */
00593                 }
00594                 return true;
00595         }
00596 
00597         function __validateResults()
00598         {
00599                 global $tree;
00600 
00601                 $new_result = array();
00602 
00603 
00604                 // check lm meta
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 } // END class.ilSearch
00706 ?>

Generated on Fri Dec 13 2013 17:56:48 for ILIAS Release_3_9_x_branch .rev 46835 by  doxygen 1.7.1