1<?php 2 3/** 4 * DokuWiki Plugin acknowledge (AJAX Action Component) 5 * 6 * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 7 * @author Andreas Gohr, Anna Dabrowska <dokuwiki@cosmocode.de> 8 */ 9 10use dokuwiki\Extension\ActionPlugin; 11use dokuwiki\Extension\EventHandler; 12use dokuwiki\Extension\Event; 13use dokuwiki\Form\Form; 14 15class action_plugin_acknowledge_ajax extends ActionPlugin 16{ 17 /** @inheritDoc */ 18 public function register(EventHandler $controller) 19 { 20 $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjaxAcknowledge'); 21 $controller->register_hook('AJAX_CALL_UNKNOWN', 'BEFORE', $this, 'handleAjaxAutocomplete'); 22 } 23 24 /** 25 * @param Event $event 26 * @param $param 27 */ 28 public function handleAjaxAcknowledge(Event $event, $param) 29 { 30 if ($event->data === 'plugin_acknowledge_acknowledge') { 31 $event->stopPropagation(); 32 $event->preventDefault(); 33 34 global $INPUT; 35 $id = $INPUT->str('id'); 36 37 if (page_exists($id)) { 38 echo $this->html(); 39 } 40 } 41 } 42 43 /** 44 * @param Event $event 45 * @return void 46 */ 47 public function handleAjaxAutocomplete(Event $event) 48 { 49 if ($event->data === 'plugin_acknowledge_autocomplete') { 50 if (!checkSecurityToken()) return; 51 52 global $INPUT; 53 54 $event->stopPropagation(); 55 $event->preventDefault(); 56 57 /** @var helper_plugin_acknowledge $hlp */ 58 $hlp = $this->loadHelper('acknowledge'); 59 60 $found = []; 61 62 if ($INPUT->has('user')) { 63 $search = $INPUT->str('user'); 64 $knownUsers = $hlp->getUsers(); 65 $found = array_filter($knownUsers, function ($user) use ($search) { 66 return (strstr(strtolower($user['label']), strtolower($search))) !== false ? $user : null; 67 }); 68 } 69 70 if ($INPUT->has('pg')) { 71 $search = $INPUT->str('pg'); 72 $pages = ft_pageLookup($search, true); 73 $found = array_map(function ($id, $title) { 74 return ['value' => $id, 'label' => $title ?? $id]; 75 }, array_keys($pages), array_values($pages)); 76 } 77 78 header('Content-Type: application/json'); 79 80 echo json_encode($found); 81 } 82 } 83 84 /** 85 * Returns the acknowledgment form/confirmation and optionally management report 86 * 87 * @return string The HTML to display 88 */ 89 protected function html() 90 { 91 global $INPUT; 92 $id = $INPUT->str('id'); 93 $user = $INPUT->server->str('REMOTE_USER'); 94 if ($id === '' || $user === '') return ''; 95 96 /** @var helper_plugin_acknowledge $helper */ 97 $helper = plugin_load('helper', 'acknowledge'); 98 99 return $this->bannerHtml($id, $user, $helper) . $this->reportHtml($id, $helper); 100 } 101 102 /** 103 * Returns the personal acknowledgement banner 104 * 105 * @param string $id 106 * @param string $user 107 * @param helper_plugin_acknowledge $helper 108 * @return string 109 */ 110 protected function bannerHtml($id, $user, helper_plugin_acknowledge $helper) 111 { 112 global $INPUT; 113 global $USERINFO; 114 115 // only display for users assigned to the page 116 if (!$helper->isUserAssigned($id, $user, $USERINFO['grps'])) { 117 return ''; 118 } 119 120 // if the approve plugin is active, only show if the page is approved 121 if ($helper->isBlockedByApprove($id)) { 122 return ''; 123 } 124 125 if ($INPUT->bool('ack')) { 126 $helper->saveAcknowledgement($id, $user); 127 } 128 129 $ack = $helper->hasUserAcknowledged($id, $user); 130 131 $html = '<div class="plugin-acknowledge-box ack' . ($ack ? ' done' : '') . '">'; 132 $html .= '<div class="ack-icon">'; 133 $html .= inlineSVG(__DIR__ . '/../admin.svg'); 134 $html .= '</div>'; 135 136 $html .= '<div class="content">'; 137 if ($ack) { 138 $html .= '<h4>'; 139 $html .= $this->getLang('ackOk'); 140 $html .= '</h4>'; 141 $html .= sprintf($this->getLang('ackGranted'), dformat($ack)); 142 } else { 143 $html .= '<h4>' . $this->getLang('ackRequired') . '</h4>'; 144 $latest = $helper->getLatestUserAcknowledgement($id, $user); 145 if ($latest) { 146 $html .= '<a href="' 147 . wl($id, ['do' => 'diff', 'at' => $latest], false, '&') . '">' 148 . sprintf($this->getLang('ackDiff'), dformat($latest)) 149 . '</a><br>'; 150 } 151 152 $form = new Form(['id' => 'ackForm']); 153 $form->addCheckbox('ack', $this->getLang('ackText'))->attr('required', 'required'); 154 $form->addHTML( 155 '<br><button type="submit" name="acksubmit" id="ack-submit">' 156 . $this->getLang('ackButton') 157 . '</button>' 158 ); 159 160 $html .= $form->toHTML(); 161 } 162 $html .= '</div>'; // content 163 $html .= '</div>'; // box 164 165 return $html; 166 } 167 168 /** 169 * Returns the manager/admin report box 170 * 171 * @param string $id 172 * @param helper_plugin_acknowledge $helper 173 * @return string 174 */ 175 protected function reportHtml($id, helper_plugin_acknowledge $helper) 176 { 177 $mode = $this->getConf('onpage_report'); 178 if ($mode === 'off') return ''; 179 180 if (!auth_ismanager()) return ''; 181 182 if (!$helper->getPageAssignees($id)) return ''; 183 184 $html = '<div class="plugin-acknowledge-box report">'; 185 186 $html .= '<div class="ack-icon">'; 187 $html .= inlineSVG(__DIR__ . '/../admin.svg'); 188 $html .= '</div>'; 189 190 $html .= '<div class="content">'; 191 $html .= '<h3>' . $this->getLang('reportTitle') . '</h3>'; 192 193 if ($mode === 'acknowledged' || $mode === 'both') { 194 $acked = $helper->getPageAcknowledgements($id, '', 'current'); 195 $html .= '<h4>' . $this->getLang('reportAcknowledgedTitle') . '</h4>'; 196 $html .= $this->userListHtml($acked); 197 } 198 199 if ($mode === 'pending' || $mode === 'both') { 200 $pending = $helper->getPageAcknowledgements($id, '', 'due'); 201 $html .= '<h4>' . $this->getLang('reportPendingTitle') . '</h4>'; 202 $html .= $this->userListHtml($pending); 203 } 204 205 $html .= '</div>'; // content 206 $html .= '</div>'; // box 207 208 return $html; 209 } 210 211 /** 212 * Renders a list of users from acknowledgement records. 213 * 214 * @param array $rows 215 * @return string 216 */ 217 protected function userListHtml($rows) 218 { 219 if (!$rows) { 220 return '<p>' . $this->getLang('reportNobody') . '</p>'; 221 } 222 223 $html = '<ul>'; 224 foreach ($rows as $row) { 225 $html .= '<li>'; 226 $html .= userlink($row['user']); 227 228 if (!empty($row['ack'])) { 229 $html .= ' ' . $this->getLang('reportAckedOn') . ' ' . hsc(dformat($row['ack'])); 230 } 231 $html .= '</li>'; 232 } 233 $html .= '</ul>'; 234 235 return $html; 236 } 237} 238