xref: /plugin/elasticsearch/action/search.php (revision 621682790b24b3b8c662e41adaaddfd1d4d3978f)
1<?php
2/**
3 * DokuWiki Plugin elasticsearch (Action Component)
4 *
5 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
6 * @author  Andreas Gohr <gohr@cosmocode.de>
7 */
8
9// must be run within Dokuwiki
10if(!defined('DOKU_INC')) die();
11
12class action_plugin_elasticsearch_indexing extends DokuWiki_Action_Plugin {
13
14    /**
15     * Registers a callback function for a given event
16     *
17     * @param Doku_Event_Handler $controller DokuWiki's event controller object
18     * @return void
19     */
20    public function register(Doku_Event_Handler &$controller) {
21
22        $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_preprocess');
23        $controller->register_hook('TPL_ACT_UNKNOWN', 'BEFORE', $this, 'handle_action');
24
25    }
26
27    /**
28     * allow our custom do command
29     *
30     * @param Doku_Event $event
31     * @param $param
32     */
33    public function handle_preprocess(Doku_Event &$event, $param) {
34        if($event->data != 'elasticsearch') return;
35        $event->preventDefault();
36        $event->stopPropagation();
37    }
38
39    /**
40     * do the actual search
41     *
42     * @param Doku_Event $event
43     * @param $param
44     */
45    public function handle_action(Doku_Event &$event, $param) {
46        if($event->data != 'elasticsearch') return;
47        $event->preventDefault();
48        $event->stopPropagation();
49        global $QUERY;
50
51        /** @var helper_plugin_elasticsearch_client $hlp */
52        $hlp = plugin_load('helper', 'elasticsearch_client');
53
54        $client = $hlp->connect();
55        $index  = $client->getIndex($this->getConf('indexname'));
56
57        // define the query string
58        $qstring = new \Elastica\Query\QueryString();
59        $qstring->setQuery($QUERY);
60
61        // create the actual search object
62        $equery = new \Elastica\Query();
63        $equery->setQuery($qstring);
64        $equery->setHighlight(
65            array(
66                "pre_tags"  => array('ELASTICSEARCH_MARKER_IN'),
67                "post_tags" => array('ELASTICSEARCH_MARKER_OUT'),
68                "fields"    => array("content" => new \StdClass())
69            )
70        );
71
72        $result = $index->search($equery);
73        $this->print_results($result);
74    }
75
76    /**
77     * Output the search results
78     *
79     * @fixme maybe add facets later?
80     * @param \Elastica\Result[] $results
81     */
82    protected function print_results($results) {
83        global $lang;
84        global $QUERY;
85
86        // just reuse the standard search page intro:
87        $intro = p_locale_xhtml('searchpage');
88        $intro = str_replace(
89            array('@QUERY@','@SEARCH@'),
90            array(hsc(rawurlencode($QUERY)),hsc($QUERY)),
91            $intro);
92        echo $intro;
93        flush();
94
95        // output results
96        $found = 0;
97        echo '<dl class="search_results">';
98        foreach($results as $row) {
99            /** @var Elastica\Result $row */
100
101            $page = $row->getSource()['uri'];
102            if(!page_exists($page) || auth_quickaclcheck($page) < AUTH_READ) continue;
103
104            echo '<dt>';
105            echo html_wikilink($page);
106            echo ': ' . $row->getScore();
107            echo '</dt>';
108
109            // snippets
110            echo '<dd>';
111            echo str_replace(
112                array('ELASTICSEARCH_MARKER_IN', 'ELASTICSEARCH_MARKER_OUT'),
113                array('<strong class="search_hit">', '</strong>'),
114                hsc(join(' … ', (array) $row->getHighlights()['content']))
115            );
116            echo '</dd>';
117            $found++;
118        }
119        if(!$found) {
120            echo '<dt>'.$lang['nothingfound'].'</dt>';
121        }
122        echo '</dl>';
123    }
124
125}