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