diff --git a/lang/en/forum.php b/lang/en/forum.php index d8d235ba317..63405afb029 100644 --- a/lang/en/forum.php +++ b/lang/en/forum.php @@ -138,6 +138,8 @@ $string['replyforum'] = 'Reply to forum'; $string['rsssubscriberssdiscussions'] = 'Display the RSS feed for \'$a\' discussions'; $string['rsssubscriberssposts'] = 'Display the RSS feed for \'$a\' posts'; $string['search'] = 'Search'; +$string['searchdatefrom'] = 'Posts must be newer than this'; +$string['searchdateto'] = 'Posts must be older than this'; $string['searchforumintro'] = 'Please enter search terms into one or more of the following fields:'; $string['searchforums'] = 'Search forums'; $string['searchfullwords'] = 'These words should appear as whole words'; diff --git a/lib/searchlib.php b/lib/searchlib.php index b793dceed71..0209951a317 100644 --- a/lib/searchlib.php +++ b/lib/searchlib.php @@ -10,6 +10,8 @@ define("TOKEN_EXACT","2"); define("TOKEN_NEGATE","3"); define("TOKEN_STRING","4"); define("TOKEN_USERID","5"); +define("TOKEN_DATEFROM","6"); +define("TOKEN_DATETO","7"); // Class to hold token/value pairs after they're parsed. @@ -51,9 +53,31 @@ class search_lexer extends Lexer{ //Set up the state machine and pattern matches for transitions. + // Patterns to handle strings of the form datefrom:foo + + // If we see the string datefrom: while in the base accept state, start + // parsing a username and go to the indatefrom state. + $this->addEntryPattern("datefrom:\S+","accept","indatefrom"); + + // Snarf everything into the username until we see whitespace, then exit + // back to the base accept state. + $this->addExitPattern("\s","indatefrom"); + + + // Patterns to handle strings of the form dateto:foo + + // If we see the string dateto: while in the base accept state, start + // parsing a username and go to the indateto state. + $this->addEntryPattern("dateto:\S+","accept","indateto"); + + // Snarf everything into the username until we see whitespace, then exit + // back to the base accept state. + $this->addExitPattern("\s","indateto"); + + // Patterns to handle strings of the form userid:foo - // If we see the string user: while in the base accept state, start + // If we see the string userid: while in the base accept state, start // parsing a username and go to the inuserid state. $this->addEntryPattern("userid:\S+","accept","inuserid"); @@ -151,6 +175,28 @@ class search_parser { return true; } + // State for handling datefrom:foo constructs. Potentially emits a token. + function indatefrom($content){ + if (strlen($content) < 10) { // State exit or missing parameter. + return true; + } + // Strip off the datefrom: part and add the reminder to the parsed token array + $param = trim(substr($content,9)); + $this->tokens[] = new search_token(TOKEN_DATEFROM,$param); + return true; + } + + // State for handling dateto:foo constructs. Potentially emits a token. + function indateto($content){ + if (strlen($content) < 8) { // State exit or missing parameter. + return true; + } + // Strip off the dateto: part and add the reminder to the parsed token array + $param = trim(substr($content,7)); + $this->tokens[] = new search_token(TOKEN_DATETO,$param); + return true; + } + // State for handling userid:foo constructs. Potentially emits a token. function inuserid($content){ if (strlen($content) < 8) { // State exit or missing parameter. @@ -241,7 +287,7 @@ class search_parser { // Other fields are database table names to search. function search_generate_SQL($parsetree, $datafield, $metafield, $mainidfield, $useridfield, - $userfirstnamefield, $userlastnamefield) { + $userfirstnamefield, $userlastnamefield, $timefield) { global $CFG; if ($CFG->dbtype == "postgres7") { @@ -289,6 +335,12 @@ function search_generate_SQL($parsetree, $datafield, $metafield, $mainidfield, $ case TOKEN_USERID: $SQLString .= "($useridfield = $value)"; break; + case TOKEN_DATETO: + $SQLString .= "($timefield <= $value)"; + break; + case TOKEN_DATEFROM: + $SQLString .= "($timefield >= $value)"; + break; case TOKEN_NEGATE: $SQLString .= "(NOT (($datafield $LIKE '%$value%') OR ($metafield $LIKE '%$value%')))"; break; diff --git a/mod/forum/lib.php b/mod/forum/lib.php index 9431e38c947..838e5978c2c 100644 --- a/mod/forum/lib.php +++ b/mod/forum/lib.php @@ -1035,7 +1035,7 @@ function forum_search_posts($searchterms, $courseid, $page=0, $recordsperpage=50 if ($lexer->parse($searchstring)) { $parsearray = $parser->get_parsed_array(); - $messagesearch = search_generate_SQL($parsearray,"p.message","p.subject","p.userid","u.id","u.firstname","u.lastname"); + $messagesearch = search_generate_SQL($parsearray,'p.message','p.subject','p.userid','u.id','u.firstname','u.lastname','p.modified'); } $selectsql = "{$CFG->prefix}forum_posts p, diff --git a/mod/forum/search.php b/mod/forum/search.php index e2f4cd0bb79..fe96c822aa2 100644 --- a/mod/forum/search.php +++ b/mod/forum/search.php @@ -16,6 +16,29 @@ $fullwords = trim(optional_param('fullwords', '', PARAM_NOTAGS)); // Whole words $notwords = trim(optional_param('notwords', '', PARAM_NOTAGS)); // Words we don't want + $fromday = optional_param('fromday', 0, PARAM_INT); // Starting date + $frommonth = optional_param('frommonth', 0, PARAM_INT); // Starting date + $fromyear = optional_param('fromyear', 0, PARAM_INT); // Starting date + $fromhour = optional_param('fromhour', 0, PARAM_INT); // Starting date + $fromminute = optional_param('fromminute', 0, PARAM_INT); // Starting date + if ($fromday) { + $datefrom = make_timestamp($fromyear, $frommonth, $fromday, $fromhour, $fromminute); + } else { + $datefrom = optional_param('datefrom', 0, PARAM_INT); // Starting date + } + + $today = optional_param('today', 0, PARAM_INT); // Ending date + $tomonth = optional_param('tomonth', 0, PARAM_INT); // Ending date + $toyear = optional_param('toyear', 0, PARAM_INT); // Ending date + $tohour = optional_param('tohour', 0, PARAM_INT); // Ending date + $tominute = optional_param('tominute', 0, PARAM_INT); // Ending date + if ($today) { + $dateto = make_timestamp($toyear, $tomonth, $today, $tohour, $tominute); + } else { + $dateto = optional_param('datefrom', 0, PARAM_INT); // Ending date + } + + if (empty($search)) { // Check the other parameters instead if (!empty($words)) { @@ -39,6 +62,12 @@ if (!empty($phrase)) { $search .= ' "'.$phrase.'"'; } + if (!empty($datefrom)) { + $search .= ' datefrom:'.$datefrom; + } + if (!empty($dateto)) { + $search .= ' dateto:'.$dateto; + } $individualparams = true; } else { $individualparams = false; @@ -82,6 +111,7 @@ } else { $groupid = 0; } + if (!$posts = forum_search_posts($searchterms, $course->id, $page*$perpage, $perpage, $totalcount, $groupid)) { print_header_simple("$strsearchresults", "", @@ -181,7 +211,7 @@ function forum_print_big_search_form($course) { - global $words, $subject, $phrase, $user, $userid, $fullwords, $notwords; + global $words, $subject, $phrase, $user, $userid, $fullwords, $notwords, $datefrom, $dateto; print_simple_box(get_string('searchforumintro', 'forum'), 'center', '', '', 'searchbox', 'intro'); @@ -196,8 +226,8 @@ function forum_print_big_search_form($course) { echo ''; echo '