1<?php 2 3if(!defined('DOKU_INC')) die(); 4define(APPROVED, 'Approved'); 5 6define(METADATA_VERSIONS_KEY, 'plugin_approve_versions'); 7 8class action_plugin_approve_approve extends DokuWiki_Action_Plugin { 9 10 private $hlp; 11 function __construct(){ 12 $this->hlp = plugin_load('helper', 'approve'); 13 } 14 15 function register(Doku_Event_Handler $controller) { 16 17 $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_approve', array()); 18 $controller->register_hook('ACTION_ACT_PREPROCESS', 'BEFORE', $this, 'handle_viewer', array()); 19 $controller->register_hook('TPL_ACT_RENDER', 'AFTER', $this, 'handle_diff_accept', array()); 20 $controller->register_hook('TPL_ACT_RENDER', 'BEFORE', $this, 'handle_display_banner', array()); 21 $controller->register_hook('HTML_SHOWREV_OUTPUT', 'BEFORE', $this, 'handle_showrev', array()); 22 // ensure a page revision is created when summary changes: 23 $controller->register_hook('COMMON_WIKIPAGE_SAVE', 'BEFORE', $this, 'handle_pagesave_before'); 24 $controller->register_hook('COMMON_WIKIPAGE_SAVE', 'AFTER', $this, 'handle_pagesave_after'); 25 } 26 27 function handle_diff_accept(Doku_Event $event, $param) { 28 global $ID; 29 30 if ($this->hlp->in_namespace($this->getConf('no_apr_namespaces'), $ID)) return; 31 32 if ($event->data == 'diff' && isset($_GET['approve'])) { 33 ptln('<a href="'.DOKU_URL.'doku.php?id='.$_GET['id'].'&approve=approve">'.$this->getLang('approve').'</a>'); 34 } 35 } 36 37 function handle_showrev(Doku_Event $event, $param) { 38 global $REV; 39 40 $last = $this->find_lastest_approved(); 41 if ($last == $REV) 42 $event->preventDefault(); 43 } 44 45 function can_approve() { 46 global $ID; 47 return auth_quickaclcheck($ID) >= AUTH_DELETE; 48 } 49 50 function handle_approve(Doku_Event $event, $param) { 51 global $ID; 52 53 if ($this->hlp->in_namespace($this->getConf('no_apr_namespaces'), $ID)) return; 54 55 if ($event->data == 'show' && isset($_GET['approve'])) { 56 if ( ! $this->can_approve()) return; 57 58 //create new page revison 59 saveWikiText($ID, rawWiki($ID), APPROVED); 60 61 header('Location: ?id='.$ID); 62 } 63 } 64 65 function handle_viewer(Doku_Event $event, $param) { 66 global $REV, $ID; 67 if ($event->data != 'show') return; 68 if (auth_quickaclcheck($ID) > AUTH_READ || ($this->hlp->in_namespace($this->getConf('no_apr_namespaces'), $ID))) return; 69 70 $last = $this->find_lastest_approved(); 71 //no page is approved 72 if ($last == -1) return; 73 //approved page is the newest page 74 if ($last == 0) return; 75 76 //if we are viewing lastest revision, show last approved 77 if ($REV == 0) header("Location: ?id=$ID&rev=$last"); 78 } 79 80 function find_lastest_approved() { 81 global $ID; 82 $m = p_get_metadata($ID); 83 $sum = $m['last_change']['sum']; 84 if ($sum == APPROVED) 85 return 0; 86 87 $changelog = new PageChangeLog($ID); 88 //wyszukaj najnowszej zatwierdzonej 89 //poszukaj w dół 90 $chs = $changelog->getRevisions(0, 10000); 91 foreach ($chs as $rev) { 92 $ch = $changelog->getRevisionInfo($rev); 93 if ($ch['sum'] == APPROVED) 94 return $rev; 95 } 96 return -1; 97 } 98 99 function handle_display_banner(Doku_Event $event, $param) { 100 global $ID, $REV, $INFO; 101 102 if ($this->hlp->in_namespace($this->getConf('no_apr_namespaces'), $ID)) return; 103 if ($event->data != 'show') return; 104 if (!$INFO['exists']) return; 105 106 $sum = $this->hlp->page_sum($ID, $REV); 107 108 109 $classes = array(); 110 if ($this->getConf('prettyprint')) { 111 $classes[] = 'plugin__approve_noprint'; 112 } 113 114 if ($sum == APPROVED) { 115 $classes[] = 'plugin__approve_green'; 116 } else { 117 $classes[] = 'plugin__approve_red'; 118 } 119 120 ptln('<div id="plugin__approve" class="' . implode(' ', $classes) . '">'); 121 122 tpl_pageinfo(); 123 ptln(' | '); 124 $last_approved_rev = $this->find_lastest_approved(); 125 if ($sum == APPROVED) { 126 $versions = p_get_metadata($ID, METADATA_VERSIONS_KEY); 127 if (!$versions) { 128 $versions = $this->render_metadata_for_approved_page($ID); 129 } 130 if (empty($REV)) { 131 $version = $versions[0]; 132 } else { 133 $version = $versions[$REV]; 134 } 135 136 ptln('<strong>'.$this->getLang('approved').'</strong> (' . $this->getLang('version') . ': ' . $version 137 . ')'); 138 if ($REV != 0 && auth_quickaclcheck($ID) > AUTH_READ) { 139 ptln('<a href="'.wl($ID).'">'); 140 ptln($this->getLang(p_get_metadata($ID, 'last_change sum') == APPROVED ? 'newest_approved' : 'newest_draft')); 141 ptln('</a>'); 142 } else if ($REV != 0 && $REV != $last_approved_rev) { 143 ptln('<a href="'.wl($ID).'">'); 144 ptln($this->getLang('newest_approved')); 145 ptln('</a>'); 146 } 147 } else { 148 ptln('<span>'.$this->getLang('draft').'</span>'); 149 150 if ($last_approved_rev == -1) { 151 if ($REV != 0) { 152 ptln('<a href="'.wl($ID).'">'); 153 ptln($this->getLang('newest_draft')); 154 ptln('</a>'); 155 } 156 } else { 157 if ($last_approved_rev != 0) 158 ptln('<a href="'.wl($ID, array('rev' => $last_approved_rev)).'">'); 159 else 160 ptln('<a href="'.wl($ID).'">'); 161 162 ptln($this->getLang('newest_approved')); 163 ptln('</a>'); 164 } 165 166 //można zatwierdzać tylko najnowsze strony 167 if ($REV == 0 && $this->can_approve()) { 168 ptln('<a href="'.wl($ID, array('rev' => $last_approved_rev, 'do' => 'diff', 169 'approve' => 'approve')).'">'); 170 ptln($this->getLang('approve')); 171 ptln('</a>'); 172 } 173 } 174 ptln('</div>'); 175 } 176 177 /** 178 * Check if the page has to be changed 179 * 180 * @param Doku_Event $event event object by reference 181 * @param mixed $param [the parameters passed as fifth argument to register_hook() when this 182 * handler was registered] 183 * @return void 184 */ 185 public function handle_pagesave_before(Doku_Event $event, $param) { 186 global $REV; 187 $id = $event->data['id']; 188 if ($this->hlp->in_namespace($this->getConf('no_apr_namespaces'), $id)) return; 189 190 //save page if summary is provided 191 if($event->data['summary'] == APPROVED) { 192 $event->data['contentChanged'] = true; 193 } 194 } 195 196 /** 197 * @param Doku_Event $event 198 * @param $param 199 */ 200 public function handle_pagesave_after(Doku_Event $event, $param) { 201 global $REV; 202 $id = $event->data['id']; 203 if ($this->hlp->in_namespace($this->getConf('no_apr_namespaces'), $id)) return; 204 205 //save page if summary is provided 206 if($event->data['summary'] == APPROVED) { 207 208 $versions = p_get_metadata($id, METADATA_VERSIONS_KEY); 209 //calculate versions 210 if (!$versions) { 211 $this->render_metadata_for_approved_page($id, $event->data['newRevision']); 212 } else { 213 $curver = $versions[0] + 1; 214 $versions[0] = $curver; 215 $versions[$event->data['newRevision']] = $curver; 216 p_set_metadata($id, array(METADATA_VERSIONS_KEY => $versions)); 217 } 218 } 219 } 220 221 222 /** 223 * Calculate current version 224 * 225 * @param $id 226 * @return int 227 */ 228 protected function render_metadata_for_approved_page($id, $currev=false) { 229 if (!$currev) $currev = @filemtime(wikiFN($id)); 230 231 $version = $this->approved($id); 232 //version for current page 233 $curver = $version + 1; 234 $versions = array(0 => $curver, $currev => $curver); 235 236 $changelog = new PageChangeLog($id); 237 $first = 0; 238 $num = 100; 239 while (count($revs = $changelog->getRevisions($first, $num)) > 0) { 240 foreach ($revs as $rev) { 241 $revInfo = $changelog->getRevisionInfo($rev); 242 if ($revInfo['sum'] == APPROVED) { 243 $versions[$rev] = $version; 244 $version -= 1; 245 } 246 } 247 $first += $num; 248 } 249 250 p_set_metadata($id, array(METADATA_VERSIONS_KEY => $versions)); 251 252 return $versions; 253 } 254 255 /** 256 * Get the number of approved pages 257 * @param $id 258 * @return int 259 */ 260 protected function approved($id) { 261 $count = 0; 262 263 $changelog = new PageChangeLog($id); 264 $first = 0; 265 $num = 100; 266 while (count($revs = $changelog->getRevisions($first, $num)) > 0) { 267 foreach ($revs as $rev) { 268 $revInfo = $changelog->getRevisionInfo($rev); 269 if ($revInfo['sum'] == APPROVED) { 270 $count += 1; 271 } 272 } 273 $first += $num; 274 } 275 276 return $count; 277 } 278} 279