From 4d0cb6e1cdd7281b9ab09540927bc3c447fcff17 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20Gro=C3=9Fe?= <grosse@cosmocode.de>
Date: Thu, 22 Mar 2018 15:48:14 +0100
Subject: [PATCH] feat(search): show search adjustments as links

This simplifies many aspects. However, it still needs much better
styling.
---
 inc/Ui/Search.php     | 134 +++++++++++++++++++++++++-----------------
 lib/scripts/search.js |  53 +----------------
 2 files changed, 82 insertions(+), 105 deletions(-)

diff --git a/inc/Ui/Search.php b/inc/Ui/Search.php
index 0fab58db4..4f3b57683 100644
--- a/inc/Ui/Search.php
+++ b/inc/Ui/Search.php
@@ -131,33 +131,6 @@ class Search extends Ui
      */
     protected function addSearchAssistanceElements(Form $searchForm, array $parsedQuery)
     {
-        $matchType = '';
-        $searchTerm = null;
-        if (count($parsedQuery['words']) === 1) {
-            $searchTerm = $parsedQuery['words'][0];
-            $firstChar = $searchTerm[0];
-            $lastChar = substr($searchTerm, -1);
-            $matchType = 'exact';
-
-            if ($firstChar === '*') {
-                $matchType = 'starts';
-            }
-            if ($lastChar === '*') {
-                $matchType = 'ends';
-            }
-            if ($firstChar === '*' && $lastChar === '*') {
-                $matchType = 'contains';
-            }
-            $searchTerm = trim($searchTerm, '*');
-        }
-
-        $searchForm->addTextInput(
-            'searchTerm',
-            '',
-            $searchForm->findPositionByAttribute('type', 'submit')
-        )
-            ->val($searchTerm)
-            ->attr('style', 'display: none;');
         $searchForm->addButton('toggleAssistant', 'toggle search assistant')
             ->attr('type', 'button')
             ->id('search-results-form__show-assistance-button')
@@ -167,22 +140,70 @@ class Search extends Ui
             ->addClass('js-advancedSearchOptions')
             ->attr('style', 'display: none;');
 
-        $searchForm->addTagOpen('div')->addClass('search-results-form__subwrapper');
-        $searchForm->addRadioButton('matchType', 'exact Match FM')->val('exact')->attr('checked',
-            $matchType === 'exact' ?: null);
-        $searchForm->addRadioButton('matchType', 'starts with FM')->val('starts')->attr('checked',
-            $matchType === 'starts' ?: null);
-        $searchForm->addRadioButton('matchType', 'ends with FM')->val('ends')->attr('checked',
-            $matchType === 'ends' ?: null);
-        $searchForm->addRadioButton('matchType', 'contains FM')->val('contains')->attr('checked',
-            $matchType === 'contains' ?: null);
+        $this->addFragmentBehaviorLinks($searchForm, $parsedQuery);
+        $this->addNamespaceSelector($searchForm, $parsedQuery);
+
         $searchForm->addTagClose('div');
+    }
 
-        $this->addNamespaceSelector($searchForm, $parsedQuery);
+    protected function addFragmentBehaviorLinks(Form $searchForm, array $parsedQuery)
+    {
+        $searchForm->addTagOpen('div')->addClass('search-results-form__subwrapper');
+
+        $this->addSearchLink(
+            $searchForm,
+            'exact Match',
+            array_map(function($term){return trim($term, '*');},$this->parsedQuery['and']),
+            $this->parsedQuery['ns']
+        );
+
+        $searchForm->addHTML(' ');
+
+        $this->addSearchLink(
+            $searchForm,
+            'starts with',
+            array_map(function($term){return trim($term, '*') . '*';},$this->parsedQuery['and']),
+            $this->parsedQuery['ns']
+        );
+
+        $searchForm->addHTML(' ');
+
+        $this->addSearchLink(
+            $searchForm,
+            'ends with',
+            array_map(function($term){return '*' . trim($term, '*');},$this->parsedQuery['and']),
+            $this->parsedQuery['ns']
+        );
+
+        $searchForm->addHTML(' ');
+
+        $this->addSearchLink(
+            $searchForm,
+            'contains',
+            array_map(function($term){return '*' . trim($term, '*') . '*';},$this->parsedQuery['and']),
+            $this->parsedQuery['ns']
+        );
 
         $searchForm->addTagClose('div');
     }
 
