xref: /dokuwiki/inc/Ui/Search.php (revision 427ed988282f72cb160d09b0830f843d462cc93a)
1<?php
2
3namespace dokuwiki\Ui;
4
5use \dokuwiki\Form\Form;
6
7class Search extends Ui
8{
9    protected $query;
10    protected $pageLookupResults = array();
11    protected $fullTextResults = array();
12    protected $highlight = array();
13
14    /**
15     * Search constructor.
16     *
17     * @param string $query the search query
18     */
19    public function __construct($query)
20    {
21        $this->query = $query;
22    }
23
24    /**
25     * run the search
26     */
27    public function execute()
28    {
29        $this->pageLookupResults = ft_pageLookup($this->query, true, useHeading('navigation'));
30        $this->fullTextResults = ft_pageSearch($this->query, $highlight);
31        $this->highlight = $highlight;
32    }
33
34    /**
35     * display the search result
36     *
37     * @return void
38     */
39    public function show()
40    {
41        $searchHTML = '';
42
43        $searchHTML .= $this->getSearchFormHTML($this->query);
44
45        $searchHTML .= $this->getSearchIntroHTML($this->query);
46
47        $searchHTML .= $this->getPageLookupHTML($this->pageLookupResults);
48
49        $searchHTML .= $this->getFulltextResultsHTML($this->fullTextResults, $this->highlight);
50
51        echo $searchHTML;
52    }
53
54    /**
55     * Get a form which can be used to adjust/refine the search
56     *
57     * @param string $query
58     *
59     * @return string
60     */
61    protected function getSearchFormHTML($query)
62    {
63        global $lang;
64
65        $searchForm = (new Form())->attrs(['method' => 'get']);
66        $searchForm->setHiddenField('do', 'search');
67
68        $searchForm->addFieldsetOpen();
69        $searchForm->addTextInput('id', '')->val($query);
70        $searchForm->addButton('', $lang['btn_search'])->attr('type', 'submit');
71        $searchForm->addFieldsetClose();
72
73        return $searchForm->toHTML();
74    }
75
76    /**
77     * Build the intro text for the search page
78     *
79     * @param string $query the search query
80     *
81     * @return string
82     */
83    protected function getSearchIntroHTML($query)
84    {
85        global $ID, $lang;
86
87        $intro = p_locale_xhtml('searchpage');
88        // allow use of placeholder in search intro
89        $pagecreateinfo = (auth_quickaclcheck($ID) >= AUTH_CREATE) ? $lang['searchcreatepage'] : '';
90        $intro = str_replace(
91            array('@QUERY@', '@SEARCH@', '@CREATEPAGEINFO@'),
92            array(hsc(rawurlencode($query)), hsc($query), $pagecreateinfo),
93            $intro
94        );
95        return $intro;
96    }
97
98    /**
99     * Build HTML for a list of pages with matching pagenames
100     *
101     * @param array $data search results
102     *
103     * @return string
104     */
105    protected function getPageLookupHTML($data)
106    {
107        if (empty($data)) {
108            return '';
109        }
110
111        global $lang;
112
113        $html = '<div class="search_quickresult">';
114        $html .= '<h3>' . $lang['quickhits'] . ':</h3>';
115        $html .= '<ul class="search_quickhits">';
116        foreach ($data as $id => $title) {
117            $html .= '<li> ';
118            if (useHeading('navigation')) {
119                $name = $title;
120            } else {
121                $ns = getNS($id);
122                if ($ns) {
123                    $name = shorten(noNS($id), ' (' . $ns . ')', 30);
124                } else {
125                    $name = $id;
126                }
127            }
128            $html .= html_wikilink(':' . $id, $name);
129            $html .= '</li> ';
130        }
131        $html .= '</ul> ';
132        //clear float (see http://www.complexspiral.com/publications/containing-floats/)
133        $html .= '<div class="clearer"></div>';
134        $html .= '</div>';
135
136        return $html;
137    }
138
139    /**
140     * Build HTML for fulltext search results or "no results" message
141     *
142     * @param array $data      the results of the fulltext search
143     * @param array $highlight the terms to be highlighted in the results
144     *
145     * @return string
146     */
147    protected function getFulltextResultsHTML($data, $highlight)
148    {
149        global $lang;
150
151        if (empty($data)) {
152            return '<div class="nothing">' . $lang['nothingfound'] . '</div>';
153        }
154
155        $html = '';
156        $html .= '<dl class="search_results">';
157        $num = 1;
158        foreach ($data as $id => $cnt) {
159            $html .= '<dt>';
160            $html .= html_wikilink(':' . $id, useHeading('navigation') ? null : $id, $highlight);
161            if ($cnt !== 0) {
162                $html .= ': ' . $cnt . ' ' . $lang['hits'] . '';
163            }
164            $html .= '</dt>';
165            if ($cnt !== 0) {
166                if ($num < FT_SNIPPET_NUMBER) { // create snippets for the first number of matches only
167                    $html .= '<dd>' . ft_snippet($id, $highlight) . '</dd>';
168                }
169                $num++;
170            }
171        }
172        $html .= '</dl>';
173
174        return $html;
175    }
176}
177