xref: /plugin/recommend/action.php (revision d0dae647eb4b3e8c01b15579fdc5751cb44d3575)
1<?php
2
3class action_plugin_recommend extends DokuWiki_Action_Plugin {
4
5    public function register(Doku_Event_Handler $controller) {
6        foreach (array('ACTION_ACT_PREPROCESS', 'AJAX_CALL_UNKNOWN',
7                       'TPL_ACT_UNKNOWN') as $event) {
8            $controller->register_hook($event, 'BEFORE', $this, 'handle');
9        }
10        $controller->register_hook('MENU_ITEMS_ASSEMBLY', 'AFTER', $this, 'handleMenu');
11        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'autocomplete');
12    }
13
14    /**
15     * Main processing
16     *
17     * @param Doku_Event $event
18     * @return void
19     */
20    public function handle(Doku_Event $event) {
21        if ($event->data !=='recommend') {
22            return;
23        }
24
25        $event->preventDefault();
26
27        if ($event->name === 'ACTION_ACT_PREPROCESS') {
28            return;
29        }
30
31        $event->stopPropagation();
32
33        global $INPUT;
34
35        // early output to trigger display msgs even via AJAX.
36        echo ' ';
37        tpl_flush();
38        if ($INPUT->server->str('REQUEST_METHOD') === 'POST') {
39            try {
40                $this->handlePost();
41                if ($event->name === 'AJAX_CALL_UNKNOWN') {
42                    $this->ajaxSuccess(); // To signal success to AJAX.
43                } else {
44                    msg($this->getLang('thanks'), 1);
45                }
46                return; // we're done here
47            } catch (\Exception $e) {
48                msg($e->getMessage(), -1);
49            }
50        }
51
52        echo $this->getForm();
53    }
54
55    /**
56     * Page menu item
57     *
58     * @param Doku_Event $event
59     * @return void
60     */
61    public function handleMenu(Doku_Event $event)
62    {
63        if ($event->data['view'] !== 'page') return;
64
65        array_splice($event->data['items'], -1, 0, [new \dokuwiki\plugin\recommend\MenuItem()]);
66    }
67
68    /**
69     * Autocomplete
70     * @param Doku_Event $event
71     * @throws Exception
72     * @author Andreas Gohr
73     *
74     */
75    public function autocomplete(Doku_Event $event)
76    {
77
78        if ($event->data !=='plugin_recommend_ac') {
79            return;
80        }
81
82        $event->preventDefault();
83        $event->stopPropagation();
84
85        /** @var \DokuWiki_Auth_Plugin $auth */
86        global $auth;
87        global $INPUT;
88
89        if (!$auth->canDo('getUsers')) {
90            throw new Exception('The user backend can not search for users');
91        }
92
93        header('Content-Type: application/json');
94
95        // check minimum length
96        $lookup = trim($INPUT->str('search'));
97        if (utf8_strlen($lookup) < 3) {
98            echo json_encode([]);
99            return;
100        }
101
102        // find users by login and name
103        $logins = $auth->retrieveUsers(0, 10, ['user' => $lookup]);
104        if (count($logins) < 10) {
105            $logins = array_merge($logins, $auth->retrieveUsers(0, 10, ['name' => $lookup]));
106        }
107
108        // reformat result for jQuery UI Autocomplete
109        $users = [];
110        foreach ($logins as $login => $info) {
111            $users[] = [
112                'label' => $info['name'] . ' [' . $login . ']',
113                'value' => $login
114            ];
115        }
116
117        echo json_encode($users);
118    }
119
120    /**
121     * Returns rendered form
122     *
123     * @return string
124     */
125    protected function getForm()
126    {
127        global $INPUT;
128
129        $id = getID(); // we may run in AJAX context
130        if ($id === '') throw new \RuntimeException('No ID given');
131
132        $form = new \dokuwiki\Form\Form([
133            'action' => wl($id, ['do' => 'recommend'], false, '&'),
134            'id' => 'plugin__recommend',
135        ]);
136        $form->setHiddenField('id', $id); // we need it for the ajax call
137
138        /** @var helper_plugin_recommend_assignment $helper */
139        $helper = plugin_load('helper', 'recommend_assignment');
140        $template = $helper->loadMatchingTemplate();
141
142        if ($INPUT->server->has('REMOTE_USER')) {
143            global $USERINFO;
144            $form->setHiddenField('s_name', $USERINFO['name']);
145            $form->setHiddenField('s_email', $USERINFO['mail']);
146        } else {
147            $form->addTextInput('s_name', $this->getLang('yourname'))->addClass('edit');
148            $form->addTextInput('s_email', $this->getLang('youremailaddress'))->addClass('edit');
149        }
150
151        $form->addTextInput('r_email', $this->getLang('recipients'))
152            ->addClass('edit')
153            ->val($template['user'] ?? '');
154        $form->addTextInput('subject', $this->getLang('subject'))
155            ->addClass('edit')
156            ->val($template['subject'] ?? '');
157        $form->addTextarea('comment', $this->getLang('message'))
158            ->attr('rows', '8')
159            ->attr('cols', '40')
160            ->addClass('edit')
161            ->val($template['message'] ?? '');
162
163        /** @var helper_plugin_captcha $captcha */
164        $captcha = plugin_load('helper', 'captcha');
165        if ($captcha) $form->addHTML($captcha->getHTML());
166
167        $form->addTagOpen('div')->addClass('buttons');
168        $form->addButton('submit', $this->getLang('send'))->attr('type', 'submit');
169        $form->addTagClose('div');
170
171        return $form->toHTML();
172    }
173
174    /**
175     * Handles form submission
176     *
177     * @throws Exception
178     */
179    protected function handlePost()
180    {
181        global $INPUT;
182
183        if (!checkSecurityToken()) {
184            throw new \Exception('Security token did not match');
185        }
186
187        /** @var helper_plugin_recommend_mail $mailHelper */
188        $mailHelper = plugin_load('helper', 'recommend_mail');
189
190        // Captcha plugin
191        $captcha = null;
192        if (@is_dir(DOKU_PLUGIN . 'captcha')) $captcha = plugin_load('helper','captcha');
193        if (!is_null($captcha) && $captcha->isEnabled() && !$captcha->check()) {
194            throw new \Exception($this->getLang('err_captcha'));
195        }
196
197        /* Validate input */
198        $recipients = $INPUT->str('r_email');
199
200        if (empty($recipients)) {
201            throw new \Exception($this->getLang('err_recipient'));
202        }
203
204        $recipients = $mailHelper->resolveRecipients($recipients);
205        $recipients = implode(',', $recipients);
206
207        if (!isset($_POST['s_email']) || !mail_isvalid($_POST['s_email'])) {
208            throw new \Exception($this->getLang('err_sendermail'));
209        }
210        if (!isset($_POST['s_name']) || trim($_POST['s_name']) === '') {
211            throw new \Exception($this->getLang('err_sendername'));
212        }
213        $s_name = $_POST['s_name'];
214        $sender = $s_name . ' <' . $_POST['s_email'] . '>';
215
216        $id = $INPUT->filter('cleanID')->str('id');
217        if ($id === '' || !page_exists($id)) throw new \Exception($this->getLang('err_page'));
218
219        $comment = $INPUT->str('comment');
220
221        /* Prepare mail text */
222        $mailtext = file_get_contents($this->localFN('template'));
223
224        global $conf;
225        foreach (array('PAGE' => $id,
226                       'SITE' => $conf['title'],
227                       'URL'  => wl($id, '', true),
228                       'COMMENT' => $comment,
229                       'AUTHOR' => $s_name) as $var => $val) {
230            $mailtext = str_replace('@' . $var . '@', $val, $mailtext);
231        }
232        /* Limit to two empty lines. */
233        $mailtext = preg_replace('/\n{4,}/', "\n\n\n", $mailtext);
234
235        $mailHelper->sendMail($recipients, $mailtext, $sender);
236
237        /** @var helper_plugin_recommend_log $log */
238        $log = new helper_plugin_recommend_log(date('Y-m'));
239        $log->writeEntry($id, $sender, $recipients, $comment);
240    }
241
242    /**
243     * show success message in ajax mode
244     */
245    protected function ajaxSuccess()
246    {
247        echo '<form id="plugin__recommend" accept-charset="utf-8" method="post" action="?do=recommend">';
248        echo '<div class="no">';
249        echo '<span class="ui-icon ui-icon-circle-check" style="float: left; margin: 0 7px 50px 0;"></span>';
250        echo '<p>' . $this->getLang('done') . '</p>';
251        echo '<button type="reset" class="button">' . $this->getLang('close') . '</button>';
252        echo '</div>';
253        echo '</form>';
254    }
255}
256