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 // menu item is only for logged in users 65 if (empty($_SERVER['REMOTE_USER'])) return; 66 67 array_splice($event->data['items'], -1, 0, [new \dokuwiki\plugin\recommend\MenuItem()]); 68 } 69 70 /** 71 * Autocomplete 72 * @param Doku_Event $event 73 * @throws Exception 74 * @author Andreas Gohr 75 * 76 */ 77 public function autocomplete(Doku_Event $event) 78 { 79 80 if ($event->data !=='plugin_recommend_ac') { 81 return; 82 } 83 84 $event->preventDefault(); 85 $event->stopPropagation(); 86 87 /** @var \DokuWiki_Auth_Plugin $auth */ 88 global $auth; 89 global $INPUT; 90 91 if (!$auth->canDo('getUsers')) { 92 throw new Exception('The user backend can not search for users'); 93 } 94 95 header('Content-Type: application/json'); 96 97 // check minimum length 98 $lookup = trim($INPUT->str('search')); 99 if (utf8_strlen($lookup) < 3) { 100 echo json_encode([]); 101 return; 102 } 103 104 // find users by login and name 105 $logins = $auth->retrieveUsers(0, 10, ['user' => $lookup]); 106 if (count($logins) < 10) { 107 $logins = array_merge($logins, $auth->retrieveUsers(0, 10, ['name' => $lookup])); 108 } 109 110 // reformat result for jQuery UI Autocomplete 111 $users = []; 112 foreach ($logins as $login => $info) { 113 $users[] = [ 114 'label' => $info['name'] . ' [' . $login . ']', 115 'value' => $login 116 ]; 117 } 118 119 echo json_encode($users); 120 } 121 122 /** 123 * Returns rendered form 124 * 125 * @return string 126 */ 127 protected function getForm() 128 { 129 global $INPUT; 130 131 $id = getID(); // we may run in AJAX context 132 if ($id === '') throw new \RuntimeException('No ID given'); 133 134 $form = new \dokuwiki\Form\Form([ 135 'action' => wl($id, ['do' => 'recommend'], false, '&'), 136 'id' => 'plugin__recommend', 137 ]); 138 $form->setHiddenField('id', $id); // we need it for the ajax call 139 140 /** @var helper_plugin_recommend_assignment $helper */ 141 $helper = plugin_load('helper', 'recommend_assignment'); 142 $template = $helper->loadMatchingTemplate(); 143 144 if ($INPUT->server->has('REMOTE_USER')) { 145 global $USERINFO; 146 $form->setHiddenField('s_name', $USERINFO['name']); 147 $form->setHiddenField('s_email', $USERINFO['mail']); 148 } else { 149 $form->addTextInput('s_name', $this->getLang('yourname'))->addClass('edit'); 150 $form->addTextInput('s_email', $this->getLang('youremailaddress'))->addClass('edit'); 151 } 152 153 $form->addTextInput('r_email', $this->getLang('recipients')) 154 ->addClass('edit') 155 ->val($template['user'] ?? ''); 156 $form->addTextInput('subject', $this->getLang('subject')) 157 ->addClass('edit') 158 ->val($template['subject'] ?? ''); 159 $form->addTextarea('comment', $this->getLang('message')) 160 ->attr('rows', '8') 161 ->attr('cols', '40') 162 ->addClass('edit') 163 ->val($template['message'] ?? ''); 164 165 /** @var helper_plugin_captcha $captcha */ 166 $captcha = plugin_load('helper', 'captcha'); 167 if ($captcha) $form->addHTML($captcha->getHTML()); 168 169 $form->addTagOpen('div')->addClass('buttons'); 170 $form->addButton('submit', $this->getLang('send'))->attr('type', 'submit'); 171 $form->addTagClose('div'); 172 173 return $form->toHTML(); 174 } 175 176 /** 177 * Handles form submission 178 * 179 * @throws Exception 180 */ 181 protected function handlePost() 182 { 183 global $INPUT; 184 185 if (!checkSecurityToken()) { 186 throw new \Exception('Security token did not match'); 187 } 188 189 /** @var helper_plugin_recommend_mail $mailHelper */ 190 $mailHelper = plugin_load('helper', 'recommend_mail'); 191 192 // Captcha plugin 193 $captcha = null; 194 if (@is_dir(DOKU_PLUGIN . 'captcha')) $captcha = plugin_load('helper','captcha'); 195 if (!is_null($captcha) && $captcha->isEnabled() && !$captcha->check()) { 196 throw new \Exception($this->getLang('err_captcha')); 197 } 198 199 /* Validate input */ 200 $recipients = $INPUT->str('r_email'); 201 202 if (empty($recipients)) { 203 throw new \Exception($this->getLang('err_recipient')); 204 } 205 206 $recipients = $mailHelper->resolveRecipients($recipients); 207 $recipients = implode(',', $recipients); 208 209 if (!isset($_POST['s_email']) || !mail_isvalid($_POST['s_email'])) { 210 throw new \Exception($this->getLang('err_sendermail')); 211 } 212 if (!isset($_POST['s_name']) || trim($_POST['s_name']) === '') { 213 throw new \Exception($this->getLang('err_sendername')); 214 } 215 $s_name = $_POST['s_name']; 216 $sender = $s_name . ' <' . $_POST['s_email'] . '>'; 217 218 $id = $INPUT->filter('cleanID')->str('id'); 219 if ($id === '' || !page_exists($id)) throw new \Exception($this->getLang('err_page')); 220 221 $comment = $INPUT->str('comment'); 222 223 global $conf; 224 $replacements = [ 225 'PAGE' => $id, 226 'SITE' => $conf['title'], 227 'URL' => wl($id, '', true), 228 'COMMENT' => $comment, 229 'AUTHOR' => $s_name 230 ]; 231 232 $mailHelper->sendMail($recipients, $sender, $replacements); 233 234 /** @var helper_plugin_recommend_log $log */ 235 $log = new helper_plugin_recommend_log(date('Y-m')); 236 $log->writeEntry($id, $sender, $recipients, $comment); 237 } 238 239 /** 240 * show success message in ajax mode 241 */ 242 protected function ajaxSuccess() 243 { 244 echo '<form id="plugin__recommend" accept-charset="utf-8" method="post" action="?do=recommend">'; 245 echo '<div class="no">'; 246 echo '<span class="ui-icon ui-icon-circle-check" style="float: left; margin: 0 7px 50px 0;"></span>'; 247 echo '<p>' . $this->getLang('done') . '</p>'; 248 echo '<button type="reset" class="button">' . $this->getLang('close') . '</button>'; 249 echo '</div>'; 250 echo '</form>'; 251 } 252} 253