14654e4deSAdrian Lang<?php 24654e4deSAdrian Lang 3*c6f9d3d5SAnna Dabrowskause dokuwiki\Extension\ActionPlugin; 4*c6f9d3d5SAnna Dabrowskause dokuwiki\Extension\EventHandler; 5*c6f9d3d5SAnna Dabrowskause dokuwiki\Extension\Event; 6*c6f9d3d5SAnna Dabrowskause dokuwiki\plugin\recommend\MenuItem; 7*c6f9d3d5SAnna Dabrowskause dokuwiki\Form\Form; 8*c6f9d3d5SAnna Dabrowskause dokuwiki\Utf8\PhpString; 94654e4deSAdrian Lang 10*c6f9d3d5SAnna Dabrowskaclass action_plugin_recommend extends ActionPlugin 11*c6f9d3d5SAnna Dabrowska{ 12*c6f9d3d5SAnna Dabrowska public function register(EventHandler $controller) 13*c6f9d3d5SAnna Dabrowska { 14*c6f9d3d5SAnna Dabrowska foreach (['ACTION_ACT_PREPROCESS', 'AJAX_CALL_UNKNOWN', 'TPL_ACT_UNKNOWN'] as $event) { 152937e9a5SAnna Dabrowska $controller->register_hook($event, 'BEFORE', $this, 'handle'); 164654e4deSAdrian Lang } 1745cf09e9SAnna Dabrowska $controller->register_hook('MENU_ITEMS_ASSEMBLY', 'AFTER', $this, 'handleMenu'); 189121cb07SAnna Dabrowska $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'autocomplete'); 194654e4deSAdrian Lang } 204654e4deSAdrian Lang 219121cb07SAnna Dabrowska /** 229121cb07SAnna Dabrowska * Main processing 239121cb07SAnna Dabrowska * 24*c6f9d3d5SAnna Dabrowska * @param Event $event 259121cb07SAnna Dabrowska * @return void 269121cb07SAnna Dabrowska */ 27*c6f9d3d5SAnna Dabrowska public function handle(Event $event) 28*c6f9d3d5SAnna Dabrowska { 292937e9a5SAnna Dabrowska if ($event->data !== 'recommend') { 304654e4deSAdrian Lang return; 314654e4deSAdrian Lang } 324654e4deSAdrian Lang 334654e4deSAdrian Lang $event->preventDefault(); 344654e4deSAdrian Lang 354654e4deSAdrian Lang if ($event->name === 'ACTION_ACT_PREPROCESS') { 364654e4deSAdrian Lang return; 374654e4deSAdrian Lang } 384654e4deSAdrian Lang 394654e4deSAdrian Lang $event->stopPropagation(); 404654e4deSAdrian Lang 41945a672eSAnna Dabrowska global $INPUT; 42945a672eSAnna Dabrowska 43945a672eSAnna Dabrowska // early output to trigger display msgs even via AJAX. 4470f4a435SAdrian Lang echo ' '; 45945a672eSAnna Dabrowska tpl_flush(); 46945a672eSAnna Dabrowska if ($INPUT->server->str('REQUEST_METHOD') === 'POST') { 47945a672eSAnna Dabrowska try { 48945a672eSAnna Dabrowska $this->handlePost(); 49945a672eSAnna Dabrowska if ($event->name === 'AJAX_CALL_UNKNOWN') { 50945a672eSAnna Dabrowska $this->ajaxSuccess(); // To signal success to AJAX. 51945a672eSAnna Dabrowska } else { 52945a672eSAnna Dabrowska msg($this->getLang('thanks'), 1); 5370f4a435SAdrian Lang } 54945a672eSAnna Dabrowska return; // we're done here 55945a672eSAnna Dabrowska } catch (\Exception $e) { 56945a672eSAnna Dabrowska msg($e->getMessage(), -1); 57945a672eSAnna Dabrowska } 58945a672eSAnna Dabrowska } 59945a672eSAnna Dabrowska 602937e9a5SAnna Dabrowska echo $this->getForm(); 614654e4deSAdrian Lang } 624654e4deSAdrian Lang 635187ba70SAnna Dabrowska /** 645187ba70SAnna Dabrowska * Page menu item 655187ba70SAnna Dabrowska * 66*c6f9d3d5SAnna Dabrowska * @param Event $event 675187ba70SAnna Dabrowska * @return void 685187ba70SAnna Dabrowska */ 69*c6f9d3d5SAnna Dabrowska public function handleMenu(Event $event) 7045cf09e9SAnna Dabrowska { 7145cf09e9SAnna Dabrowska if ($event->data['view'] !== 'page') return; 729fd061b7SAnna Dabrowska // menu item is only for logged in users 739fd061b7SAnna Dabrowska if (empty($_SERVER['REMOTE_USER'])) return; 7445cf09e9SAnna Dabrowska 75*c6f9d3d5SAnna Dabrowska array_splice($event->data['items'], -1, 0, [new MenuItem()]); 7645cf09e9SAnna Dabrowska } 775187ba70SAnna Dabrowska 782937e9a5SAnna Dabrowska /** 799121cb07SAnna Dabrowska * Autocomplete 80*c6f9d3d5SAnna Dabrowska * @param Event $event 819121cb07SAnna Dabrowska * @throws Exception 829121cb07SAnna Dabrowska * @author Andreas Gohr 839121cb07SAnna Dabrowska */ 84*c6f9d3d5SAnna Dabrowska public function autocomplete(Event $event) 859121cb07SAnna Dabrowska { 869121cb07SAnna Dabrowska 879121cb07SAnna Dabrowska if ($event->data !== 'plugin_recommend_ac') { 889121cb07SAnna Dabrowska return; 899121cb07SAnna Dabrowska } 909121cb07SAnna Dabrowska 919121cb07SAnna Dabrowska $event->preventDefault(); 929121cb07SAnna Dabrowska $event->stopPropagation(); 939121cb07SAnna Dabrowska 949121cb07SAnna Dabrowska /** @var \DokuWiki_Auth_Plugin $auth */ 959121cb07SAnna Dabrowska global $auth; 969121cb07SAnna Dabrowska global $INPUT; 979121cb07SAnna Dabrowska 989121cb07SAnna Dabrowska if (!$auth->canDo('getUsers')) { 999121cb07SAnna Dabrowska throw new Exception('The user backend can not search for users'); 1009121cb07SAnna Dabrowska } 1019121cb07SAnna Dabrowska 1029121cb07SAnna Dabrowska header('Content-Type: application/json'); 1039121cb07SAnna Dabrowska 1049121cb07SAnna Dabrowska // check minimum length 1059121cb07SAnna Dabrowska $lookup = trim($INPUT->str('search')); 106*c6f9d3d5SAnna Dabrowska if (PhpString::strlen($lookup) < 3) { 1079121cb07SAnna Dabrowska echo json_encode([]); 1089121cb07SAnna Dabrowska return; 1099121cb07SAnna Dabrowska } 1109121cb07SAnna Dabrowska 1119121cb07SAnna Dabrowska // find users by login and name 1129121cb07SAnna Dabrowska $logins = $auth->retrieveUsers(0, 10, ['user' => $lookup]); 1139121cb07SAnna Dabrowska if (count($logins) < 10) { 1149121cb07SAnna Dabrowska $logins = array_merge($logins, $auth->retrieveUsers(0, 10, ['name' => $lookup])); 1159121cb07SAnna Dabrowska } 1169121cb07SAnna Dabrowska 1179121cb07SAnna Dabrowska // reformat result for jQuery UI Autocomplete 1189121cb07SAnna Dabrowska $users = []; 1199121cb07SAnna Dabrowska foreach ($logins as $login => $info) { 1209121cb07SAnna Dabrowska $users[] = [ 1219121cb07SAnna Dabrowska 'label' => $info['name'] . ' [' . $login . ']', 1229121cb07SAnna Dabrowska 'value' => $login 1239121cb07SAnna Dabrowska ]; 1249121cb07SAnna Dabrowska } 1259121cb07SAnna Dabrowska 1269121cb07SAnna Dabrowska echo json_encode($users); 1279121cb07SAnna Dabrowska } 1289121cb07SAnna Dabrowska 1299121cb07SAnna Dabrowska /** 1302937e9a5SAnna Dabrowska * Returns rendered form 1312937e9a5SAnna Dabrowska * 1322937e9a5SAnna Dabrowska * @return string 1332937e9a5SAnna Dabrowska */ 1342937e9a5SAnna Dabrowska protected function getForm() 1352937e9a5SAnna Dabrowska { 1362937e9a5SAnna Dabrowska global $INPUT; 1372937e9a5SAnna Dabrowska 1382937e9a5SAnna Dabrowska $id = getID(); // we may run in AJAX context 1392937e9a5SAnna Dabrowska if ($id === '') throw new \RuntimeException('No ID given'); 1402937e9a5SAnna Dabrowska 141*c6f9d3d5SAnna Dabrowska $form = new Form([ 1422937e9a5SAnna Dabrowska 'action' => wl($id, ['do' => 'recommend'], false, '&'), 143945a672eSAnna Dabrowska 'id' => 'plugin__recommend', 1442937e9a5SAnna Dabrowska ]); 1452937e9a5SAnna Dabrowska $form->setHiddenField('id', $id); // we need it for the ajax call 1462937e9a5SAnna Dabrowska 147b8b86b6cSAnna Dabrowska /** @var helper_plugin_recommend_assignment $helper */ 148b8b86b6cSAnna Dabrowska $helper = plugin_load('helper', 'recommend_assignment'); 149b8b86b6cSAnna Dabrowska $template = $helper->loadMatchingTemplate(); 150b8b86b6cSAnna Dabrowska 1512937e9a5SAnna Dabrowska if ($INPUT->server->has('REMOTE_USER')) { 152e596e22bSAdrian Lang global $USERINFO; 1532937e9a5SAnna Dabrowska $form->setHiddenField('s_name', $USERINFO['name']); 1542937e9a5SAnna Dabrowska $form->setHiddenField('s_email', $USERINFO['mail']); 155e596e22bSAdrian Lang } else { 1562937e9a5SAnna Dabrowska $form->addTextInput('s_name', $this->getLang('yourname'))->addClass('edit'); 1572937e9a5SAnna Dabrowska $form->addTextInput('s_email', $this->getLang('youremailaddress'))->addClass('edit'); 158e596e22bSAdrian Lang } 159e596e22bSAdrian Lang 160d0dae647SAnna Dabrowska $form->addTextInput('r_email', $this->getLang('recipients')) 161d0dae647SAnna Dabrowska ->addClass('edit') 162d0dae647SAnna Dabrowska ->val($template['user'] ?? ''); 163d0dae647SAnna Dabrowska $form->addTextInput('subject', $this->getLang('subject')) 164d0dae647SAnna Dabrowska ->addClass('edit') 165d0dae647SAnna Dabrowska ->val($template['subject'] ?? ''); 166b8b86b6cSAnna Dabrowska $form->addTextarea('comment', $this->getLang('message')) 167b8b86b6cSAnna Dabrowska ->attr('rows', '8') 168b8b86b6cSAnna Dabrowska ->attr('cols', '40') 169b8b86b6cSAnna Dabrowska ->addClass('edit') 170d0dae647SAnna Dabrowska ->val($template['message'] ?? ''); 1712937e9a5SAnna Dabrowska 1722937e9a5SAnna Dabrowska /** @var helper_plugin_captcha $captcha */ 1732937e9a5SAnna Dabrowska $captcha = plugin_load('helper', 'captcha'); 1742937e9a5SAnna Dabrowska if ($captcha) $form->addHTML($captcha->getHTML()); 1752937e9a5SAnna Dabrowska 1762937e9a5SAnna Dabrowska $form->addTagOpen('div')->addClass('buttons'); 1772937e9a5SAnna Dabrowska $form->addButton('submit', $this->getLang('send'))->attr('type', 'submit'); 1782937e9a5SAnna Dabrowska $form->addTagClose('div'); 1792937e9a5SAnna Dabrowska 1802937e9a5SAnna Dabrowska return $form->toHTML(); 1814654e4deSAdrian Lang } 1824654e4deSAdrian Lang 1832937e9a5SAnna Dabrowska /** 184945a672eSAnna Dabrowska * Handles form submission 1852937e9a5SAnna Dabrowska * 1862937e9a5SAnna Dabrowska * @throws Exception 1872937e9a5SAnna Dabrowska */ 188945a672eSAnna Dabrowska protected function handlePost() 1892937e9a5SAnna Dabrowska { 190945a672eSAnna Dabrowska global $INPUT; 191945a672eSAnna Dabrowska 1922937e9a5SAnna Dabrowska if (!checkSecurityToken()) { 1932937e9a5SAnna Dabrowska throw new \Exception('Security token did not match'); 1942937e9a5SAnna Dabrowska } 1952937e9a5SAnna Dabrowska 1965187ba70SAnna Dabrowska /** @var helper_plugin_recommend_mail $mailHelper */ 1975187ba70SAnna Dabrowska $mailHelper = plugin_load('helper', 'recommend_mail'); 1985187ba70SAnna Dabrowska 199945a672eSAnna Dabrowska // Captcha plugin 2005187ba70SAnna Dabrowska $captcha = null; 2015187ba70SAnna Dabrowska if (@is_dir(DOKU_PLUGIN . 'captcha')) $captcha = plugin_load('helper', 'captcha'); 2025187ba70SAnna Dabrowska if (!is_null($captcha) && $captcha->isEnabled() && !$captcha->check()) { 203945a672eSAnna Dabrowska throw new \Exception($this->getLang('err_captcha')); 204e596e22bSAdrian Lang } 205e596e22bSAdrian Lang 2065187ba70SAnna Dabrowska /* Validate input */ 2075187ba70SAnna Dabrowska $recipients = $INPUT->str('r_email'); 2085187ba70SAnna Dabrowska 2095187ba70SAnna Dabrowska if (empty($recipients)) { 210945a672eSAnna Dabrowska throw new \Exception($this->getLang('err_recipient')); 2114654e4deSAdrian Lang } 212e596e22bSAdrian Lang 2135187ba70SAnna Dabrowska $recipients = $mailHelper->resolveRecipients($recipients); 2145187ba70SAnna Dabrowska $recipients = implode(',', $recipients); 2155187ba70SAnna Dabrowska 216e596e22bSAdrian Lang if (!isset($_POST['s_email']) || !mail_isvalid($_POST['s_email'])) { 217945a672eSAnna Dabrowska throw new \Exception($this->getLang('err_sendermail')); 218e596e22bSAdrian Lang } 219c18a4184SAdrian Lang if (!isset($_POST['s_name']) || trim($_POST['s_name']) === '') { 220945a672eSAnna Dabrowska throw new \Exception($this->getLang('err_sendername')); 221c18a4184SAdrian Lang } 222c18a4184SAdrian Lang $s_name = $_POST['s_name']; 223c18a4184SAdrian Lang $sender = $s_name . ' <' . $_POST['s_email'] . '>'; 2244654e4deSAdrian Lang 2252937e9a5SAnna Dabrowska $id = $INPUT->filter('cleanID')->str('id'); 2262937e9a5SAnna Dabrowska if ($id === '' || !page_exists($id)) throw new \Exception($this->getLang('err_page')); 2274654e4deSAdrian Lang 2282937e9a5SAnna Dabrowska $comment = $INPUT->str('comment'); 2294654e4deSAdrian Lang 2304654e4deSAdrian Lang global $conf; 231f1a0181dSAnna Dabrowska $replacements = [ 232f1a0181dSAnna Dabrowska 'PAGE' => $id, 2334654e4deSAdrian Lang 'SITE' => $conf['title'], 2342937e9a5SAnna Dabrowska 'URL' => wl($id, '', true), 2354654e4deSAdrian Lang 'COMMENT' => $comment, 236f1a0181dSAnna Dabrowska 'AUTHOR' => $s_name 237f1a0181dSAnna Dabrowska ]; 2384654e4deSAdrian Lang 239f1a0181dSAnna Dabrowska $mailHelper->sendMail($recipients, $sender, $replacements); 240945a672eSAnna Dabrowska 2412937e9a5SAnna Dabrowska /** @var helper_plugin_recommend_log $log */ 2422937e9a5SAnna Dabrowska $log = new helper_plugin_recommend_log(date('Y-m')); 2435187ba70SAnna Dabrowska $log->writeEntry($id, $sender, $recipients, $comment); 2442937e9a5SAnna Dabrowska } 245945a672eSAnna Dabrowska 246945a672eSAnna Dabrowska /** 247945a672eSAnna Dabrowska * show success message in ajax mode 248945a672eSAnna Dabrowska */ 249945a672eSAnna Dabrowska protected function ajaxSuccess() 250945a672eSAnna Dabrowska { 251945a672eSAnna Dabrowska echo '<form id="plugin__recommend" accept-charset="utf-8" method="post" action="?do=recommend">'; 252945a672eSAnna Dabrowska echo '<div class="no">'; 253945a672eSAnna Dabrowska echo '<span class="ui-icon ui-icon-circle-check" style="float: left; margin: 0 7px 50px 0;"></span>'; 254945a672eSAnna Dabrowska echo '<p>' . $this->getLang('done') . '</p>'; 255945a672eSAnna Dabrowska echo '<button type="reset" class="button">' . $this->getLang('close') . '</button>'; 256945a672eSAnna Dabrowska echo '</div>'; 257945a672eSAnna Dabrowska echo '</form>'; 258945a672eSAnna Dabrowska } 2594654e4deSAdrian Lang} 260