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