xref: /dokuwiki/inc/Action/Search.php (revision 0cba610bea94e5841d211c0d3f57ae96e8ad1379)
164ab5140SAndreas Gohr<?php
264ab5140SAndreas Gohr
364ab5140SAndreas Gohrnamespace dokuwiki\Action;
464ab5140SAndreas Gohr
564ab5140SAndreas Gohruse dokuwiki\Action\Exception\ActionAbort;
6*0cba610bSSatoshi Saharause dokuwiki\Search\FulltextSearch;
7*0cba610bSSatoshi Saharause dokuwiki\Search\MetadataSearch;
8*0cba610bSSatoshi Saharause dokuwiki\Search\QueryParser;
964ab5140SAndreas Gohr
10ab583a1bSAndreas Gohr/**
11ab583a1bSAndreas Gohr * Class Search
12ab583a1bSAndreas Gohr *
13ab583a1bSAndreas Gohr * Search for pages and content
14ab583a1bSAndreas Gohr *
15ab583a1bSAndreas Gohr * @package dokuwiki\Action
16ab583a1bSAndreas Gohr */
1764ab5140SAndreas Gohrclass Search extends AbstractAction {
1864ab5140SAndreas Gohr
196639a152SMichael Große    protected $pageLookupResults = array();
206639a152SMichael Große    protected $fullTextResults = array();
216639a152SMichael Große    protected $highlight = array();
226639a152SMichael Große
2364ab5140SAndreas Gohr    /** @inheritdoc */
24ec701221SAndreas Gohr    public function minimumPermission() {
2564ab5140SAndreas Gohr        return AUTH_NONE;
2664ab5140SAndreas Gohr    }
2764ab5140SAndreas Gohr
2864ab5140SAndreas Gohr    /**
2964ab5140SAndreas Gohr     * we only search if a search word was given
3064ab5140SAndreas Gohr     *
3164ab5140SAndreas Gohr     * @inheritdoc
3264ab5140SAndreas Gohr     */
33b2c9cd19SAndreas Gohr    public function checkPreconditions() {
34b2c9cd19SAndreas Gohr        parent::checkPreconditions();
3564ab5140SAndreas Gohr    }
3664ab5140SAndreas Gohr
37d09b5b64SMichael Große    public function preProcess()
38d09b5b64SMichael Große    {
39d22b78c8SMichael Große        global $QUERY, $ID, $conf, $INPUT;
40d22b78c8SMichael Große        $s = cleanID($QUERY);
41d22b78c8SMichael Große
423286c65dSMichael Große        if ($ID !== $conf['start'] && !$INPUT->has('q')) {
43d22b78c8SMichael Große            parse_str($INPUT->server->str('QUERY_STRING'), $urlParts);
44d22b78c8SMichael Große            $urlParts['q'] = $urlParts['id'];
45918638dcSSchplurtz le Déboulonné            unset($urlParts['id']);
46cc21cb50SAndreas Gohr            $url = wl($ID, $urlParts, true, '&');
47d22b78c8SMichael Große            send_redirect($url);
48d22b78c8SMichael Große        }
49d22b78c8SMichael Große
50d22b78c8SMichael Große        if ($s === '') throw new ActionAbort();
51d09b5b64SMichael Große        $this->adjustGlobalQuery();
52d09b5b64SMichael Große    }
53d09b5b64SMichael Große
5464ab5140SAndreas Gohr    /** @inheritdoc */
55d09b5b64SMichael Große    public function tplContent()
56d09b5b64SMichael Große    {
576639a152SMichael Große        $this->execute();
586639a152SMichael Große
596639a152SMichael Große        $search = new \dokuwiki\Ui\Search($this->pageLookupResults, $this->fullTextResults, $this->highlight);
6021fcef82SMichael Große        $search->show();
6164ab5140SAndreas Gohr    }
62d09b5b64SMichael Große
636639a152SMichael Große
646639a152SMichael Große    /**
656639a152SMichael Große     * run the search
666639a152SMichael Große     */
676639a152SMichael Große    protected function execute()
686639a152SMichael Große    {
696639a152SMichael Große        global $INPUT, $QUERY;
70422bbbc6SMichael Große        $after = $INPUT->str('min');
71422bbbc6SMichael Große        $before = $INPUT->str('max');
72*0cba610bSSatoshi Sahara        $this->pageLookupResults = MetadataSearch::pageLookup($QUERY, true, useHeading('navigation'), $after, $before);
73*0cba610bSSatoshi Sahara        $this->fullTextResults = FulltextSearch::pageSearch($QUERY, $highlight, $INPUT->str('srt'), $after, $before);
746639a152SMichael Große        $this->highlight = $highlight;
756639a152SMichael Große    }
766639a152SMichael Große
77d09b5b64SMichael Große    /**
7813ce475dSAndreas Gohr     * Adjust the global query accordingly to the config search_nslimit and search_fragment
79d09b5b64SMichael Große     *
80d09b5b64SMichael Große     * This will only do something if the search didn't originate from the form on the searchpage itself
81d09b5b64SMichael Große     */
82d09b5b64SMichael Große    protected function adjustGlobalQuery()
83d09b5b64SMichael Große    {
84340f849aSMichael Große        global $conf, $INPUT, $QUERY, $ID;
85d09b5b64SMichael Große
861265b193SMichael Große        if ($INPUT->bool('sf')) {
87d09b5b64SMichael Große            return;
88d09b5b64SMichael Große        }
89d09b5b64SMichael Große
90*0cba610bSSatoshi Sahara        $parsedQuery = QueryParser::convert($QUERY);
91d09b5b64SMichael Große
92d09b5b64SMichael Große        if (empty($parsedQuery['ns']) && empty($parsedQuery['notns'])) {
9313ce475dSAndreas Gohr            if ($conf['search_nslimit'] > 0) {
94340f849aSMichael Große                if (getNS($ID) !== false) {
95340f849aSMichael Große                    $nsParts = explode(':', getNS($ID));
9613ce475dSAndreas Gohr                    $ns = implode(':', array_slice($nsParts, 0, $conf['search_nslimit']));
97d09b5b64SMichael Große                    $QUERY .= " @$ns";
98d09b5b64SMichael Große                }
99d09b5b64SMichael Große            }
100d09b5b64SMichael Große        }
101d09b5b64SMichael Große
10213ce475dSAndreas Gohr        if ($conf['search_fragment'] !== 'exact') {
103d09b5b64SMichael Große            if (empty(array_diff($parsedQuery['words'], $parsedQuery['and']))) {
104d09b5b64SMichael Große                if (strpos($QUERY, '*') === false) {
105d09b5b64SMichael Große                    $queryParts = explode(' ', $QUERY);
106d09b5b64SMichael Große                    $queryParts = array_map(function ($part) {
107d09b5b64SMichael Große                        if (strpos($part, '@') === 0) {
108d09b5b64SMichael Große                            return $part;
109d09b5b64SMichael Große                        }
110d09b5b64SMichael Große                        if (strpos($part, 'ns:') === 0) {
111d09b5b64SMichael Große                            return $part;
112d09b5b64SMichael Große                        }
113d09b5b64SMichael Große                        if (strpos($part, '^') === 0) {
114d09b5b64SMichael Große                            return $part;
115d09b5b64SMichael Große                        }
116d09b5b64SMichael Große                        if (strpos($part, '-ns:') === 0) {
117d09b5b64SMichael Große                            return $part;
118d09b5b64SMichael Große                        }
119d09b5b64SMichael Große
120d09b5b64SMichael Große                        global $conf;
121d09b5b64SMichael Große
12213ce475dSAndreas Gohr                        if ($conf['search_fragment'] === 'starts_with') {
123d09b5b64SMichael Große                            return $part . '*';
124d09b5b64SMichael Große                        }
12513ce475dSAndreas Gohr                        if ($conf['search_fragment'] === 'ends_with') {
126d09b5b64SMichael Große                            return '*' . $part;
127d09b5b64SMichael Große                        }
128d09b5b64SMichael Große
129d09b5b64SMichael Große                        return '*' . $part . '*';
130d09b5b64SMichael Große
131d09b5b64SMichael Große                    }, $queryParts);
132d09b5b64SMichael Große                    $QUERY = implode(' ', $queryParts);
133d09b5b64SMichael Große                }
134d09b5b64SMichael Große            }
135d09b5b64SMichael Große        }
136d09b5b64SMichael Große    }
13764ab5140SAndreas Gohr}
138