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 $recipientEmails = $template['user'] ?? ''; 152 $message = $template['message'] ?? ''; 153 $form->addTextInput('r_email', $this->getLang('recipients'))->addClass('edit')->val($recipientEmails); 154 $form->addTextInput('subject', $this->getLang('subject'))->addClass('edit'); 155 $form->addTextarea('comment', $this->getLang('message')) 156 ->attr('rows', '8') 157 ->attr('cols', '40') 158 ->addClass('edit') 159 ->val($message); 160 161 /** @var helper_plugin_captcha $captcha */ 162 $captcha = plugin_load('helper', 'captcha'); 163 if ($captcha) $form->addHTML($captcha->getHTML()); 164 165 $form->addTagOpen('div')->addClass('buttons'); 166 $form->addButton('submit', $this->getLang('send'))->attr('type', 'submit'); 167 $form->addTagClose('div'); 168 169 return $form->toHTML(); 170 } 171 172 /** 173 * Handles form submission 174 * 175 * @throws Exception 176 */ 177 protected function handlePost() 178 { 179 global $INPUT; 180 181 if (!checkSecurityToken()) { 182 throw new \Exception('Security token did not match'); 183 } 184 185 /** @var helper_plugin_recommend_mail $mailHelper */ 186 $mailHelper = plugin_load('helper', 'recommend_mail'); 187 188 // Captcha plugin 189 $captcha = null; 190 if (@is_dir(DOKU_PLUGIN . 'captcha')) $captcha = plugin_load('helper','captcha'); 191 if (!is_null($captcha) && $captcha->isEnabled() && !$captcha->check()) { 192 throw new \Exception($this->getLang('err_captcha')); 193 } 194 195 /* Validate input */ 196 $recipients = $INPUT->str('r_email'); 197 198 if (empty($recipients)) { 199 throw new \Exception($this->getLang('err_recipient')); 200 } 201 202 $recipients = $mailHelper->resolveRecipients($recipients); 203 $recipients = implode(',', $recipients); 204 205 if (!isset($_POST['s_email']) || !mail_isvalid($_POST['s_email'])) { 206 throw new \Exception($this->getLang('err_sendermail')); 207 } 208 if (!isset($_POST['s_name']) || trim($_POST['s_name']) === '') { 209 throw new \Exception($this->getLang('err_sendername')); 210 } 211 $s_name = $_POST['s_name']; 212 $sender = $s_name . ' <' . $_POST['s_email'] . '>'; 213 214 $id = $INPUT->filter('cleanID')->str('id'); 215 if ($id === '' || !page_exists($id)) throw new \Exception($this->getLang('err_page')); 216 217 $comment = $INPUT->str('comment'); 218 219 /* Prepare mail text */ 220 $mailtext = file_get_contents($this->localFN('template')); 221 222 global $conf; 223 foreach (array('PAGE' => $id, 224 'SITE' => $conf['title'], 225 'URL' => wl($id, '', true), 226 'COMMENT' => $comment, 227 'AUTHOR' => $s_name) as $var => $val) { 228 $mailtext = str_replace('@' . $var . '@', $val, $mailtext); 229 } 230 /* Limit to two empty lines. */ 231 $mailtext = preg_replace('/\n{4,}/', "\n\n\n", $mailtext); 232 233 $mailHelper->sendMail($recipients, $mailtext, $sender); 234 235 /** @var helper_plugin_recommend_log $log */ 236 $log = new helper_plugin_recommend_log(date('Y-m')); 237 $log->writeEntry($id, $sender, $recipients, $comment); 238 } 239 240 /** 241 * show success message in ajax mode 242 */ 243 protected function ajaxSuccess() 244 { 245 echo '<form id="plugin__recommend" accept-charset="utf-8" method="post" action="?do=recommend">'; 246 echo '<div class="no">'; 247 echo '<span class="ui-icon ui-icon-circle-check" style="float: left; margin: 0 7px 50px 0;"></span>'; 248 echo '<p>' . $this->getLang('done') . '</p>'; 249 echo '<button type="reset" class="button">' . $this->getLang('close') . '</button>'; 250 echo '</div>'; 251 echo '</form>'; 252 } 253} 254