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