1ff9bc75fSJarrod Lowe<?php 2*f576111dSAndreas Gohr/** 3*f576111dSAndreas Gohr * DokuWiki Plugin publish (Syntax Component) 4*f576111dSAndreas Gohr * 5*f576111dSAndreas Gohr * @license GPL 2 http://www.gnu.org/licenses/gpl-2.0.html 6*f576111dSAndreas Gohr * @author Jarrod Lowe <dokuwiki@rrod.net> 7*f576111dSAndreas Gohr * @author Andreas Gohr <gohr@cosmocode.de> 8*f576111dSAndreas Gohr */ 9ff9bc75fSJarrod Lowe 10ff9bc75fSJarrod Lowe 11ff9bc75fSJarrod Lowe// must be run within DokuWiki 12ff9bc75fSJarrod Loweif(!defined('DOKU_INC')) die(); 13ff9bc75fSJarrod Lowe 14ff9bc75fSJarrod Lowe 15ff9bc75fSJarrod Loweclass syntax_plugin_publish extends DokuWiki_Syntax_Plugin { 16*f576111dSAndreas Gohr private $hlp; 17ff9bc75fSJarrod Lowe 18*f576111dSAndreas Gohr function syntax_plugin_publish(){ 19*f576111dSAndreas Gohr $this->hlp = plugin_load('helper','publish'); 20*f576111dSAndreas Gohr } 21ff9bc75fSJarrod Lowe 22ff9bc75fSJarrod Lowe function pattern() { return '\[APPROVALS.*?\]'; } 23ff9bc75fSJarrod Lowe function getType() { return 'substition'; } 24ff9bc75fSJarrod Lowe function getSort() { return 20; } 25ff9bc75fSJarrod Lowe function PType() { return 'block'; } 26ff9bc75fSJarrod Lowe function connectTo($mode) { $this->Lexer->addSpecialPattern($this->pattern(),$mode,'plugin_publish'); } 27ff9bc75fSJarrod Lowe function handle($match, $state, $pos, &$handler){ 28ff9bc75fSJarrod Lowe $namespace = substr($match, 11, -1); 29ff9bc75fSJarrod Lowe return array($match, $state, $pos, $namespace); 30ff9bc75fSJarrod Lowe } 31ff9bc75fSJarrod Lowe 32ff9bc75fSJarrod Lowe function render($mode, &$renderer, $data) { 33ff9bc75fSJarrod Lowe global $conf; 34ff9bc75fSJarrod Lowe 35ff9bc75fSJarrod Lowe if($mode == 'xhtml'){ 36*f576111dSAndreas Gohr $ns = cleanID(getNS($data[3] . ":*")); 37ff9bc75fSJarrod Lowe $dir = $conf['datadir'] . '/' . str_replace(':', '/', $ns); 38ff9bc75fSJarrod Lowe $pages = array(); 39*f576111dSAndreas Gohr search($pages, $dir, array($this,'search_helper'), array($ns, $this->getConf('apr_namespaces'))); 40ff9bc75fSJarrod Lowe if(count($pages) == 0) { 41ff9bc75fSJarrod Lowe $renderer->doc .= '<p class="apr_none">' . $this->getLang('apr_p_none') . '</p>'; 42ff9bc75fSJarrod Lowe return true; 43ff9bc75fSJarrod Lowe } 44*f576111dSAndreas Gohr usort($pages, array($this,'_pagesorter')); 45ff9bc75fSJarrod Lowe 46*f576111dSAndreas Gohr // Output Table 47ff9bc75fSJarrod Lowe $renderer->doc .= '<table class="apr_table"><tr class="apr_head">'; 48ff9bc75fSJarrod Lowe $renderer->doc .= '<th class="apr_page">' . $this->getLang('apr_p_hdr_page') . '</th>'; 49ff9bc75fSJarrod Lowe $renderer->doc .= '<th class="apr_prev">' . $this->getLang('apr_p_hdr_previous') . '</th>'; 50ff9bc75fSJarrod Lowe $renderer->doc .= '<th class="apr_upd">' . $this->getLang('apr_p_hdr_updated') . '</th>'; 51ff9bc75fSJarrod Lowe $renderer->doc .= '</tr>'; 52ff9bc75fSJarrod Lowe $working_ns = null; 53ff9bc75fSJarrod Lowe foreach($pages as $page) { 54*f576111dSAndreas Gohr // $page: 0 -> pagename, 1 -> approval metadata, 2 -> last changed date 55ff9bc75fSJarrod Lowe $this_ns = getNS($page[0]); 56ff9bc75fSJarrod Lowe if($this_ns != $working_ns) { 57ff9bc75fSJarrod Lowe $name_ns = $this_ns; 58ff9bc75fSJarrod Lowe if($this_ns == '') { $name_ns = 'root'; } 59ff9bc75fSJarrod Lowe $renderer->doc .= '<tr class="apr_ns"><td colspan="3"><a href="'; 60ff9bc75fSJarrod Lowe $renderer->doc .= wl($this_ns . ':' . $this->getConf('start')); 61ff9bc75fSJarrod Lowe $renderer->doc .= '">'; 62ff9bc75fSJarrod Lowe $renderer->doc .= $name_ns; 63ff9bc75fSJarrod Lowe $renderer->doc .= '</a></td></tr>'; 64ff9bc75fSJarrod Lowe $working_ns = $this_ns; 65ff9bc75fSJarrod Lowe } 66ff9bc75fSJarrod Lowe $updated = '<a href="' . wl($page[0]) . '">' . date('d/m/Y H:i', $page[2]) . '</a>'; 67ff9bc75fSJarrod Lowe if($page[1] == null || count($page[1]) == 0) { 68*f576111dSAndreas Gohr // Has never been approved 69ff9bc75fSJarrod Lowe $approved = ''; 70ff9bc75fSJarrod Lowe }else{ 71ff9bc75fSJarrod Lowe $keys = array_keys($page[1]); 72ff9bc75fSJarrod Lowe sort($keys); 73ff9bc75fSJarrod Lowe $last = $keys[count($keys)-1]; 74ff9bc75fSJarrod Lowe $approved .= sprintf($this->getLang('apr_p_approved'), 75ff9bc75fSJarrod Lowe $page[1][$last][1], 76ff9bc75fSJarrod Lowe wl($page[0], 'rev=' . $last), 77ff9bc75fSJarrod Lowe date('d/m/Y H:i', $last)); 78ff9bc75fSJarrod Lowe if($last == $page[2]) { $updated = 'Unchanged'; } //shouldn't be possible: 79ff9bc75fSJarrod Lowe //the search_helper should have 80ff9bc75fSJarrod Lowe //excluded this 81ff9bc75fSJarrod Lowe } 82ff9bc75fSJarrod Lowe 83ff9bc75fSJarrod Lowe $renderer->doc .= '<tr class="apr_table'; 84ff9bc75fSJarrod Lowe if($approved == '') { $renderer->doc .= ' apr_never'; } 85ff9bc75fSJarrod Lowe $renderer->doc .= '"><td class="apr_page"><a href="'; 86ff9bc75fSJarrod Lowe $renderer->doc .= wl($page[0]); 87ff9bc75fSJarrod Lowe $renderer->doc .= '">'; 88ff9bc75fSJarrod Lowe $renderer->doc .= $page[0]; 89ff9bc75fSJarrod Lowe $renderer->doc .= '</a></td><td class="apr_prev">'; 90ff9bc75fSJarrod Lowe $renderer->doc .= $approved; 91ff9bc75fSJarrod Lowe $renderer->doc .= '</td><td class="apr_upd">'; 92ff9bc75fSJarrod Lowe $renderer->doc .= $updated; 93ff9bc75fSJarrod Lowe $renderer->doc .= '</td></tr>'; 94ff9bc75fSJarrod Lowe 95*f576111dSAndreas Gohr //$renderer->doc .= '<tr><td colspan="3">' . print_r($page, true) . '</td></tr>'; 96ff9bc75fSJarrod Lowe } 97ff9bc75fSJarrod Lowe $renderer->doc .= '</table>'; 98ff9bc75fSJarrod Lowe return true; 99ff9bc75fSJarrod Lowe } 100ff9bc75fSJarrod Lowe return false; 101ff9bc75fSJarrod Lowe } 102ff9bc75fSJarrod Lowe 103*f576111dSAndreas Gohr /** 104*f576111dSAndreas Gohr * search callback function 105*f576111dSAndreas Gohr * 106*f576111dSAndreas Gohr * filter out pages which can't be approved by the current user 107*f576111dSAndreas Gohr * then check if they need approving 108*f576111dSAndreas Gohr */ 109*f576111dSAndreas Gohr function _search_helper(&$data, $base, $file, $type, $lvl, $opts) { 110*f576111dSAndreas Gohr $ns = $opts[0]; 111*f576111dSAndreas Gohr $valid_ns = $opts[1]; 112*f576111dSAndreas Gohr if($type == 'd') { return $this->hlp->in_sub_namespace($valid_ns, $ns . ':' . str_replace('/', ':', $file)); } 113*f576111dSAndreas Gohr if(!preg_match('#\.txt$#', $file)) { return false; } 114*f576111dSAndreas Gohr $id = pathID($ns . $file); 115*f576111dSAndreas Gohr if(!in_namespace($valid_ns, $id)) { return false; } 116*f576111dSAndreas Gohr if(auth_quickaclcheck($id) < AUTH_DELETE) { return false; } //insufficent permissions 117*f576111dSAndreas Gohr $meta = p_get_metadata($id); 118*f576111dSAndreas Gohr if($meta['approval'][$meta['last_change']['date']]) { 119*f576111dSAndreas Gohr // Already approved 120*f576111dSAndreas Gohr return false; 121*f576111dSAndreas Gohr } 122*f576111dSAndreas Gohr $data[] = array($id, $meta['approval'], $meta['last_change']['date']); 123*f576111dSAndreas Gohr return false; 124*f576111dSAndreas Gohr } 125*f576111dSAndreas Gohr 126*f576111dSAndreas Gohr /** 127*f576111dSAndreas Gohr * Custom sort callback 128*f576111dSAndreas Gohr */ 129*f576111dSAndreas Gohr function _pagesorter($a, $b){ 130*f576111dSAndreas Gohr $ac = explode(':',$a[0]); 131*f576111dSAndreas Gohr $bc = explode(':',$b[0]); 132*f576111dSAndreas Gohr $an = count($ac); 133*f576111dSAndreas Gohr $bn = count($bc); 134*f576111dSAndreas Gohr 135*f576111dSAndreas Gohr // Same number of elements, can just string sort 136*f576111dSAndreas Gohr if($an == $bn) { return strcmp($a[0], $b[0]); } 137*f576111dSAndreas Gohr 138*f576111dSAndreas Gohr // For each level: 139*f576111dSAndreas Gohr // If this is not the last element in either list: 140*f576111dSAndreas Gohr // same -> continue 141*f576111dSAndreas Gohr // otherwise strcmp 142*f576111dSAndreas Gohr // If this is the last element in either list, it wins 143*f576111dSAndreas Gohr $n = 0; 144*f576111dSAndreas Gohr while(true) { 145*f576111dSAndreas Gohr if($n + 1 == $an) { return -1; } 146*f576111dSAndreas Gohr if($n + 1 == $bn) { return 1; } 147*f576111dSAndreas Gohr $s = strcmp($ac[$n], $bc[$n]); 148*f576111dSAndreas Gohr if($s != 0) { return $s; } 149*f576111dSAndreas Gohr $n += 1; 150*f576111dSAndreas Gohr } 151*f576111dSAndreas Gohr } 152ff9bc75fSJarrod Lowe 153ff9bc75fSJarrod Lowe 154ff9bc75fSJarrod Lowe} 155ff9bc75fSJarrod Lowe 156