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