1<?php 2/** 3 * Include Plugin: Display a wiki page within another wiki page 4 * 5 * Action plugin component, for cache validity determination 6 * 7 * @license GPL 2 (http://www.gnu.org/licenses/gpl.html) 8 * @author Christopher Smith <chris@jalakai.co.uk> 9 */ 10if(!defined('DOKU_INC')) die(); // no Dokuwiki, no go 11 12if(!defined('DOKU_PLUGIN')) define('DOKU_PLUGIN',DOKU_INC.'lib/plugins/'); 13require_once(DOKU_PLUGIN.'action.php'); 14 15/** 16 * All DokuWiki plugins to extend the parser/rendering mechanism 17 * need to inherit from this class 18 */ 19class action_plugin_include extends DokuWiki_Action_Plugin { 20 21 var $supportedModes = array('xhtml'); 22 23 /** 24 * return some info 25 */ 26 function getInfo() { 27 return array( 28 'author' => 'Gina Häußge, Michael Klier, Christopher Smith', 29 'email' => 'dokuwiki@chimeric.de', 30 'date' => '2008-04-20', 31 'name' => 'Include Plugin', 32 'desc' => 'Improved cache handling for included pages', 33 'url' => 'http://wiki.splitbrain.org/plugin:include', 34 ); 35 } 36 37 /** 38 * plugin should use this method to register its handlers with the dokuwiki's event controller 39 */ 40 function register(&$controller) { 41 $controller->register_hook('PARSER_CACHE_USE','BEFORE', $this, '_cache_prepare'); 42# $controller->register_hook('PARSER_CACHE_USE','AFTER', $this, '_cache_result'); // debugging only 43 } 44 45 /** 46 * prepare the cache object for default _useCache action 47 */ 48 function _cache_prepare(&$event, $param) { 49 $cache =& $event->data; 50 51 // we're only interested in wiki pages and supported render modes 52 if (!isset($cache->page)) return; 53 if (!isset($cache->mode) || !in_array($cache->mode, $this->supportedModes)) return; 54 55 $key = ''; 56 $depends = array(); 57 $expire = $this->_inclusion_check($cache->page, $key, $depends); 58 59# global $debug; 60# $debug[] = compact('key','expire','depends','cache'); 61 62 // empty $key implies no includes, so nothing to do 63 if (empty($key)) return; 64 65 // mark the cache as being modified by the include plugin 66 $cache->include = true; 67 68 // set new cache key & cache name - now also dependent on included page ids and their ACL_READ status 69 $cache->key .= $key; 70 $cache->cache = getCacheName($cache->key, $cache->ext); 71 72 // inclusion check was able to determine the cache must be invalid 73 if ($expire) { 74 $event->preventDefault(); 75 $event->stopPropagation(); 76 $event->result = false; 77 return; 78 } 79 80 // update depends['files'] array to include all included files 81 $cache->depends['files'] = !empty($cache->depends['files']) ? array_merge($cache->depends['files'], $depends) : $depends; 82 } 83 84 /** 85 * carry out included page checks: 86 * - to establish proper cache name, its dependent on the read status of included pages 87 * - to establish file dependencies, the included raw wiki pages 88 * 89 * @param string $id wiki page name 90 * @param string $key (reference) cache key 91 * @param array $depends array of include file dependencies 92 * 93 * @return bool expire the cache 94 */ 95 function _inclusion_check($id, &$key, &$depends) { 96 $hasPart = p_get_metadata($id, 'relation haspart'); 97 if (empty($hasPart)) return false; 98 99 $expire = false; 100 foreach ($hasPart as $page => $exists) { 101 // ensure its a wiki page 102 if (strpos($page,'/') || cleanID($page) != $page) continue; 103 104 // recursive includes aren't allowed and there is no need to do the same page twice 105 $file = wikiFN($page); 106 if (in_array($file, $depends)) continue; 107 108 // file existence state is different from state recorded in metadata 109 if (@file_exists($file) != $exists) { 110 111 if (($acl = $this->_acl_read_check($page)) != 'NONE') { $expire = true; } 112 113 } else if ($exists) { 114 115 // carry out an inclusion check on the included page, that will update $key & $depends 116 if ($this->_inclusion_check($page, $key, $depends)) { $expire = true; } 117 if (($acl = $this->_acl_read_check($page)) != 'NONE') { $depends[] = $file; } 118 119 } else { 120 $acl = 'NONE'; 121 } 122 123 // add this page and acl status to the key 124 $key .= '#'.$page.'|'.$acl; 125 } 126 127 return $expire; 128 } 129 130 function _acl_read_check($id) { 131 return (AUTH_READ <= auth_quickaclcheck($id)) ? 'READ' : 'NONE'; 132 } 133 134 function _cache_result(&$event, $param) { 135 $cache =& $event->data; 136 if (empty($cache->include)) return; 137 138# global $debug; 139# $debug['cache_result'][] = $event->result ? 'true' : 'false'; 140 } 141 142} 143//vim:ts=4:sw=4:et:enc=utf-8: 144