1 <?php
2 
3 namespace dokuwiki\Action;
4 
5 use dokuwiki\Action\Exception\ActionAbort;
6 
7 /**
8  * Class Search
9  *
10  * Search for pages and content
11  *
12  * @package dokuwiki\Action
13  */
14 class Search extends AbstractAction
15 {
16     protected $pageLookupResults = [];
17     protected $fullTextResults = [];
18     protected $highlight = [];
19 
20     /** @inheritdoc */
21     public function minimumPermission()
22     {
23         return AUTH_NONE;
24     }
25 
26     /**
27      * we only search if a search word was given
28      *
29      * @inheritdoc
30      */
31     public function checkPreconditions()
32     {
33         parent::checkPreconditions();
34     }
35 
36     public function preProcess()
37     {
38         global $QUERY, $ID, $conf, $INPUT;
39         $s = cleanID($QUERY);
40 
41         if ($ID !== $conf['start'] && !$INPUT->has('q')) {
42             parse_str($INPUT->server->str('QUERY_STRING'), $urlParts);
43             $urlParts['q'] = $urlParts['id'];
44             unset($urlParts['id']);
45             $url = wl($ID, $urlParts, true, '&');
46             send_redirect($url);
47         }
48 
49         if ($s === '') throw new ActionAbort();
50         $this->adjustGlobalQuery();
51     }
52 
53     /** @inheritdoc */
54     public function tplContent()
55     {
56         $this->execute();
57 
58         $search = new \dokuwiki\Ui\Search($this->pageLookupResults, $this->fullTextResults, $this->highlight);
59         $search->show();
60     }
61 
62 
63     /**
64      * run the search
65      */
66     protected function execute()
67     {
68         global $INPUT, $QUERY;
69         $after = $INPUT->str('min');
70         $before = $INPUT->str('max');
71         $this->pageLookupResults = ft_pageLookup($QUERY, true, useHeading('navigation'), $after, $before);
72         $this->fullTextResults = ft_pageSearch($QUERY, $highlight, $INPUT->str('srt'), $after, $before);
73         $this->highlight = $highlight;
74     }
75 
76     /**
77      * Adjust the global query accordingly to the config search_nslimit and search_fragment
78      *
79      * This will only do something if the search didn't originate from the form on the searchpage itself
80      */
81     protected function adjustGlobalQuery()
82     {
83         global $conf, $INPUT, $QUERY, $ID;
84 
85         if ($INPUT->bool('sf')) {
86             return;
87         }
88 
89         $Indexer = idx_get_indexer();
90         $parsedQuery = ft_queryParser($Indexer, $QUERY);
91 
92         if (empty($parsedQuery['ns']) && empty($parsedQuery['notns'])) {
93             if ($conf['search_nslimit'] > 0) {
94                 if (getNS($ID) !== false) {
95                     $nsParts = explode(':', getNS($ID));
96                     $ns = implode(':', array_slice($nsParts, 0, $conf['search_nslimit']));
97                     $QUERY .= " @$ns";
98                 }
99             }
100         }
101 
102         if ($conf['search_fragment'] !== 'exact') {
103             if (empty(array_diff($parsedQuery['words'], $parsedQuery['and']))) {
104                 if (strpos($QUERY, '*') === false) {
105                     $queryParts = explode(' ', $QUERY);
106                     $queryParts = array_map(function ($part) {
107                         if (strpos($part, '@') === 0) {
108                             return $part;
109                         }
110                         if (strpos($part, 'ns:') === 0) {
111                             return $part;
112                         }
113                         if (strpos($part, '^') === 0) {
114                             return $part;
115                         }
116                         if (strpos($part, '-ns:') === 0) {
117                             return $part;
118                         }
119 
120                         global $conf;
121 
122                         if ($conf['search_fragment'] === 'starts_with') {
123                             return $part . '*';
124                         }
125                         if ($conf['search_fragment'] === 'ends_with') {
126                             return '*' . $part;
127                         }
128 
129                         return '*' . $part . '*';
130                     }, $queryParts);
131                     $QUERY = implode(' ', $queryParts);
132                 }
133             }
134         }
135     }
136 }
137