1<?php
2
3use dokuwiki\Form\Form;
4use dokuwiki\Extension\ActionPlugin;
5use dokuwiki\Extension\EventHandler;
6use dokuwiki\Extension\Event;
7use dokuwiki\Form\InputElement;
8
9/**
10 * DokuWiki Plugin searchns (Action Component)
11 *
12 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html
13 * @author Anna Dabrowska <dokuwiki@cosmocode.de>
14 */
15class action_plugin_searchns extends ActionPlugin
16{
17    /** @inheritDoc */
18    public function register(EventHandler $controller)
19    {
20        $controller->register_hook('FORM_QUICKSEARCH_OUTPUT', 'BEFORE', $this, 'handleForm');
21        $controller->register_hook('DOKUWIKI_STARTED', 'AFTER', $this, 'handleStart');
22        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjax');
23        $controller->register_hook('SEARCH_QUERY_PAGELOOKUP', 'AFTER', $this, 'sortResults');
24        $controller->register_hook('SEARCH_RESULT_PAGELOOKUP', 'AFTER', $this, 'resultHeading');
25    }
26
27    /**
28     * Performs the quick search
29     *
30     * @param Event $event
31     * @return void
32     */
33    public function handleAjax(Event $event)
34    {
35        if ($event->data !== 'plugin_searchns_qsearch') return;
36
37        $event->preventDefault();
38        $event->stopPropagation();
39
40        /** @var helper_plugin_searchns $helper */
41        $helper = plugin_load('helper', 'searchns');
42        echo $helper->qSearch();
43    }
44
45    /**
46     * Adds selected namespace to global query
47     * @param Event $event
48     * @return void
49     */
50    public function handleStart(Event $event)
51    {
52        global $INPUT;
53        global $QUERY;
54
55        if ($INPUT->str('ns')) {
56            $QUERY .= ' @' . $INPUT->str('ns');
57        }
58    }
59
60    /**
61     * Modifies the quicksearch form
62     *
63     * @param Event $event Event object
64     * @return void
65     */
66    public function handleForm(Event $event)
67    {
68        global $ACT;
69        global $QUERY;
70        global $INPUT;
71        global $lang;
72
73        /** @var Form $form */
74        $form = $event->data;
75
76        /** @var \helper_plugin_searchns $helper */
77        $helper = plugin_load('helper', 'searchns');
78
79        $ns = $INPUT->str('ns');
80
81        // strip namespace from text input, we have a dropdown for this
82        if ($ns) {
83            $q = str_replace('@' . $ns, '', $QUERY);
84        } else {
85            $q = '';
86        }
87
88        $newQ = new InputElement('text', 'q');
89        $newQ->addClass('edit')
90            ->attrs([
91                'title' => '[F]',
92                'accesskey' => 'f',
93                'placeholder' => $lang['btn_search'],
94                'autocomplete' => 'off',
95            ])
96            ->id('qsearchns__in')
97            ->val($ACT === 'search' ? $q : '')
98            ->useInput(false);
99
100        $form->replaceElement(
101            $newQ,
102            $form->findPositionByAttribute('name', 'q')
103        );
104
105        $namespaces = $helper->getNsFromConfig();
106        if ($this->getConf('filter by acl')) {
107            $namespaces = array_filter($namespaces, [$helper, 'filterByACL']);
108        }
109
110        // prepend namespace dropdown
111        $form->addDropdown(
112            'ns',
113            array_flip($namespaces),
114            $this->getLang('namespace label'),
115            0
116        )
117            ->id('qsearchns__ns')
118            ->val($ns);
119    }
120
121    /**
122     * Sort and group results based on configured namespaces.
123     *
124     * @param Event $event
125     * @return void
126     */
127    public function sortResults(Event $event)
128    {
129        global $INPUT;
130        global $QUERY;
131
132        if ($INPUT->str('ns') || strpos($QUERY, '@') !== false) return;
133
134        $event->stopPropagation();
135
136        /** @var \helper_plugin_searchns $helper */
137        $helper = plugin_load('helper', 'searchns');
138
139        $event->result = $helper->sortAndGroup($event->result);
140    }
141
142    /**
143     * Format namespace headings (pseudo results)
144     *
145     * @param Event $event
146     * @return void
147     */
148    public function resultHeading(Event $event)
149    {
150        global $INPUT;
151        global $QUERY;
152
153        if ($INPUT->str('ns') || strpos($QUERY, '@') !== false) return;
154
155        /** @var \helper_plugin_searchns $helper */
156        $helper = plugin_load('helper', 'searchns');
157
158        $labels = array_keys($helper->getNsFromConfig() + [$this->getLang('other label') => '']);
159
160        if (in_array($event->data['page'], $labels)) {
161            $event->data['listItemContent'][0] = '<div class="searchns_heading">' . $event->data['page'] . '</div>';
162        }
163    }
164}
165