From: skodak Date: Sun, 25 May 2008 20:43:46 +0000 (+0000) Subject: MDL-14981 regex search support in datalib, fixed course search X-Git-Url: http://git.mjollnir.org/gw?a=commitdiff_plain;h=06c1a1daf4233cfdcf5af187f3538783d2e6264f;p=moodle.git MDL-14981 regex search support in datalib, fixed course search --- diff --git a/course/search.php b/course/search.php index f169006ee6..d6645ab393 100644 --- a/course/search.php +++ b/course/search.php @@ -200,8 +200,8 @@ if (!has_capability('moodle/site:config', get_context_instance(CONTEXT_SYSTEM))) { foreach ($courses as $course) { - $course->fullname = highlight("$search", $course->fullname); - $course->summary = highlight("$search", $course->summary); + $course->fullname = highlight(trim($search, '+'), $course->fullname); + $course->summary = highlight(trim($search, '+'), $course->summary); $course->summary .= "

"; $course->summary .= "$strcategory: category\">"; $course->summary .= $displaylist[$course->category]; @@ -230,7 +230,7 @@ $coursecontext = get_context_instance(CONTEXT_COURSE, $course->id); } - $course->fullname = highlight("$search", $course->fullname); + $course->fullname = highlight(trim($search, '+'), $course->fullname); $linkcss = $course->visible ? "" : " class=\"dimmed\" "; // are we displaying the front page (courseid=1)? diff --git a/lib/datalib.php b/lib/datalib.php index edf224e7e3..682110c556 100644 --- a/lib/datalib.php +++ b/lib/datalib.php @@ -1021,74 +1021,68 @@ function get_my_courses($userid, $sort='visible DESC,sortorder ASC', $fields=NUL function get_courses_search($searchterms, $sort='fullname ASC', $page=0, $recordsperpage=50, &$totalcount) { global $CFG, $DB; - if ($CFG->dbfamily == 'postgres') { - $REGEXP = '~*'; - $NOTREGEXP = '!~*'; - } else { - $REGEXP = 'REGEXP'; - $NOTREGEXP = 'NOT REGEXP'; + if ($DB->sql_regex_supported()) { + $REGEXP = $DB->sql_regex(true); + $NOTREGEXP = $DB->sql_regex(false); } $LIKE = $DB->sql_ilike(); // case-insensitive - $fullnamesearch = ''; - $summarysearch = ''; + $searchcond = array(); + $params = array(); + $i = 0; - $params = array(); + $concat = $DB->sql_concat('c.summary', "' '", 'c.fullname'); foreach ($searchterms as $searchterm) { + $i++; $NOT = ''; /// Initially we aren't going to perform NOT LIKE searches, only MSSQL and Oracle /// will use it to simulate the "-" operator with LIKE clause /// Under Oracle and MSSQL, trim the + and - operators and perform /// simpler LIKE (or NOT LIKE) queries - if ($CFG->dbfamily == 'oracle' || $CFG->dbfamily == 'mssql') { + if (!$DB->sql_regex_supported()) { if (substr($searchterm, 0, 1) == '-') { $NOT = ' NOT '; } $searchterm = trim($searchterm, '+-'); } - if ($fullnamesearch) { - $fullnamesearch .= ' AND '; - } - if ($summarysearch) { - $summarysearch .= ' AND '; - } - - // TODO: the "-" here does not work much because it may be cancelled by OR condition "( $fullnamesearch ) OR ( $summarysearch )" + // TODO: +- may not work for non latin languages if (substr($searchterm,0,1) == '+') { - $searchterm = substr($searchterm,1); - $searchterm = preg_quote($searchterm, '|'); - $summarysearch .= " c.summary $REGEXP :ss "; - $params['ss'] = "(^|[^a-zA-Z0-9])$searchterm([^a-zA-Z0-9]|$)"; - $fullnamesearch .= " c.fullname $REGEXP :fs "; - $params['fs'] = "(^|[^a-zA-Z0-9])$searchterm([^a-zA-Z0-9]|$)"; + $searchterm = trim($searchterm, '+-'); + $searchterm = preg_quote($searchterm, '|'); + $searchcond[] = "$concat $REGEXP :ss$i"; + $params['ss'.$i] = "(^|[^a-zA-Z0-9])$searchterm([^a-zA-Z0-9]|$)"; + } else if (substr($searchterm,0,1) == "-") { - $searchterm = substr($searchterm,1); - $searchterm = preg_quote($searchterm, '|'); - $summarysearch .= " c.summary $NOTREGEXP :ss "; - $params['ss'] = "(^|[^a-zA-Z0-9])$searchterm([^a-zA-Z0-9]|$)"; - $fullnamesearch .= " c.fullname $NOTREGEXP :fs "; - $params['fs'] = "(^|[^a-zA-Z0-9])$searchterm([^a-zA-Z0-9]|$)"; + $searchterm = trim($searchterm, '+-'); + $searchterm = preg_quote($searchterm, '|'); + $searchcond[] = "$concat $NOTREGEXP :ss$i"; + $params['ss'.$i] = "(^|[^a-zA-Z0-9])$searchterm([^a-zA-Z0-9]|$)"; + } else { - $summarysearch .= " summary $NOT $LIKE :ss "; - $fullnamesearch .= " fullname $NOT $LIKE :fs "; - $params['ss'] = "%$searchterm%"; - $params['fs'] = "%$searchterm%"; + $searchcond[] = "$concat $NOT $LIKE :ss$i"; + $params['ss'.$i] = "%$searchterm%"; } } + if (empty($searchcond)) { + $totalcount = 0; + return array(); + } + + $searchcond = implode(" AND ", $searchcond); + $sql = "SELECT c.*, ctx.id AS ctxid, ctx.path AS ctxpath, ctx.depth AS ctxdepth, ctx.contextlevel AS ctxlevel FROM {course} c JOIN {context} ctx ON (c.id = ctx.instanceid AND ctx.contextlevel=".CONTEXT_COURSE.") - WHERE (( $fullnamesearch ) OR ( $summarysearch )) - AND category > 0 - ORDER BY $sort"; + WHERE $searchcond AND c.id <> ".SITEID." + ORDER BY $sort"; $courses = array(); $c = 0; // counts how many visible courses we've seen diff --git a/lib/dml/moodle_database.php b/lib/dml/moodle_database.php index 9df73d679c..6dcbcc2a4f 100644 --- a/lib/dml/moodle_database.php +++ b/lib/dml/moodle_database.php @@ -1281,6 +1281,22 @@ abstract class moodle_database { return ' ( NOT ' . $this->sql_isempty($tablename, $fieldname, $nullablefield, $textfield) . ') '; } + /** + * Does this driver suppoer regex syntax when searching + */ + public function sql_regex_supported() { + return false; + } + + /** + * Return regex positive or negative match sql + * @param bool $positivematch + * @return string or empty if not supported + */ + public function sql_regex($positivematch=true) { + return ''; + } + /// transactions /** * on DBs that support it, switch to transaction mode and begin a transaction diff --git a/lib/dml/mysqli_adodb_moodle_database.php b/lib/dml/mysqli_adodb_moodle_database.php index 85cf8f8e9d..9b4280b5a7 100644 --- a/lib/dml/mysqli_adodb_moodle_database.php +++ b/lib/dml/mysqli_adodb_moodle_database.php @@ -221,4 +221,19 @@ class mysqli_adodb_moodle_database extends adodb_moodle_database { return ' CAST(' . $fieldname . ' AS SIGNED) '; } + /** + * Does this driver suppoer regex syntax when searching + */ + public function sql_regex_supported() { + return true; + } + + /** + * Return regex positive or negative match sql + * @param bool $positivematch + * @return string or empty if not supported + */ + public function sql_regex($positivematch=true) { + return $positivematch ? 'REGEXP' : 'NOT REGEXP'; + } } diff --git a/lib/dml/postgres7_adodb_moodle_database.php b/lib/dml/postgres7_adodb_moodle_database.php index ccabab6d07..7d190705ca 100644 --- a/lib/dml/postgres7_adodb_moodle_database.php +++ b/lib/dml/postgres7_adodb_moodle_database.php @@ -424,4 +424,20 @@ class postgres7_adodb_moodle_database extends adodb_moodle_database { public function sql_cast_char2int($fieldname, $text=false) { return ' CAST(' . $fieldname . ' AS INT) '; } + + /** + * Does this driver suppoer regex syntax when searching + */ + public function sql_regex_supported() { + return true; + } + + /** + * Return regex positive or negative match sql + * @param bool $positivematch + * @return string or empty if not supported + */ + public function sql_regex($positivematch=true) { + return $positivematch ? '~*' : '!~*'; + } }