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