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