2006-07-25 17:10:58 +00:00
|
|
|
<?php
|
|
|
|
require_once("$CFG->dirroot/search/Zend/Search/Lucene.php");
|
|
|
|
|
|
|
|
class SearchResult {
|
|
|
|
public $url,
|
2006-09-20 21:00:45 +00:00
|
|
|
$title,
|
2006-07-25 17:10:58 +00:00
|
|
|
$doctype,
|
|
|
|
$author,
|
|
|
|
$score,
|
|
|
|
$number;
|
|
|
|
} //SearchResult
|
|
|
|
|
|
|
|
|
|
|
|
//split this into Cache class and extend to SearchCache?
|
|
|
|
class SearchCache {
|
|
|
|
private $mode,
|
|
|
|
$valid;
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
public function __construct($mode='session') {
|
|
|
|
$accepted_modes = array('session');
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
if (in_array($mode, $accepted_modes)) {
|
|
|
|
$this->mode = $mode;
|
|
|
|
} else {
|
|
|
|
$this->mode = 'session';
|
|
|
|
} //else
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
$this->valid = true;
|
|
|
|
} //constructor
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
public function can_cache() {
|
|
|
|
return $this->valid;
|
|
|
|
} //can_cache
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
public function cache($id=false, $object=false) {
|
|
|
|
//see if there was a previous query
|
|
|
|
$last_term = $this->fetch('search_last_term');
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
//if this query is different from the last, clear out the last one
|
|
|
|
if ($id != false and $last_term != $id) {
|
|
|
|
$this->clear($last_term);
|
|
|
|
} //if
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
//store the new query if id and object are passed in
|
|
|
|
if ($object and $id) {
|
|
|
|
$this->store('search_last_term', $id);
|
|
|
|
$this->store($id, $object);
|
|
|
|
return true;
|
|
|
|
//otherwise return the stored results
|
2006-09-20 21:00:45 +00:00
|
|
|
} else if ($id and $this->exists($id)) {
|
2006-07-25 17:10:58 +00:00
|
|
|
return $this->fetch($id);
|
|
|
|
} //else
|
|
|
|
} //cache
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
private function exists($id) {
|
|
|
|
switch ($this->mode) {
|
|
|
|
case 'session' :
|
|
|
|
return isset($_SESSION[$id]);
|
|
|
|
} //switch
|
|
|
|
} //exists
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
private function clear($id) {
|
|
|
|
switch ($this->mode) {
|
|
|
|
case 'session' :
|
|
|
|
unset($_SESSION[$id]);
|
|
|
|
session_unregister($id);
|
|
|
|
return;
|
|
|
|
} //switch
|
2006-09-20 21:00:45 +00:00
|
|
|
} //clear
|
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
private function fetch($id) {
|
|
|
|
switch ($this->mode) {
|
|
|
|
case 'session' :
|
|
|
|
return ($this->exists($id)) ? unserialize($_SESSION[$id]) : false;
|
|
|
|
} //switch
|
|
|
|
} //fetch
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
private function store($id, $object) {
|
|
|
|
switch ($this->mode) {
|
|
|
|
case 'session' :
|
|
|
|
$_SESSION[$id] = serialize($object);
|
|
|
|
return;
|
|
|
|
} //switch
|
2006-09-20 21:00:45 +00:00
|
|
|
} //store
|
2006-07-25 17:10:58 +00:00
|
|
|
} //SearchCache
|
2006-09-20 21:00:45 +00:00
|
|
|
|
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
class SearchQuery {
|
|
|
|
private $index,
|
|
|
|
$term,
|
2006-09-20 21:00:45 +00:00
|
|
|
$pagenumber,
|
2006-07-25 17:10:58 +00:00
|
|
|
$cache,
|
|
|
|
$validquery,
|
2006-09-20 21:00:45 +00:00
|
|
|
$validindex,
|
2006-07-25 17:10:58 +00:00
|
|
|
$results,
|
2006-09-08 01:18:48 +00:00
|
|
|
$results_per_page,
|
|
|
|
$total_results;
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
public function __construct($term='', $page=1, $results_per_page=10, $cache=false) {
|
|
|
|
global $CFG;
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
$this->term = $term;
|
|
|
|
$this->pagenumber = $page;
|
|
|
|
$this->cache = $cache;
|
|
|
|
$this->validquery = true;
|
2006-09-20 21:00:45 +00:00
|
|
|
$this->validindex = true;
|
|
|
|
$this->results_per_page = $results_per_page;
|
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
$index_path = SEARCH_INDEX_PATH;
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
try {
|
|
|
|
$this->index = new Zend_Search_Lucene($index_path, false);
|
2006-09-20 21:00:45 +00:00
|
|
|
} catch(Exception $e) {
|
|
|
|
$this->validindex = false;
|
2006-07-25 17:10:58 +00:00
|
|
|
return;
|
|
|
|
} //catch
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
if (empty($this->term)) {
|
|
|
|
$this->validquery = false;
|
|
|
|
} else {
|
|
|
|
$this->set_query($this->term);
|
2006-09-20 21:00:45 +00:00
|
|
|
} //else
|
2006-07-25 17:10:58 +00:00
|
|
|
} //constructor
|
2006-09-20 21:00:45 +00:00
|
|
|
|
|
|
|
public function set_query($term='') {
|
2006-07-25 17:10:58 +00:00
|
|
|
if (!empty($term)) {
|
|
|
|
$this->term = $term;
|
|
|
|
} //if
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
if (empty($this->term)) {
|
|
|
|
$this->validquery = false;
|
|
|
|
} else {
|
|
|
|
$this->validquery = true;
|
|
|
|
} //else
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
if ($this->validquery and $this->validindex) {
|
|
|
|
$this->results = $this->get_results();
|
|
|
|
} else {
|
|
|
|
$this->results = array();
|
2006-09-20 21:00:45 +00:00
|
|
|
} //else
|
2006-07-25 17:10:58 +00:00
|
|
|
} //set_query
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
public function results() {
|
2006-09-08 01:18:48 +00:00
|
|
|
return $this->results;
|
2006-07-25 17:10:58 +00:00
|
|
|
} //results
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-09-08 01:18:48 +00:00
|
|
|
private function process_results($all=false) {
|
2006-07-25 17:10:58 +00:00
|
|
|
global $USER;
|
2006-09-08 01:18:48 +00:00
|
|
|
|
2006-09-20 21:00:45 +00:00
|
|
|
$term = strtolower($this->term);
|
|
|
|
|
2006-09-08 01:18:48 +00:00
|
|
|
//experimental - return more results
|
2006-09-20 21:00:45 +00:00
|
|
|
$strip_arr = array('author:', 'title:', '+', '-', 'doctype:');
|
2006-09-08 01:18:48 +00:00
|
|
|
$stripped_term = str_replace($strip_arr, '', $term);
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-09-08 01:18:48 +00:00
|
|
|
$hits = $this->index->find($term." title:".$stripped_term." author:".$stripped_term);
|
|
|
|
//--
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-09-08 01:18:48 +00:00
|
|
|
$hitcount = count($hits);
|
2006-09-20 21:00:45 +00:00
|
|
|
$this->total_results = $hitcount;
|
|
|
|
|
2006-09-08 01:18:48 +00:00
|
|
|
if ($hitcount == 0) return array();
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-09-08 01:18:48 +00:00
|
|
|
$totalpages = ceil($hitcount/$this->results_per_page);
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-09-08 01:18:48 +00:00
|
|
|
if (!$all) {
|
|
|
|
if ($hitcount < $this->results_per_page) {
|
|
|
|
$this->pagenumber = 1;
|
|
|
|
} else if ($this->pagenumber > $totalpages) {
|
|
|
|
$this->pagenumber =$totalpages;
|
2006-09-20 21:00:45 +00:00
|
|
|
} //if
|
|
|
|
|
2006-09-08 01:18:48 +00:00
|
|
|
$start = ($this->pagenumber - 1) * $this->results_per_page;
|
|
|
|
$end = $start + $this->results_per_page;
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-09-08 01:18:48 +00:00
|
|
|
if ($end > $hitcount) {
|
|
|
|
$end = $hitcount;
|
2006-09-20 21:00:45 +00:00
|
|
|
} //if
|
2006-09-08 01:18:48 +00:00
|
|
|
} else {
|
|
|
|
$start = 0;
|
|
|
|
$end = $hitcount;
|
|
|
|
} //else
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-09-08 01:18:48 +00:00
|
|
|
$resultdoc = new SearchResult();
|
2006-09-20 21:00:45 +00:00
|
|
|
$resultdocs = array();
|
|
|
|
|
2006-09-08 01:18:48 +00:00
|
|
|
for ($i = $start; $i < $end; $i++) {
|
|
|
|
$hit = $hits[$i];
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
//check permissions on each result
|
2006-08-14 02:29:43 +00:00
|
|
|
if ($this->can_display($USER, $hit->id, $hit->doctype, $hit->course_id, $hit->group_id)) {
|
2006-07-25 17:10:58 +00:00
|
|
|
$resultdoc->number = $i;
|
|
|
|
$resultdoc->url = $hit->url;
|
|
|
|
$resultdoc->title = $hit->title;
|
|
|
|
$resultdoc->score = $hit->score;
|
|
|
|
$resultdoc->doctype = $hit->doctype;
|
|
|
|
$resultdoc->author = $hit->author;
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
//and store it
|
2006-09-20 21:00:45 +00:00
|
|
|
$resultdocs[] = clone($resultdoc);
|
2006-07-25 17:10:58 +00:00
|
|
|
} //if
|
|
|
|
} //foreach
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
return $resultdocs;
|
2006-09-08 01:18:48 +00:00
|
|
|
} //process_results
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
private function get_results() {
|
|
|
|
$cache = new SearchCache();
|
2006-09-20 21:00:45 +00:00
|
|
|
|
|
|
|
if ($this->cache and $cache->can_cache()) {
|
2006-07-25 17:10:58 +00:00
|
|
|
if (!($resultdocs = $cache->cache($this->term))) {
|
2006-09-08 01:18:48 +00:00
|
|
|
$resultdocs = $this->process_results();
|
2006-07-25 17:10:58 +00:00
|
|
|
//cache the results so we don't have to compute this on every page-load
|
2006-09-20 21:00:45 +00:00
|
|
|
$cache->cache($this->term, $resultdocs);
|
2006-07-25 17:10:58 +00:00
|
|
|
//print "Using new results.";
|
2006-09-20 21:00:45 +00:00
|
|
|
} else {
|
2006-07-25 17:10:58 +00:00
|
|
|
//There was something in the cache, so we're using that to save time
|
|
|
|
//print "Using cached results.";
|
2006-09-20 21:00:45 +00:00
|
|
|
} //else
|
2006-07-25 17:10:58 +00:00
|
|
|
} else {
|
|
|
|
//no caching :(
|
|
|
|
//print "Caching disabled!";
|
2006-09-08 01:18:48 +00:00
|
|
|
$resultdocs = $this->process_results();
|
2006-07-25 17:10:58 +00:00
|
|
|
} //else
|
|
|
|
|
|
|
|
return $resultdocs;
|
2006-09-20 21:00:45 +00:00
|
|
|
} //get_results
|
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
public function page_numbers() {
|
|
|
|
$pages = $this->total_pages();
|
2006-09-20 21:00:45 +00:00
|
|
|
$query = htmlentities($this->term);
|
2006-07-25 17:10:58 +00:00
|
|
|
$page = $this->pagenumber;
|
|
|
|
$next = "Next";
|
|
|
|
$back = "Back";
|
2006-09-20 21:00:45 +00:00
|
|
|
|
|
|
|
$ret = "<div align='center' id='search_page_links'>";
|
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
//Back is disabled if we're on page 1
|
|
|
|
if ($page > 1) {
|
|
|
|
$ret .= "<a href='query.php?query_string=$query&page=".($page-1)."'>< $back</a> ";
|
|
|
|
} else {
|
|
|
|
$ret .= "< $back ";
|
|
|
|
} //else
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
//don't <a href> the current page
|
|
|
|
for ($i = 1; $i <= $pages; $i++) {
|
|
|
|
if ($page == $i) {
|
|
|
|
$ret .= "[$i] ";
|
|
|
|
} else {
|
|
|
|
$ret .= "<a href='query.php?query_string=$query&page=$i'>$i</a> ";
|
|
|
|
} //else
|
|
|
|
} //for
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
//Next disabled if we're on the last page
|
2006-09-20 21:00:45 +00:00
|
|
|
if ($page < $pages) {
|
2006-07-25 17:10:58 +00:00
|
|
|
$ret .= "<a href='query.php?query_string=$query&page=".($page+1)."'>$next ></a> ";
|
|
|
|
} else {
|
|
|
|
$ret .= "$next > ";
|
|
|
|
} //else
|
2006-09-20 21:00:45 +00:00
|
|
|
|
|
|
|
$ret .= "</div>";
|
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
//shorten really long page lists, to stop table distorting width-ways
|
|
|
|
if (strlen($ret) > 70) {
|
|
|
|
$start = 4;
|
2006-09-20 21:00:45 +00:00
|
|
|
$end = $page - 5;
|
2006-07-25 17:10:58 +00:00
|
|
|
$ret = preg_replace("/<a\D+\d+\D+>$start<\/a>.*?<a\D+\d+\D+>$end<\/a>/", '...', $ret);
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
$start = $page + 5;
|
2006-09-20 21:00:45 +00:00
|
|
|
$end = $pages - 3;
|
2006-07-25 17:10:58 +00:00
|
|
|
$ret = preg_replace("/<a\D+\d+\D+>$start<\/a>.*?<a\D+\d+\D+>$end<\/a>/", '...', $ret);
|
|
|
|
} //if
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
return $ret;
|
2006-09-20 21:00:45 +00:00
|
|
|
} //page_numbers
|
2006-07-25 17:10:58 +00:00
|
|
|
|
2006-09-20 21:00:45 +00:00
|
|
|
//can the user see this result?
|
2006-08-14 02:29:43 +00:00
|
|
|
private function can_display(&$user, $this_id, $doctype, $course_id, $group_id) {
|
2006-07-25 17:10:58 +00:00
|
|
|
//this function should return true/false depending on
|
|
|
|
//whether or not a user can see this resource
|
|
|
|
//..
|
|
|
|
//if one of you nice moodlers see this, feel free to
|
2006-09-20 21:00:45 +00:00
|
|
|
//implement it for me .. :-P
|
2006-07-25 17:10:58 +00:00
|
|
|
return true;
|
|
|
|
} //can_display
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
public function count() {
|
2006-09-08 01:18:48 +00:00
|
|
|
return $this->total_results;
|
2006-07-25 17:10:58 +00:00
|
|
|
} //count
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
public function is_valid() {
|
|
|
|
return ($this->validquery and $this->validindex);
|
|
|
|
} //is_valid
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
public function is_valid_query() {
|
|
|
|
return $this->validquery;
|
|
|
|
} //is_valid_query
|
|
|
|
|
|
|
|
public function is_valid_index() {
|
|
|
|
return $this->validindex;
|
|
|
|
} //is_valid_index
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
public function total_pages() {
|
|
|
|
return ceil($this->count()/$this->results_per_page);
|
2006-09-20 21:00:45 +00:00
|
|
|
} //pages
|
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
public function get_pagenumber() {
|
|
|
|
return $this->pagenumber;
|
|
|
|
} //get_pagenumber
|
2006-09-20 21:00:45 +00:00
|
|
|
|
2006-07-25 17:10:58 +00:00
|
|
|
public function get_results_per_page() {
|
|
|
|
return $this->results_per_page;
|
2006-09-20 21:00:45 +00:00
|
|
|
} //get_results_per_page
|
2006-07-25 17:10:58 +00:00
|
|
|
} //SearchQuery
|
|
|
|
|
|
|
|
?>
|