From 67c15ecea77ff971dcb554de77cf1c25de1140a0 Mon Sep 17 00:00:00 2001 From: Michael Hamann Date: Sun, 8 May 2011 00:51:22 +0200 Subject: Change when metadata is rendered - only when really needed This changes the cache logic for metadata. It introduces a new mode that tries to avoid rendering the page again for simple requests but still updates the metadata when the page has been changed (but not when the cache timeout has been reached or purge is used). It simply compares the time of the last rendering with the last modified time of the page. The old boolean $render parameter has been changed into an int with three possible values. Compatibility for the old parameter is provided using a check with is_numeric using the following mapping: - false is still don't render (0 is the new value for that) - true is using that new render logic which means that many plugins will still work unchanged even if they request a lot of data using $render=true (1 is the new value for that providing full compatibility in the case 1 has been used instead of true) The default value for p_get_first_heading is now that new simple cache logic, the default value for getting metadata is the cache logic which should be used with care but is the only way to request (rendered) metadata that can change because of plugin installations or upgrades. --- inc/parserutils.php | 60 ++++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 12 deletions(-) (limited to 'inc/parserutils.php') diff --git a/inc/parserutils.php b/inc/parserutils.php index 84aaebb4e..d7451cee4 100644 --- a/inc/parserutils.php +++ b/inc/parserutils.php @@ -14,7 +14,16 @@ if(!defined('DOKU_INC')) die('meh.'); * metadata? When this limit is reached the title index is loaded and used for * all following requests. */ -if (!defined('P_GET_FIRST_HEADING_METADATA_LIMIT')) define('P_GET_FIRST_HEADING_METADATA_LIMIT', 10); +if (!defined('P_GET_FIRST_HEADING_METADATA_LIMIT')) define('P_GET_FIRST_HEADING_METADATA_LIMIT', 20); + +/** Don't render metadata even if it is outdated or doesn't exist */ +define('METADATA_DONT_RENDER', 0); +/** Render metadata when the page is really newer or the metadata doesn't exist. Uses just a simple check, + but should work pretty well for loading simple metadata values like the page title and avoids + rendering a lot of pages in one request. */ +define('METADATA_RENDER_USING_SIMPLE_CACHE', 1); +/** Render metadata using the metadata cache logic. */ +define('METADATA_RENDER_USING_CACHE', 2); /** * Returns the parsed Wikitext in XHTML for the given id and revision. @@ -229,13 +238,15 @@ function p_get_instructions($text){ * * @param string $id The id of the page the metadata should be returned from * @param string $key The key of the metdata value that shall be read (by default everything) - separate hierarchies by " " like "date created" - * @param boolean $render If the page should be rendererd when the cache can't be used - default true + * @param int $render If the page should be rendererd - possible values: + * METADATA_DONT_RENDER, METADATA_RENDER_USING_SIMPLE_CACHE, METADATA_RENDER_USING_CACHE, default: + * METADATA_RENDER_USING_CACHE * @return mixed The requested metadata fields * * @author Esther Brunner * @author Michael Hamann */ -function p_get_metadata($id, $key='', $render=true){ +function p_get_metadata($id, $key='', $render=METADATA_RENDER_USING_CACHE){ global $ID; // cache the current page @@ -244,14 +255,32 @@ function p_get_metadata($id, $key='', $render=true){ $cache = ($ID == $id); $meta = p_read_metadata($id, $cache); + if (!is_numeric($render)) { + if ($render) { + $render = METADATA_RENDER_USING_SIMPLE_CACHE; + } else { + $render = METADATA_DONT_RENDER; + } + } + // prevent recursive calls in the cache static $recursion = false; - if (!$recursion && $render){ + if (!$recursion && $render != METADATA_DONT_RENDER && page_exists($id)){ $recursion = true; $cachefile = new cache_renderer($id, wikiFN($id), 'metadata'); - if (page_exists($id) && !$cachefile->useCache()){ + $do_render = false; + if ($render == METADATA_RENDER_USING_SIMPLE_CACHE) { + $pagefn = wikiFN($id); + $metafn = metaFN($id, '.meta'); + if (!@file_exists($metafn) || @filemtime($pagefn) > @filemtime($cachefile->cache)) { + $do_render = true; + } + } elseif (!$cachefile->useCache()){ + $do_render = true; + } + if ($do_render) { $old_meta = $meta; $meta = p_render_metadata($id, $meta); // only update the file when the metadata has been changed @@ -647,18 +676,25 @@ function & p_get_renderer($mode) { /** * Gets the first heading from a file * + * After P_GET_FIRST_HEADING_METADATA_LIMIT requests for different pages the title + * index will be loaded and used instead. Use METADATA_DONT_RENDER when you are + * requesting a lot of titles, METADATA_RENDER_USING_CACHE when you think + * rendering the page although it hasn't changed might be needed (or also + * want to influence rendering using events) and METADATA_RENDER_USING_SIMPLE_CACHE + * otherwise. Use METADATA_RENDER_USING_CACHE with care as it could cause + * parsing and rendering a lot of pages in one request. + * * @param string $id dokuwiki page id - * @param bool $render rerender if first heading not known - * default: true -- must be set to false for calls from the metadata renderer to - * protects against loops and excessive resource usage when pages - * for which only a first heading is required will attempt to - * render metadata for all the pages for which they require first - * headings ... and so on. + * @param int $render rerender if first heading not known + * default: METADATA_RENDER_USING_SIMPLE_CACHE + * Possible values: METADATA_DONT_RENDER, + * METADATA_RENDER_USING_SIMPLE_CACHE, + * METADATA_RENDER_USING_CACHE * * @author Andreas Gohr * @author Michael Hamann */ -function p_get_first_heading($id, $render=true){ +function p_get_first_heading($id, $render=METADATA_RENDER_USING_SIMPLE_CACHE){ // counter how many titles have been requested using p_get_metadata static $count = 1; // the index of all titles, only loaded when many titles are requested -- cgit v1.2.3