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 echo '<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 echo '<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_db $db */ 50 $db = $this->loadHelper('approve_db'); 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_db $db */ 77 $db = $this->loadHelper('approve_db'); 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_db $db */ 98 $db = $this->loadHelper('approve_db'); 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_db $db */ 122 $db = $this->loadHelper('approve_db'); 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 if ($event->data != 'show' || !$INFO['exists']) return; 142 143 /* Return true if banner should not be displayed for users with or below read only permission. */ 144 if (auth_quickaclcheck($INFO['id']) <= AUTH_READ && !$this->getConf('display_banner_for_readonly')) { 145 return; 146 } 147 148 /** @var helper_plugin_approve_acl $acl */ 149 $acl = $this->loadHelper('approve_acl'); 150 if (!$acl->useApproveHere($INFO['id'])) return; 151 152 $last_change_date = @filemtime(wikiFN($INFO['id'])); 153 $rev = !$INFO['rev'] ? $last_change_date : $INFO['rev']; 154 155 156 /** @var helper_plugin_approve_db $db */ 157 $db = $this->loadHelper('approve_db'); 158 159 $page_revision = $db->getPageRevision($INFO['id'], $rev); 160 $last_approved_rev = $db->getLastDbRev($INFO['id'], 'approved'); 161 162 $classes = []; 163 if ($page_revision['status'] == 'approved' && $rev == $last_approved_rev) { 164 $classes[] = 'plugin__approve_approved'; 165 } elseif ($page_revision['status'] == 'approved') { 166 $classes[] = 'plugin__approve_old_approved'; 167 } elseif ($this->getConf('ready_for_approval') && $page_revision['status'] == 'ready_for_approval') { 168 $classes[] = 'plugin__approve_ready'; 169 } else { 170 $classes[] = 'plugin__approve_draft'; 171 } 172 173 echo '<div id="plugin__approve" class="' . implode(' ', $classes) . '">'; 174 175 176 if ($page_revision['status'] == 'approved') { 177 echo '<strong>'.$this->getLang('approved').'</strong>'; 178 echo ' ' . dformat(strtotime($page_revision['approved'])); 179 180 if($this->getConf('banner_long')) { 181 echo ' ' . $this->getLang('by') . ' ' . userlink($page_revision['approved_by'], true); 182 echo ' (' . $this->getLang('version') . ': ' . $page_revision['version'] . ')'; 183 } 184 185 //not the newest page 186 if ($rev != $last_change_date) { 187 // we can see drafts 188 if ($acl->clientCanSeeDrafts($INFO['id'])) { 189 echo ' <a href="' . wl($INFO['id']) . '">'; 190 echo $this->getLang($last_approved_rev == $last_change_date ? 'newest_approved' : 'newest_draft'); 191 echo '</a>'; 192 // we cannot see link to draft but there is some newer approved version 193 } elseif ($last_approved_rev != $rev) { 194 $urlParameters = []; 195 if ($last_approved_rev != $last_change_date) { 196 $urlParameters['rev'] = $last_approved_rev; 197 } 198 echo ' <a href="' . wl($INFO['id'], $urlParameters) . '">'; 199 echo $this->getLang('newest_approved'); 200 echo '</a>'; 201 } 202 } 203 204 } else { 205 if ($this->getConf('ready_for_approval') && $page_revision['status'] == 'ready_for_approval') { 206 echo '<strong>'.$this->getLang('marked_approve_ready').'</strong>'; 207 echo ' ' . dformat(strtotime($page_revision['ready_for_approval'])); 208 echo ' ' . $this->getLang('by') . ' ' . userlink($page_revision['ready_for_approval_by'], true); 209 } else { 210 echo '<strong>'.$this->getLang('draft').'</strong>'; 211 } 212 213 // not exists approve for current page 214 if ($last_approved_rev == null) { 215 // not the newest page 216 if ($rev != $last_change_date) { 217 echo ' <a href="'.wl($INFO['id']).'">'; 218 echo $this->getLang('newest_draft'); 219 echo '</a>'; 220 } 221 } else { 222 $urlParameters = []; 223 if ($last_approved_rev != $last_change_date) { 224 $urlParameters['rev'] = $last_approved_rev; 225 } 226 echo ' <a href="' . wl($INFO['id'], $urlParameters) . '">'; 227 echo $this->getLang('newest_approved'); 228 echo '</a>'; 229 } 230 231 //we are in current page 232 if ($rev == $last_change_date) { 233 if ($this->getConf('ready_for_approval') && 234 $acl->clientCanMarkReadyForApproval($INFO['id']) && 235 $page_revision['status'] != 'ready_for_approval') { 236 237 $urlParameters = [ 238 'rev' => $last_approved_rev, 239 'do' => 'diff', 240 'ready_for_approval' => 'ready_for_approval' 241 ]; 242 echo ' | <a href="'.wl($INFO['id'], $urlParameters).'">'; 243 echo $this->getLang('approve_ready'); 244 echo '</a>'; 245 } 246 247 if ($acl->clientCanApprove($INFO['id'])) { 248 $urlParameters = [ 249 'rev' => $last_approved_rev, 250 'do' => 'diff', 251 'approve' => 'approve' 252 ]; 253 echo ' | <a href="'.wl($INFO['id'], $urlParameters).'">'; 254 echo $this->getLang('approve'); 255 echo '</a>'; 256 } 257 } 258 } 259 260 261 if ($this->getConf('banner_long')) { 262 $page_metadata = $db->getPageMetadata($INFO['id']); 263 if (isset($page_metadata['approver'])) { 264 echo ' | ' . $this->getLang('approver') . ': ' . userlink($page_metadata['approver'], true); 265 } 266 } 267 268 echo '</div>'; 269 } 270 271 /** 272 * 273 * @param Event $event 274 */ 275 public function handle_pagesave_after(Event $event) { 276 //no content was changed 277 if (!$event->data['contentChanged']) return; 278 279 /** @var helper_plugin_approve_db $db */ 280 $db = $this->loadHelper('approve_db'); 281 282 $id = $event->data['id']; 283 switch ($event->data['changeType']) { 284 case DOKU_CHANGE_TYPE_CREATE: 285 case DOKU_CHANGE_TYPE_EDIT: 286 case DOKU_CHANGE_TYPE_MINOR_EDIT: 287 case DOKU_CHANGE_TYPE_REVERT: 288 $db->handlePageEdit($id); 289 break; 290 case DOKU_CHANGE_TYPE_DELETE: 291 $db->handlePageDelete($id); 292 break; 293 } 294 } 295} 296