diff options
Diffstat (limited to 'inc/parserutils.php')
-rw-r--r-- | inc/parserutils.php | 160 |
1 files changed, 118 insertions, 42 deletions
diff --git a/inc/parserutils.php b/inc/parserutils.php index 061704cb3..f219696d5 100644 --- a/inc/parserutils.php +++ b/inc/parserutils.php @@ -222,31 +222,33 @@ function p_get_instructions($text){ * @author Esther Brunner <esther@kaffeehaus.ch> */ function p_get_metadata($id, $key=false, $render=false){ - global $INFO; - - if ($id == $INFO['id'] && !empty($INFO['meta'])) { - $meta = $INFO['meta']; - } else { - $file = metaFN($id, '.meta'); - - if (@file_exists($file)) $meta = unserialize(io_readFile($file, false)); - else $meta = array(); - - // metadata has never been rendered before - do it! - if ($render && !$meta['description']['abstract']){ - $meta = p_render_metadata($id, $meta); - io_saveFile($file, serialize($meta)); - } + global $ID, $INFO, $cache_metadata; + + // cache the current page + // Benchmarking shows the current page's metadata is generally the only page metadata + // accessed several times. This may catch a few other pages, but that shouldn't be an issue. + $cache = ($ID == $id); + $meta = p_read_metadata($id, $cache); + + // metadata has never been rendered before - do it! + if ($render && !$meta['description']['abstract']){ + $meta = p_render_metadata($id, $meta); + io_saveFile($file, serialize($meta)); + + // sync cached copies, including $INFO metadata + if (!empty($cache_metadata[$id])) $cache_metadata[$id] = $meta; + if (!empty($INFO) && ($id == $INFO['id'])) { $INFO['meta'] = $meta['current']; } } // filter by $key if ($key){ list($key, $subkey) = explode(' ', $key, 2); - if (trim($subkey)) return $meta[$key][$subkey]; - else return $meta[$key]; + if (trim($subkey)) return $meta['current'][$key][$subkey]; + + return $meta['current'][$key]; } - return $meta; + return $meta['current']; } /** @@ -254,14 +256,17 @@ function p_get_metadata($id, $key=false, $render=false){ * * @author Esther Brunner <esther@kaffeehaus.ch> */ -function p_set_metadata($id, $data, $render=false){ +function p_set_metadata($id, $data, $render=false, $persistent=true){ if (!is_array($data)) return false; - $orig = p_get_metadata($id); + global $ID; + + // cache the current page + $cache = ($ID == $id); + $orig = p_read_metadata($id, $cache); // render metadata first? - if ($render) $meta = p_render_metadata($id, $orig); - else $meta = $orig; + $meta = $render ? p_render_metadata($id, $orig) : $orig; // now add the passed metadata $protected = array('description', 'date', 'contributor'); @@ -269,58 +274,129 @@ function p_set_metadata($id, $data, $render=false){ // be careful with sub-arrays of $meta['relation'] if ($key == 'relation'){ + foreach ($value as $subkey => $subvalue){ - $meta[$key][$subkey] = array_merge($meta[$key][$subkey], $subvalue); + $meta['current'][$key][$subkey] = array_merge($meta['current'][$key][$subkey], $subvalue); + if ($persistent) + $meta['persistent'][$key][$subkey] = array_merge($meta['persistent'][$key][$subkey], $subvalue); } // be careful with some senisitive arrays of $meta } elseif (in_array($key, $protected)){ + if (is_array($value)){ #FIXME not sure if this is the intended thing: - if(!is_array($meta[$key])) $meta[$key] = array($meta[$key]); - $meta[$key] = array_merge($meta[$key], $value); + if(!is_array($meta['current'][$key])) $meta['current'][$key] = array($meta['current'][$key]); + $meta['current'][$key] = array_merge($meta['current'][$key], $value); + + if ($persistent) { + if(!is_array($meta['persistent'][$key])) $meta['persistent'][$key] = array($meta['persistent'][$key]); + $meta['persistent'][$key] = array_merge($meta['persistent'][$key], $value); + } } // no special treatment for the rest } else { - $meta[$key] = $value; + $meta['current'][$key] = $value; + if ($persistent) $meta['persistent'][$key] = $value; } } // save only if metadata changed if ($meta == $orig) return true; - // check if current page metadata has been altered - if so sync the changes - global $INFO; - if ($id == $INFO['id'] && isset($INFO['meta'])) { - $INFO['meta'] = $meta; - } + // sync cached copies, including $INFO metadata + global $cache_metadata, $INFO; + + if (!empty($cache_metadata[$id])) $cache_metadata[$id] = $meta; + if (!empty($INFO) && ($id == $INFO['id'])) { $INFO['meta'] = $meta['current']; } return io_saveFile(metaFN($id, '.meta'), serialize($meta)); } /** + * read the metadata from source/cache for $id + * (internal use only - called by p_get_metadata & p_set_metadata) + * + * this function also converts the metadata from the original format to + * the current format ('current' & 'persistent' arrays) + * + * @author Christopher Smith <chris@jalakai.co.uk> + * + * @param string $id absolute wiki page id + * @param bool $cache whether or not to cache metadata in memory + * (only use for metadata likely to be accessed several times) + * + * @return array metadata + */ +function p_read_metadata($id,$cache=false) { + global $cache_metadata; + + if (isset($cache_metadata[$id])) return $cache_metadata[$id]; + + $file = metaFN($id, '.meta'); + $meta = @file_exists($file) ? unserialize(io_readFile($file, false)) : array('current'=>array(),'persistent'=>array()); + + // convert $meta from old format to new (current+persistent) format + if (!isset($meta['current'])) { + $meta = array('current'=>$meta,'persistent'=>$meta); + + // remove non-persistent keys + unset($meta['persistent']['title']); + unset($meta['persistent']['description']['abstract']); + unset($meta['persistent']['description']['tableofcontents']); + unset($meta['persistent']['relation']['haspart']); + unset($meta['persistent']['relation']['references']); + unset($meta['persistent']['date']['valid']); + + if (empty($meta['persistent']['description'])) unset($meta['persistent']['description']); + if (empty($meta['persistent']['relation'])) unset($meta['persistent']['relation']); + if (empty($meta['persistent']['date'])) unset($meta['persistent']['date']); + + // save converted metadata + io_saveFile($file, serialize($meta)); + } + + if ($cache) { + $cache_metadata[$id] = $meta; + } + + return $meta; +} + +/** * renders the metadata of a page * * @author Esther Brunner <esther@kaffeehaus.ch> */ function p_render_metadata($id, $orig){ - require_once DOKU_INC."inc/parser/metadata.php"; - // get instructions - $instructions = p_cached_instructions(wikiFN($id),false,$id); + // add an extra key for the event - to tell event handlers the page whose metadata this is + $orig['page'] = $id; + $evt = new Doku_Event('PARSER_METADATA_RENDER', $orig); + if ($evt->advise_before()) { - // set up the renderer - $renderer = & new Doku_Renderer_metadata(); - $renderer->meta = $orig; + require_once DOKU_INC."inc/parser/metadata.php"; + + // get instructions + $instructions = p_cached_instructions(wikiFN($id),false,$id); + + // set up the renderer + $renderer = & new Doku_Renderer_metadata(); + $renderer->meta = $orig['current']; + $renderer->persistent = $orig['persistent']; + + // loop through the instructions + foreach ($instructions as $instruction){ + // execute the callback against the renderer + call_user_func_array(array(&$renderer, $instruction[0]), $instruction[1]); + } - // loop through the instructions - foreach ($instructions as $instruction){ - // execute the callback against the renderer - call_user_func_array(array(&$renderer, $instruction[0]), $instruction[1]); + $evt->result = array('current'=>$renderer->meta,'persistent'=>$renderer->persistent); } + $evt->advise_after(); - return $renderer->meta; + return $evt->result; } /** |