xref: /dokuwiki/inc/Action/Search.php (revision d22b78c8b597b55c8f2e9859f7d626efcef322ce)
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    /** @inheritdoc */
17    public function minimumPermission() {
18        return AUTH_NONE;
19    }
20
21    /**
22     * we only search if a search word was given
23     *
24     * @inheritdoc
25     */
26    public function checkPermissions() {
27        parent::checkPermissions();
28    }
29
30    public function preProcess()
31    {
32        global $QUERY, $ID, $conf, $INPUT;
33        $s = cleanID($QUERY);
34
35        if ($ID !== $conf['start'] && $s === '') {
36            parse_str($INPUT->server->str('QUERY_STRING'), $urlParts);
37            $urlParts['q'] = $urlParts['id'];
38            $urlParts['id'] = $conf['start'];
39            $url = DOKU_URL . DOKU_SCRIPT . '?' . http_build_query($urlParts, null, '&');
40            send_redirect($url);
41        }
42
43        if ($s === '') throw new ActionAbort();
44        $this->adjustGlobalQuery();
45    }
46
47    /** @inheritdoc */
48    public function tplContent()
49    {
50        $search = new \dokuwiki\Ui\Search();
51        $search->execute();
52        $search->show();
53    }
54
55    /**
56     * Adjust the global query accordingly to the config search_limit_to_first_ns and search_default_fragment_behaviour
57     *
58     * This will only do something if the search didn't originate from the form on the searchpage itself
59     */
60    protected function adjustGlobalQuery()
61    {
62        global $conf, $INPUT, $QUERY;
63
64        if ($INPUT->bool('searchPageForm')) {
65            return;
66        }
67
68        $Indexer = idx_get_indexer();
69        $parsedQuery = ft_queryParser($Indexer, $QUERY);
70
71        if (empty($parsedQuery['ns']) && empty($parsedQuery['notns'])) {
72            if ($conf['search_limit_to_first_ns'] > 0) {
73                $searchOriginPage = $INPUT->str('from');
74                if (getNS($searchOriginPage) !== false) {
75                    $nsParts = explode(':', getNS($searchOriginPage));
76                    $ns = implode(':', array_slice($nsParts, 0, $conf['search_limit_to_first_ns']));
77                    $QUERY .= " @$ns";
78                }
79            }
80        }
81
82        if ($conf['search_default_fragment_behaviour'] !== 'exact') {
83            if (empty(array_diff($parsedQuery['words'], $parsedQuery['and']))) {
84                if (strpos($QUERY, '*') === false) {
85                    $queryParts = explode(' ', $QUERY);
86                    $queryParts = array_map(function ($part) {
87                        if (strpos($part, '@') === 0) {
88                            return $part;
89                        }
90                        if (strpos($part, 'ns:') === 0) {
91                            return $part;
92                        }
93                        if (strpos($part, '^') === 0) {
94                            return $part;
95                        }
96                        if (strpos($part, '-ns:') === 0) {
97                            return $part;
98                        }
99
100                        global $conf;
101
102                        if ($conf['search_default_fragment_behaviour'] === 'starts_with') {
103                            return $part . '*';
104                        }
105                        if ($conf['search_default_fragment_behaviour'] === 'ends_with') {
106                            return '*' . $part;
107                        }
108
109                        return '*' . $part . '*';
110
111                    }, $queryParts);
112                    $QUERY = implode(' ', $queryParts);
113                }
114            }
115        }
116    }
117}
118