xref: /plugin/recommend/action.php (revision 9121cb07ff02058edafe0496d07f44d1c51921af)
14654e4deSAdrian Lang<?php
24654e4deSAdrian Lang
34654e4deSAdrian Langclass action_plugin_recommend extends DokuWiki_Action_Plugin {
44654e4deSAdrian Lang
52937e9a5SAnna Dabrowska    public function register(Doku_Event_Handler $controller) {
670f4a435SAdrian Lang        foreach (array('ACTION_ACT_PREPROCESS', 'AJAX_CALL_UNKNOWN',
770f4a435SAdrian Lang                       'TPL_ACT_UNKNOWN') as $event) {
82937e9a5SAnna Dabrowska            $controller->register_hook($event, 'BEFORE', $this, 'handle');
94654e4deSAdrian Lang        }
1045cf09e9SAnna Dabrowska        $controller->register_hook('MENU_ITEMS_ASSEMBLY', 'AFTER', $this, 'handleMenu');
11*9121cb07SAnna Dabrowska        $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'autocomplete');
124654e4deSAdrian Lang    }
134654e4deSAdrian Lang
14*9121cb07SAnna Dabrowska    /**
15*9121cb07SAnna Dabrowska     * Main processing
16*9121cb07SAnna Dabrowska     *
17*9121cb07SAnna Dabrowska     * @param Doku_Event $event
18*9121cb07SAnna Dabrowska     * @return void
19*9121cb07SAnna Dabrowska     */
202937e9a5SAnna Dabrowska    public function handle(Doku_Event $event) {
212937e9a5SAnna Dabrowska        if ($event->data !=='recommend') {
224654e4deSAdrian Lang            return;
234654e4deSAdrian Lang        }
244654e4deSAdrian Lang
254654e4deSAdrian Lang        $event->preventDefault();
264654e4deSAdrian Lang
274654e4deSAdrian Lang        if ($event->name === 'ACTION_ACT_PREPROCESS') {
284654e4deSAdrian Lang            return;
294654e4deSAdrian Lang        }
304654e4deSAdrian Lang
314654e4deSAdrian Lang        $event->stopPropagation();
324654e4deSAdrian Lang
33945a672eSAnna Dabrowska        global $INPUT;
34945a672eSAnna Dabrowska
35945a672eSAnna Dabrowska        // early output to trigger display msgs even via AJAX.
3670f4a435SAdrian Lang        echo ' ';
37945a672eSAnna Dabrowska        tpl_flush();
38945a672eSAnna Dabrowska        if ($INPUT->server->str('REQUEST_METHOD') === 'POST') {
39945a672eSAnna Dabrowska            try {
40945a672eSAnna Dabrowska                $this->handlePost();
41945a672eSAnna Dabrowska                if ($event->name === 'AJAX_CALL_UNKNOWN') {
42945a672eSAnna Dabrowska                    $this->ajaxSuccess(); // To signal success to AJAX.
43945a672eSAnna Dabrowska                } else {
44945a672eSAnna Dabrowska                    msg($this->getLang('thanks'), 1);
4570f4a435SAdrian Lang                }
46945a672eSAnna Dabrowska                return; // we're done here
47945a672eSAnna Dabrowska            } catch (\Exception $e) {
48945a672eSAnna Dabrowska                msg($e->getMessage(), -1);
49945a672eSAnna Dabrowska            }
50945a672eSAnna Dabrowska        }
51945a672eSAnna Dabrowska
522937e9a5SAnna Dabrowska        echo $this->getForm();
534654e4deSAdrian Lang    }
544654e4deSAdrian Lang
555187ba70SAnna Dabrowska    /**
565187ba70SAnna Dabrowska     * Page menu item
575187ba70SAnna Dabrowska     *
585187ba70SAnna Dabrowska     * @param Doku_Event $event
595187ba70SAnna Dabrowska     * @return void
605187ba70SAnna Dabrowska     */
6145cf09e9SAnna Dabrowska    public function handleMenu(Doku_Event $event)
6245cf09e9SAnna Dabrowska    {
6345cf09e9SAnna Dabrowska        if ($event->data['view'] !== 'page') return;
6445cf09e9SAnna Dabrowska
6545cf09e9SAnna Dabrowska        array_splice($event->data['items'], -1, 0, [new \dokuwiki\plugin\recommend\MenuItem()]);
6645cf09e9SAnna Dabrowska    }
675187ba70SAnna Dabrowska
682937e9a5SAnna Dabrowska    /**
69*9121cb07SAnna Dabrowska     * Autocomplete
70*9121cb07SAnna Dabrowska     * @param Doku_Event $event
71*9121cb07SAnna Dabrowska     * @throws Exception
72*9121cb07SAnna Dabrowska     * @author Andreas Gohr
73*9121cb07SAnna Dabrowska     *
74*9121cb07SAnna Dabrowska     */
75*9121cb07SAnna Dabrowska    public function autocomplete(Doku_Event $event)
76*9121cb07SAnna Dabrowska    {
77*9121cb07SAnna Dabrowska
78*9121cb07SAnna Dabrowska        if ($event->data !=='plugin_recommend_ac') {
79*9121cb07SAnna Dabrowska            return;
80*9121cb07SAnna Dabrowska        }
81*9121cb07SAnna Dabrowska
82*9121cb07SAnna Dabrowska        $event->preventDefault();
83*9121cb07SAnna Dabrowska        $event->stopPropagation();
84*9121cb07SAnna Dabrowska
85*9121cb07SAnna Dabrowska        /** @var \DokuWiki_Auth_Plugin $auth */
86*9121cb07SAnna Dabrowska        global $auth;
87*9121cb07SAnna Dabrowska        global $INPUT;
88*9121cb07SAnna Dabrowska
89*9121cb07SAnna Dabrowska        if (!$auth->canDo('getUsers')) {
90*9121cb07SAnna Dabrowska            throw new Exception('The user backend can not search for users');
91*9121cb07SAnna Dabrowska        }
92*9121cb07SAnna Dabrowska
93*9121cb07SAnna Dabrowska        header('Content-Type: application/json');
94*9121cb07SAnna Dabrowska
95*9121cb07SAnna Dabrowska        // check minimum length
96*9121cb07SAnna Dabrowska        $lookup = trim($INPUT->str('search'));
97*9121cb07SAnna Dabrowska        if (utf8_strlen($lookup) < 3) {
98*9121cb07SAnna Dabrowska            echo json_encode([]);
99*9121cb07SAnna Dabrowska            return;
100*9121cb07SAnna Dabrowska        }
101*9121cb07SAnna Dabrowska
102*9121cb07SAnna Dabrowska        // find users by login and name
103*9121cb07SAnna Dabrowska        $logins = $auth->retrieveUsers(0, 10, ['user' => $lookup]);
104*9121cb07SAnna Dabrowska        if (count($logins) < 10) {
105*9121cb07SAnna Dabrowska            $logins = array_merge($logins, $auth->retrieveUsers(0, 10, ['name' => $lookup]));
106*9121cb07SAnna Dabrowska        }
107*9121cb07SAnna Dabrowska
108*9121cb07SAnna Dabrowska        // reformat result for jQuery UI Autocomplete
109*9121cb07SAnna Dabrowska        $users = [];
110*9121cb07SAnna Dabrowska        foreach ($logins as $login => $info) {
111*9121cb07SAnna Dabrowska            $users[] = [
112*9121cb07SAnna Dabrowska                'label' => $info['name'] . ' [' . $login . ']',
113*9121cb07SAnna Dabrowska                'value' => $login
114*9121cb07SAnna Dabrowska            ];
115*9121cb07SAnna Dabrowska        }
116*9121cb07SAnna Dabrowska
117*9121cb07SAnna Dabrowska        echo json_encode($users);
118*9121cb07SAnna Dabrowska    }
119*9121cb07SAnna Dabrowska
120*9121cb07SAnna Dabrowska    /**
1212937e9a5SAnna Dabrowska     * Returns rendered form
1222937e9a5SAnna Dabrowska     *
1232937e9a5SAnna Dabrowska     * @return string
1242937e9a5SAnna Dabrowska     */
1252937e9a5SAnna Dabrowska    protected function getForm()
1262937e9a5SAnna Dabrowska    {
1272937e9a5SAnna Dabrowska        global $INPUT;
1282937e9a5SAnna Dabrowska
1292937e9a5SAnna Dabrowska        $id = getID(); // we may run in AJAX context
1302937e9a5SAnna Dabrowska        if ($id === '') throw new \RuntimeException('No ID given');
1312937e9a5SAnna Dabrowska
1322937e9a5SAnna Dabrowska        $form = new \dokuwiki\Form\Form([
1332937e9a5SAnna Dabrowska            'action' => wl($id, ['do' => 'recommend'], false, '&'),
134945a672eSAnna Dabrowska            'id' => 'plugin__recommend',
1352937e9a5SAnna Dabrowska        ]);
1362937e9a5SAnna Dabrowska        $form->setHiddenField('id', $id); // we need it for the ajax call
1372937e9a5SAnna Dabrowska
138b8b86b6cSAnna Dabrowska        /** @var helper_plugin_recommend_assignment $helper */
139b8b86b6cSAnna Dabrowska        $helper = plugin_load('helper', 'recommend_assignment');
140b8b86b6cSAnna Dabrowska        $template = $helper->loadMatchingTemplate();
141b8b86b6cSAnna Dabrowska
1422937e9a5SAnna Dabrowska        if ($INPUT->server->has('REMOTE_USER')) {
143e596e22bSAdrian Lang            global $USERINFO;
1442937e9a5SAnna Dabrowska            $form->setHiddenField('s_name', $USERINFO['name']);
1452937e9a5SAnna Dabrowska            $form->setHiddenField('s_email', $USERINFO['mail']);
146e596e22bSAdrian Lang        } else {
1472937e9a5SAnna Dabrowska            $form->addTextInput('s_name', $this->getLang('yourname'))->addClass('edit');
1482937e9a5SAnna Dabrowska            $form->addTextInput('s_email', $this->getLang('youremailaddress'))->addClass('edit');
149e596e22bSAdrian Lang        }
150e596e22bSAdrian Lang
151b8b86b6cSAnna Dabrowska        $recipientEmails = $template['user'] ?? '';
152b8b86b6cSAnna Dabrowska        $message = $template['message'] ?? '';
153b8b86b6cSAnna Dabrowska        $form->addTextInput('r_email', $this->getLang('recipients'))->addClass('edit')->val($recipientEmails);
1542937e9a5SAnna Dabrowska        $form->addTextInput('subject', $this->getLang('subject'))->addClass('edit');
155b8b86b6cSAnna Dabrowska        $form->addTextarea('comment', $this->getLang('message'))
156b8b86b6cSAnna Dabrowska            ->attr('rows', '8')
157b8b86b6cSAnna Dabrowska            ->attr('cols', '40')
158b8b86b6cSAnna Dabrowska            ->addClass('edit')
159b8b86b6cSAnna Dabrowska            ->val($message);
1602937e9a5SAnna Dabrowska
1612937e9a5SAnna Dabrowska        /** @var helper_plugin_captcha $captcha */
1622937e9a5SAnna Dabrowska        $captcha = plugin_load('helper', 'captcha');
1632937e9a5SAnna Dabrowska        if ($captcha) $form->addHTML($captcha->getHTML());
1642937e9a5SAnna Dabrowska
1652937e9a5SAnna Dabrowska        $form->addTagOpen('div')->addClass('buttons');
1662937e9a5SAnna Dabrowska        $form->addButton('submit', $this->getLang('send'))->attr('type', 'submit');
1672937e9a5SAnna Dabrowska        $form->addTagClose('div');
1682937e9a5SAnna Dabrowska
1692937e9a5SAnna Dabrowska        return $form->toHTML();
1704654e4deSAdrian Lang    }
1714654e4deSAdrian Lang
1722937e9a5SAnna Dabrowska    /**
173945a672eSAnna Dabrowska     * Handles form submission
1742937e9a5SAnna Dabrowska     *
1752937e9a5SAnna Dabrowska     * @throws Exception
1762937e9a5SAnna Dabrowska     */
177945a672eSAnna Dabrowska    protected function handlePost()
1782937e9a5SAnna Dabrowska    {
179945a672eSAnna Dabrowska        global $INPUT;
180945a672eSAnna Dabrowska
1812937e9a5SAnna Dabrowska        if (!checkSecurityToken()) {
1822937e9a5SAnna Dabrowska            throw new \Exception('Security token did not match');
1832937e9a5SAnna Dabrowska        }
1842937e9a5SAnna Dabrowska
1855187ba70SAnna Dabrowska        /** @var helper_plugin_recommend_mail $mailHelper */
1865187ba70SAnna Dabrowska        $mailHelper = plugin_load('helper', 'recommend_mail');
1875187ba70SAnna Dabrowska
188945a672eSAnna Dabrowska        // Captcha plugin
1895187ba70SAnna Dabrowska        $captcha = null;
1905187ba70SAnna Dabrowska        if (@is_dir(DOKU_PLUGIN . 'captcha')) $captcha = plugin_load('helper','captcha');
1915187ba70SAnna Dabrowska        if (!is_null($captcha) && $captcha->isEnabled() && !$captcha->check()) {
192945a672eSAnna Dabrowska            throw new \Exception($this->getLang('err_captcha'));
193e596e22bSAdrian Lang        }
194e596e22bSAdrian Lang
1955187ba70SAnna Dabrowska        /* Validate input */
1965187ba70SAnna Dabrowska        $recipients = $INPUT->str('r_email');
1975187ba70SAnna Dabrowska
1985187ba70SAnna Dabrowska        if (empty($recipients)) {
199945a672eSAnna Dabrowska            throw new \Exception($this->getLang('err_recipient'));
2004654e4deSAdrian Lang        }
201e596e22bSAdrian Lang
2025187ba70SAnna Dabrowska        $recipients = $mailHelper->resolveRecipients($recipients);
2035187ba70SAnna Dabrowska        $recipients = implode(',', $recipients);
2045187ba70SAnna Dabrowska
205e596e22bSAdrian Lang        if (!isset($_POST['s_email']) || !mail_isvalid($_POST['s_email'])) {
206945a672eSAnna Dabrowska            throw new \Exception($this->getLang('err_sendermail'));
207e596e22bSAdrian Lang        }
208c18a4184SAdrian Lang        if (!isset($_POST['s_name']) || trim($_POST['s_name']) === '') {
209945a672eSAnna Dabrowska            throw new \Exception($this->getLang('err_sendername'));
210c18a4184SAdrian Lang        }
211c18a4184SAdrian Lang        $s_name = $_POST['s_name'];
212c18a4184SAdrian Lang        $sender = $s_name . ' <' . $_POST['s_email'] . '>';
2134654e4deSAdrian Lang
2142937e9a5SAnna Dabrowska        $id = $INPUT->filter('cleanID')->str('id');
2152937e9a5SAnna Dabrowska        if ($id === '' || !page_exists($id)) throw new \Exception($this->getLang('err_page'));
2164654e4deSAdrian Lang
2172937e9a5SAnna Dabrowska        $comment = $INPUT->str('comment');
2184654e4deSAdrian Lang
2195187ba70SAnna Dabrowska        /* Prepare mail text */
220369955a1SAnna Dabrowska        $mailtext = file_get_contents($this->localFN('template'));
2214654e4deSAdrian Lang
2224654e4deSAdrian Lang        global $conf;
2235187ba70SAnna Dabrowska        foreach (array('PAGE' => $id,
2244654e4deSAdrian Lang                       'SITE' => $conf['title'],
2252937e9a5SAnna Dabrowska                       'URL'  => wl($id, '', true),
2264654e4deSAdrian Lang                       'COMMENT' => $comment,
227c18a4184SAdrian Lang                       'AUTHOR' => $s_name) as $var => $val) {
2284654e4deSAdrian Lang            $mailtext = str_replace('@' . $var . '@', $val, $mailtext);
2294654e4deSAdrian Lang        }
2302cdbf48fSAdrian Lang        /* Limit to two empty lines. */
2314654e4deSAdrian Lang        $mailtext = preg_replace('/\n{4,}/', "\n\n\n", $mailtext);
2324654e4deSAdrian Lang
2335187ba70SAnna Dabrowska        $mailHelper->sendMail($recipients, $mailtext, $sender);
234945a672eSAnna Dabrowska
2352937e9a5SAnna Dabrowska        /** @var helper_plugin_recommend_log $log */
2362937e9a5SAnna Dabrowska        $log = new helper_plugin_recommend_log(date('Y-m'));
2375187ba70SAnna Dabrowska        $log->writeEntry($id, $sender, $recipients, $comment);
2382937e9a5SAnna Dabrowska    }
239945a672eSAnna Dabrowska
240945a672eSAnna Dabrowska    /**
241945a672eSAnna Dabrowska     * show success message in ajax mode
242945a672eSAnna Dabrowska     */
243945a672eSAnna Dabrowska    protected function ajaxSuccess()
244945a672eSAnna Dabrowska    {
245945a672eSAnna Dabrowska        echo '<form id="plugin__recommend" accept-charset="utf-8" method="post" action="?do=recommend">';
246945a672eSAnna Dabrowska        echo '<div class="no">';
247945a672eSAnna Dabrowska        echo '<span class="ui-icon ui-icon-circle-check" style="float: left; margin: 0 7px 50px 0;"></span>';
248945a672eSAnna Dabrowska        echo '<p>' . $this->getLang('done') . '</p>';
249945a672eSAnna Dabrowska        echo '<button type="reset" class="button">' . $this->getLang('close') . '</button>';
250945a672eSAnna Dabrowska        echo '</div>';
251945a672eSAnna Dabrowska        echo '</form>';
252945a672eSAnna Dabrowska    }
2534654e4deSAdrian Lang}
254