xref: /dokuwiki/inc/Action/Search.php (revision 90fb952c4c30c09c8446076ba05991c89a3f0b01)
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    {
24        return AUTH_NONE;
25    }
26
27    /**
28     * we only search if a search word was given
29     *
30     * @inheritdoc
31     */
32    public function checkPreconditions()
33    {
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        $this->pageLookupResults = ft_pageLookup($QUERY, true, useHeading('navigation'), $after, $before);
73        $this->fullTextResults = ft_pageSearch($QUERY, $highlight, $INPUT->str('srt'), $after, $before);
74        $this->highlight = $highlight;
75    }
76
77    /**
78     * Adjust the global query accordingly to the config search_nslimit and search_fragment
79     *
80     * This will only do something if the search didn't originate from the form on the searchpage itself
81     */
82    protected function adjustGlobalQuery()
83    {
84        global $conf, $INPUT, $QUERY, $ID;
85
86        if ($INPUT->bool('sf')) {
87            return;
88        }
89
90        $Indexer = idx_get_indexer();
91        $parsedQuery = ft_queryParser($Indexer, $QUERY);
92
93        if (empty($parsedQuery['ns']) && empty($parsedQuery['notns'])) {
94            if ($conf['search_nslimit'] > 0) {
95                if (getNS($ID) !== false) {
96                    $nsParts = explode(':', getNS($ID));
97                    $ns = implode(':', array_slice($nsParts, 0, $conf['search_nslimit']));
98                    $QUERY .= " @$ns";
99                }
100            }
101        }
102
103        if ($conf['search_fragment'] !== 'exact') {
104            if (empty(array_diff($parsedQuery['words'], $parsedQuery['and']))) {
105                if (strpos($QUERY, '*') === false) {
106                    $queryParts = explode(' ', $QUERY);
107                    $queryParts = array_map(function ($part) {
108                        if (strpos($part, '@') === 0) {
109                            return $part;
110                        }
111                        if (strpos($part, 'ns:') === 0) {
112                            return $part;
113                        }
114                        if (strpos($part, '^') === 0) {
115                            return $part;
116                        }
117                        if (strpos($part, '-ns:') === 0) {
118                            return $part;
119                        }
120
121                        global $conf;
122
123                        if ($conf['search_fragment'] === 'starts_with') {
124                            return $part . '*';
125                        }
126                        if ($conf['search_fragment'] === 'ends_with') {
127                            return '*' . $part;
128                        }
129
130                        return '*' . $part . '*';
131
132                    }, $queryParts);
133                    $QUERY = implode(' ', $queryParts);
134                }
135            }
136        }
137    }
138}
139