]> git.mjollnir.org Git - moodle.git/commitdiff
MDL-14981 regex search support in datalib, fixed course search
authorskodak <skodak>
Sun, 25 May 2008 20:43:46 +0000 (20:43 +0000)
committerskodak <skodak>
Sun, 25 May 2008 20:43:46 +0000 (20:43 +0000)
course/search.php
lib/datalib.php
lib/dml/moodle_database.php
lib/dml/mysqli_adodb_moodle_database.php
lib/dml/postgres7_adodb_moodle_database.php

index f169006ee6b58e71b7c074ddd2880f32cdffea42..d6645ab393fcbdf74f4502aa319c4c1ab4ebca44 100644 (file)
 
         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 .= "<br /><p class=\"category\">";
                 $course->summary .= "$strcategory: <a href=\"category.php?id=$course->category\">";
                 $course->summary .= $displaylist[$course->category];
                     $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)?
index edf224e7e39ad3d6e891685c33bb29baf9e67126..682110c55655d59e60dd2034b33379cd2ae357ec 100644 (file)
@@ -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
 
index 9df73d679cc4b6e93277e266c71eac99596d0152..6dcbcc2a4f223f8c3bf40e30c913e94b5af4e7be 100644 (file)
@@ -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
index 85cf8f8e9d0b2ebd3438d0f3f32590a27c4849ca..9b4280b5a7800524f8b7b32e6b559474a031ddd8 100644 (file)
@@ -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';
+    }
 }
index ccabab6d07c5de06c76a56ec2b955716e319c4de..7d190705ca1ae0dd587442fb51e608df22fc029e 100644 (file)
@@ -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 ? '~*' : '!~*';
+    }
 }