+    protected function addSearchLink(Form $searchForm, $label, $and, $ns) {
+        $newQuery = ft_queryUnparser_simple(
+            $and,
+            [],
+            [],
+            $ns,
+            []
+        );
+        $searchForm->addTagOpen('a')
+            ->attrs([
+                'href' => wl($newQuery, ['do' => 'search', 'searchPageForm' => '1'], false, '&')
+            ])
+        ;
+        $searchForm->addHTML($label);
+        $searchForm->addTagClose('a');
+    }
+
     /**
      * Add the elements for the namespace selector
      *
@@ -192,26 +213,33 @@ class Search extends Ui
     protected function addNamespaceSelector(Form $searchForm, array $parsedQuery)
     {
         $baseNS = empty($parsedQuery['ns']) ? '' : $parsedQuery['ns'][0];
-        $namespaces = [];
         $searchForm->addTagOpen('div')->addClass('search-results-form__subwrapper');
+
         if ($baseNS) {
-            $searchForm->addRadioButton('namespace', '(no namespace FIXME)')->val('');
-            $parts = [$baseNS => count($this->fullTextResults)];
-            $upperNameSpace = $baseNS;
-            while ($upperNameSpace = getNS($upperNameSpace)) {
-                $parts[$upperNameSpace] = 0;
-            }
-            $namespaces = array_reverse($parts);
-        };
+            $searchForm->addTagOpen('div');
+
+            $this->addSearchLink(
+                $searchForm,
+                'remove current namespace restriction',
+                $this->parsedQuery['and'],
+                []
+            );
+
+            $searchForm->addTagClose('div');
+        }
+
+        $extraNS = $this->getAdditionalNamespacesFromResults($baseNS);
+        if (!empty($extraNS)) {
+            $searchForm->addTagOpen('div');
+            $searchForm->addHTML('first level ns below current: ');
 
-        $namespaces = array_merge($namespaces, $this->getAdditionalNamespacesFromResults($baseNS));
+            foreach ($extraNS as $extraNS => $count) {
+                $searchForm->addHTML(' ');
+                $label = $extraNS . ($count ? " ($count)" : '');
 
-        foreach ($namespaces as $extraNS => $count) {
-            $label = $extraNS . ($count ? " ($count)" : '');
-            $namespaceCB = $searchForm->addRadioButton('namespace', $label)->val($extraNS);
-            if ($extraNS === $baseNS) {
-                $namespaceCB->attr('checked', true);
+                $this->addSearchLink($searchForm, $label, $this->parsedQuery['and'], [$extraNS]);
             }
+            $searchForm->addTagClose('div');
         }
 
         $searchForm->addTagClose('div');
@@ -385,7 +413,7 @@ class Search extends Ui
             [$ns],
             []
         );
-        $href = wl($newQuery, ['do' => 'search']);
+        $href = wl($newQuery, ['do' => 'search', 'searchPageForm' => '1']);
         $attributes = buildAttributes([
             'rel' => 'nofollow',
             'class' => 'search_namespace_link',
diff --git a/lib/scripts/search.js b/lib/scripts/search.js
index 0c9dca76a..cf7399b5d 100644
--- a/lib/scripts/search.js
+++ b/lib/scripts/search.js
@@ -9,59 +9,8 @@ jQuery(function () {
         return;
     }
     const $toggleAssistanceButton = $searchForm.find('#search-results-form__show-assistance-button');
-    const $queryInput = $searchForm.find('[name="id"]');
-    const $termInput = $searchForm.find('[name="searchTerm"]');
 
     $toggleAssistanceButton.on('click', function () {
-        jQuery('.js-advancedSearchOptions').toggle();
-        $queryInput.toggle();
-        $termInput.toggle();
+        jQuery('.js-advancedSearchOptions').dw_toggle();
     });
-
-
-    const $matchTypeSwitcher = $searchForm.find('[name="matchType"]');
-    const $namespaceSwitcher = $searchForm.find('[name="namespace"]');
-    const $refiningElements = $termInput.add($matchTypeSwitcher).add($namespaceSwitcher);
-    $refiningElements.on('input change', function () {
-        $queryInput.val(
-            rebuildQuery(
-                $termInput.val(),
-                $matchTypeSwitcher.filter(':checked').val(),
-                $namespaceSwitcher.filter(':checked').val()
-            )
-        );
-    });
-
-    /**
-     * Rebuild the search query from the parts
-     *
-     * @param {string} searchTerm the word which is to be searched
-     * @param {enum} matchType the type of matching that is to be done
-     * @param {string} namespace list of namespaces to which to limit the search
-     *
-     * @return {string} the query string for the actual search
-     */
-    function rebuildQuery(searchTerm, matchType, namespace) {
-        let query = '';
-
-        switch (matchType) {
-        case 'contains':
-            query = '*' + searchTerm + '*';
-            break;
-        case 'starts':
-            query = '*' + searchTerm;
-            break;
-        case 'ends':
-            query = searchTerm + '*';
-            break;
-        default:
-            query = searchTerm;
-        }
-
-        if (namespace && namespace.length) {
-            query += ' @' + namespace;
-        }
-
-        return query;
-    }
 });
-- 
GitLab