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