xref: /plugin/tagging/action/elasticsearch.php (revision 4a5f6748cc05de089e597e38ded8dddb091156f4)
1<?php
2
3/**
4 * Class action_plugin_tagging_elasticsearch
5 */
6class action_plugin_tagging_elasticsearch extends DokuWiki_Action_Plugin
7{
8
9    public function register(Doku_Event_Handler $controller)
10    {
11        $controller->register_hook(
12            'PLUGIN_ELASTICSEARCH_CREATEMAPPING', 'BEFORE', $this,
13            'elasticMapping'
14        );
15
16        $controller->register_hook(
17            'PLUGIN_ELASTICSEARCH_INDEXPAGE', 'BEFORE', $this,
18            'elasticIndexPage'
19        );
20
21        $controller->register_hook(
22            'PLUGIN_ELASTICSEARCH_FILTERS', 'BEFORE', $this,
23            'elasticSearchFilter'
24        );
25
26        $controller->register_hook(
27            'PLUGIN_ELASTICSEARCH_SEARCHFIELDS', 'BEFORE', $this,
28            'elasticSearchFields'
29        );
30
31        $controller->register_hook(
32            'PLUGIN_ELASTICSEARCH_QUERY', 'BEFORE', $this,
33            'setupTagSearchElastic'
34        );
35    }
36    /**
37     * Add our own field mapping to Elasticsearch
38     *
39     * @param Doku_Event $event
40     */
41    public function elasticMapping(Doku_Event $event)
42    {
43        $event->data[] = ['tagging' => ['type' => 'keyword']];
44    }
45
46    /**
47     * Add taggings to Elastic index
48     *
49     * @param Doku_Event $event
50     */
51    public function elasticIndexPage(Doku_Event $event)
52    {
53        $data = &$event->data;
54
55        /** @var helper_plugin_tagging $hlp */
56        $hlp = plugin_load('helper', 'tagging');
57        $tags = $hlp->findItems(['pid' => $data['uri']], 'tag');
58
59        $data['tagging'] = array_keys($tags);
60    }
61
62    /**
63     * Add configuration for tagging filter in advanced search
64     * when using Elasticsearch plugin
65     *
66     * @param Doku_Event $event
67     */
68    public function elasticSearchFilter(Doku_Event $event)
69    {
70        $event->data['tagging'] = [
71            'label' => $this->getLang('search_filter_label'),
72            'fieldPath' => 'tagging',
73            'limit' => '100',
74        ];
75    }
76
77    /**
78     * Remove tags from query string and put them into $INPUT
79     * to be used as filter by Elasticsearch.
80     * Also return new #tag values to be appended to the query.
81     *
82     * @param Doku_Event $event
83     */
84    public function setupTagSearchElastic(Doku_Event $event)
85    {
86        global $QUERY;
87        global $INPUT;
88
89        $taggingFilter = $INPUT->arr('tagging');
90
91        // get (hash)tags from query
92        preg_match_all('/(?:#)(\w+)/u', $QUERY, $matches);
93        if (isset($matches[1])) {
94            $INPUT->set('tagging', array_merge($matches[1], $taggingFilter));
95        }
96        \action_plugin_tagging_search::removeTagsFromQuery($QUERY);
97
98        // return tagging filter as hashtags to be appended to the original query (without doubles)
99        if ($taggingFilter) {
100            $additions = array_map(function ($tag) use ($matches) {
101                if (!isset($matches[1]) || !in_array($tag, $matches[1])) {
102                    return "#$tag";
103                }
104                return null;
105            }, $taggingFilter);
106            $event->data += array_filter($additions);
107        }
108    }
109
110    /**
111     * Add tagging to the list of search fields
112     *
113     * @param Doku_Event $event
114     */
115    public function elasticSearchFields(Doku_Event $event)
116    {
117        array_push($event->data, 'tagging');
118    }
119}
120