support query splitting and quoting and search content and tags
authorChristian Weiske <cweiske@cweiske.de>
Fri, 24 Oct 2014 15:23:55 +0000 (17:23 +0200)
committerChristian Weiske <cweiske@cweiske.de>
Fri, 24 Oct 2014 15:23:55 +0000 (17:23 +0200)
lib/notestorage.php
lib/search/provider.php

index 951bf06e23647a00aa6adb296ad5ec606cc2577b..67baa202e3293e5486746ad81f3e3799f4b2e20c 100644 (file)
@@ -274,17 +274,27 @@ class NoteStorage
     /**
      * Search for a note
      *
-     * @param string $query Query string
+     * @param string $keywords AND-concatenated query strings
      *
      * @return array Database rows with note_guid and note_title
      */
-    public function search($query)
+    public function search($keywords)
     {
+        $sqlWhere = ' AND (note_title LIKE ? OR note_tags LIKE ? OR note_content LIKE ?)';
+        $arData = array(
+            $this->username
+        );
+        foreach ($keywords as $keyword) {
+            $arData[] = '%' . $keyword . '%';//title
+            $arData[] = '%' . $keyword . '%';//tags
+            $arData[] = '%' . $keyword . '%';//content
+        }
         $result = \OC_DB::executeAudited(
             'SELECT `note_guid`, `note_title`'
             . ' FROM `*PREFIX*grauphel_notes`'
-            . ' WHERE note_user = ? AND note_title LIKE ?',
-            array($this->username, '%' . $query . '%')
+            . ' WHERE note_user = ?'
+            . str_repeat($sqlWhere, count($keywords)),
+            $arData
         );
 
         $notes = array();
index 5b42bb70f9c6c6ce1e0b5864c7cf59d04cd999a6..8b867bb91bb5e7f2a41c6f2ea2a30ea46d4a09c0 100644 (file)
@@ -40,13 +40,13 @@ class Provider extends \OCP\Search\Provider
         $urlGen = \OC::$server->getURLGenerator();
         $notes  = new NoteStorage($urlGen);
         $notes->setUsername(\OC_User::getUser());
-        $rows = $notes->search($query);
+        $rows = $notes->search($this->parseQuery($query));
 
         $results = array();
         foreach ($rows as $row) {
             $res = new Note();
             $res->id   = $row['note_guid'];
-            $res->name = $row['note_title'];
+            $res->name = htmlspecialchars_decode($row['note_title']);
             $res->link = $urlGen->linkToRoute(
                 'grauphel.gui.note', array('guid' => $row['note_guid'])
             );
@@ -54,5 +54,48 @@ class Provider extends \OCP\Search\Provider
         }
         return $results;
     }
+
+    /**
+     * Splits the user's query string up into several keywords
+     * that all have to be within the note (AND).
+     *
+     * Split by space, quotes are supported:
+     * - foo bar
+     *   -> searches for notes that contain "foo" and "bar"
+     * - foo "bar baz"
+     *   -> searches for notes that contain "foo" and "bar baz"
+     *
+     * @param string $query User-given query string
+     *
+     * @return array Array of keywords
+     */
+    protected function parseQuery($query)
+    {
+        $keywords = explode(' ', $query);
+        array_map('trim', $keywords);
+        $loop = 0;
+        do {
+            $changed = false;
+            foreach ($keywords as $key => &$keyword) {
+                if ($keyword{0} != '"') {
+                    continue;
+                }
+                if (substr($keyword, -1) == '"') {
+                    // "foo"
+                    $keyword = trim($keyword, '"');
+                    continue;
+                }
+                if ($key < count($keywords) -1) {
+                    //not at the end
+                    $keyword .= ' ' . $keywords[$key + 1];
+                    unset($keywords[$key + 1]);
+                    $changed = true;
+                    break;
+                }
+            }
+        } while ($changed && ++$loop < 20);
+
+        return $keywords;
+    }
 }
 ?>