1<?php 2 3use dokuwiki\Extension\ActionPlugin; 4use dokuwiki\Extension\EventHandler; 5use dokuwiki\Extension\Event; 6 7class action_plugin_approve_approve extends ActionPlugin { 8 /** 9 * @inheritDoc 10 */ 11 public function register(EventHandler $controller) { 12 $controller->register_hook('TPL_ACT_RENDER', 'AFTER', $this, 'handle_diff_accept'); 13 $controller->register_hook('HTML_SHOWREV_OUTPUT', 'BEFORE', $this, 'handle_showrev'); 14 $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_approve'); 15 $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_mark_ready_for_approval'); 16 $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_viewer'); 17 $controller->register_hook('TPL_ACT_RENDER', 'BEFORE', $this, 'handle_display_banner'); 18 $controller->register_hook('COMMON_WIKIPAGE_SAVE', 'AFTER', $this, 'handle_pagesave_after'); 19 } 20 21 /** 22 * @param Event $event 23 */ 24 public function handle_diff_accept(Event $event) { 25 global $INFO; 26 27 /** @var helper_plugin_approve_acl $acl */ 28 $acl = $this->loadHelper('approve_acl'); 29 30 if (!$acl->useApproveHere($INFO['id'])) return; 31 32 if ($event->data == 'diff' && isset($_GET['approve'])) { 33 $href = wl($INFO['id'], ['approve' => 'approve']); 34 ptln('<a href="' . $href . '">'.$this->getLang('approve').'</a>'); 35 } 36 37 if ($this->getConf('ready_for_approval') && $event->data == 'diff' && isset($_GET['ready_for_approval'])) { 38 $href = wl($INFO['id'], ['ready_for_approval' => 'ready_for_approval']); 39 ptln('<a href="' . $href . '">'.$this->getLang('approve_ready').'</a>'); 40 } 41 } 42 43 /** 44 * @param Event $event 45 */ 46 public function handle_showrev(Event $event) { 47 global $INFO; 48 49 /** @var helper_plugin_approve_data $db */ 50 $db = $this->loadHelper('approve_data'); 51 /** @var helper_plugin_approve_acl $acl */ 52 $acl = $this->loadHelper('approve_acl'); 53 54 if (!$acl->useApproveHere($INFO['id'])) return; 55 56 $last_approved_rev = $db->getLastDbRev($INFO['id'], 'approved'); 57 if ($last_approved_rev == $INFO['rev']) { 58 $event->preventDefault(); 59 } 60 } 61 62 /** 63 * @param Event $event 64 */ 65 public function handle_approve(Event $event) { 66 global $INFO; 67 68 /** @var helper_plugin_approve_acl $acl */ 69 $acl = $this->loadHelper('approve_acl'); 70 71 if ($event->data != 'show') return; 72 if (!isset($_GET['approve'])) return; 73 if (!$acl->useApproveHere($INFO['id'])) return; 74 if (!$acl->clientCanApprove($INFO['id'])) return; 75 76 /** @var helper_plugin_approve_data $db */ 77 $db = $this->loadHelper('approve_data'); 78 $db->setApprovedStatus($INFO['id']); 79 80 header('Location: ' . wl($INFO['id'])); 81 } 82 83 /** 84 * @param Event $event 85 */ 86 public function handle_mark_ready_for_approval(Event $event) { 87 global $INFO; 88 89 /** @var helper_plugin_approve_acl $acl */ 90 $acl = $this->loadHelper('approve_acl'); 91 92 if ($event->data != 'show') return; 93 if (!isset($_GET['ready_for_approval'])) return; 94 if (!$acl->useApproveHere($INFO['id'])) return; 95 if (!$acl->clientCanMarkReadyForApproval($INFO['id'])) return; 96 97 /** @var helper_plugin_approve_data $db */ 98 $db = $this->loadHelper('approve_data'); 99 $db->setReadyForApprovalStatus($INFO['id']); 100 101 header('Location: ' . wl($INFO['id'])); 102 } 103 104 /** 105 * Redirect to latest approved page for user that don't have EDIT permission. 106 * 107 * @param Event $event 108 */ 109 public function handle_viewer(Event $event) { 110 global $INFO; 111 112 /** @var helper_plugin_approve_acl $acl */ 113 $acl = $this->loadHelper('approve_acl'); 114 115 if ($event->data != 'show') return; 116 //apply only to current page 117 if ($INFO['rev'] != 0) return; 118 if (!$acl->useApproveHere($INFO['id'])) return; 119 if ($acl->clientCanSeeDrafts($INFO['id'])) return; 120 121 /** @var helper_plugin_approve_data $db */ 122 $db = $this->loadHelper('approve_data'); 123 $last_approved_rev = $db->getLastDbRev($INFO['id'], 'approved'); 124 125 //no page is approved 126 if (!$last_approved_rev) return; 127 128 $last_change_date = @filemtime(wikiFN($INFO['id'])); 129 // current page is approved 130 if ($last_approved_rev == $last_change_date) return; 131 132 header("Location: " . wl($INFO['id'], ['rev' => $last_approved_rev], false, '&')); 133 } 134 135 /** 136 * @param Event $event 137 */ 138 public function handle_display_banner(Event $event) { 139 global $INFO; 140 141 /** @var helper_plugin_approve_acl $acl */ 142 $acl = $this->loadHelper('approve_acl'); 143 if (!$acl->useApproveHere($INFO['id'])) return; 144 145 $last_change_date = @filemtime(wikiFN($INFO['id'])); 146 $rev = !$INFO['rev'] ? $last_change_date : $INFO['rev']; 147 148 149 /** @var helper_plugin_approve_data $db */ 150 $db = $this->loadHelper('approve_data'); 151 152 $page_revision = $db->getPageRevision($INFO['id'], $rev); 153 $last_approved_rev = $db->getLastDbRev($INFO['id'], 'approved'); 154 155 $classes = []; 156 if ($page_revision['status'] == 'approved' && $rev == $last_approved_rev) { 157 $classes[] = 'plugin__approve_approved'; 158 } elseif ($page_revision['status'] == 'approved') { 159 $classes[] = 'plugin__approve_old_approved'; 160 } elseif ($this->getConf('ready_for_approval') && $page_revision['status'] == 'ready_for_approval') { 161 $classes[] = 'plugin__approve_ready'; 162 } else { 163 $classes[] = 'plugin__approve_draft'; 164 } 165 166 ptln('<div id="plugin__approve" class="' . implode(' ', $classes) . '">'); 167 168 169 if ($page_revision['status'] == 'approved') { 170 ptln('<strong>'.$this->getLang('approved').'</strong>'); 171 ptln(' ' . dformat(strtotime($page_revision['approved']))); 172 173 if($this->getConf('banner_long')) { 174 ptln(' ' . $this->getLang('by') . ' ' . userlink($page_revision['approved_by'], true)); 175 ptln(' (' . $this->getLang('version') . ': ' . $page_revision['version'] . ')'); 176 } 177 178 //not the newest page 179 if ($rev != $last_change_date) { 180 // we can see drafts 181 if ($acl->clientCanSeeDrafts($INFO['id'])) { 182 ptln('<a href="' . wl($INFO['id']) . '">'); 183 ptln($this->getLang($last_approved_rev == $last_change_date ? 'newest_approved' : 'newest_draft')); 184 ptln('</a>'); 185 // we cannot see link to draft but there is some newer approved version 186 } elseif ($last_approved_rev != $rev) { 187 $urlParameters = []; 188 if ($last_approved_rev != $last_change_date) { 189 $urlParameters['rev'] = $last_approved_rev; 190 } 191 ptln('<a href="' . wl($INFO['id'], $urlParameters) . '">'); 192 ptln($this->getLang('newest_approved')); 193 ptln('</a>'); 194 } 195 } 196 197 } else { 198 if ($this->getConf('ready_for_approval') && $page_revision['status'] == 'ready_for_approval') { 199 ptln('<strong>'.$this->getLang('marked_approve_ready').'</strong>'); 200 ptln(' ' . dformat(strtotime($page_revision['ready_for_approval']))); 201 ptln(' ' . $this->getLang('by') . ' ' . userlink($page_revision['ready_for_approval_by'], true)); 202 } else { 203 ptln('<strong>'.$this->getLang('draft').'</strong>'); 204 } 205 206 // not exists approve for current page 207 if ($last_approved_rev == null) { 208 // not the newest page 209 if ($rev != $last_change_date) { 210 ptln('<a href="'.wl($INFO['id']).'">'); 211 ptln($this->getLang('newest_draft')); 212 ptln('</a>'); 213 } 214 } else { 215 $urlParameters = []; 216 if ($last_approved_rev != $last_change_date) { 217 $urlParameters['rev'] = $last_approved_rev; 218 } 219 ptln('<a href="' . wl($INFO['id'], $urlParameters) . '">'); 220 ptln($this->getLang('newest_approved')); 221 ptln('</a>'); 222 } 223 224 //we are in current page 225 if ($rev == $last_change_date) { 226 if ($this->getConf('ready_for_approval') && 227 $acl->clientCanMarkReadyForApproval($INFO['id']) && 228 $page_revision['status'] != 'ready_for_approval') { 229 230 $urlParameters = [ 231 'rev' => $last_approved_rev, 232 'do' => 'diff', 233 'ready_for_approval' => 'ready_for_approval' 234 ]; 235 ptln(' | <a href="'.wl($INFO['id'], $urlParameters).'">'); 236 ptln($this->getLang('approve_ready')); 237 ptln('</a>'); 238 } 239 240 if ($acl->clientCanApprove($INFO['id'])) { 241 $urlParameters = [ 242 'rev' => $last_approved_rev, 243 'do' => 'diff', 244 'approve' => 'approve' 245 ]; 246 ptln(' | <a href="'.wl($INFO['id'], $urlParameters).'">'); 247 ptln($this->getLang('approve')); 248 ptln('</a>'); 249 } 250 } 251 } 252 253 if (isset($page_metadata['approver']) & $this->getConf('banner_long')) { 254 ptln(' | ' . $this->getLang('approver') . ': ' . userlink($page_metadata['approver'], true)); 255 } 256 257 ptln('</div>'); 258 } 259 260 /** 261 * 262 * @param Event $event 263 */ 264 public function handle_pagesave_after(Event $event) { 265 //no content was changed 266 if (!$event->data['contentChanged']) return; 267 268 /** @var helper_plugin_approve_data $db */ 269 $db = $this->loadHelper('approve_data'); 270 271 $id = $event->data['id']; 272 switch ($event->data['changeType']) { 273 case DOKU_CHANGE_TYPE_CREATE: 274 case DOKU_CHANGE_TYPE_EDIT: 275 case DOKU_CHANGE_TYPE_MINOR_EDIT: 276 case DOKU_CHANGE_TYPE_REVERT: 277 $db->handlePageEdit($id); 278 break; 279 case DOKU_CHANGE_TYPE_DELETE: 280 $db->handlePageDelete($id); 281 break; 282 } 283 } 284} 285