summaryrefslogtreecommitdiff
path: root/inc/parserutils.php
diff options
context:
space:
mode:
Diffstat (limited to 'inc/parserutils.php')
-rw-r--r--inc/parserutils.php124
1 files changed, 77 insertions, 47 deletions
diff --git a/inc/parserutils.php b/inc/parserutils.php
index 9b2d99328..abba89b5a 100644
--- a/inc/parserutils.php
+++ b/inc/parserutils.php
@@ -10,11 +10,43 @@
if(!defined('DOKU_INC')) die('meh.');
/**
- * For how many different pages shall the first heading be loaded from the
- * metadata? When this limit is reached the title index is loaded and used for
- * all following requests.
+ * How many pages shall be rendered for getting metadata during one request
+ * at maximum? Note that this limit isn't respected when METADATA_RENDER_UNLIMITED
+ * is passed as render parameter to p_get_metadata.
*/
-if (!defined('P_GET_FIRST_HEADING_METADATA_LIMIT')) define('P_GET_FIRST_HEADING_METADATA_LIMIT', 10);
+if (!defined('P_GET_METADATA_RENDER_LIMIT')) define('P_GET_METADATA_RENDER_LIMIT', 5);
+
+/** 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. The P_GET_METADATA_RENDER_LIMIT is used in this mode.
+ * Use this if it is unlikely that the metadata value you are requesting
+ * does depend e.g. on pages that are included in the current page using
+ * the include plugin (this is very likely the case for the page title, but
+ * not for relation references).
+ */
+define('METADATA_RENDER_USING_SIMPLE_CACHE', 1);
+/**
+ * Render metadata using the metadata cache logic. The P_GET_METADATA_RENDER_LIMIT
+ * is used in this mode. Use this mode when you are requesting more complex
+ * metadata. Although this will cause rendering more often it might actually have
+ * the effect that less current metadata is returned as it is more likely than in
+ * the simple cache mode that metadata needs to be rendered for all pages at once
+ * which means that when the metadata for the page is requested that actually needs
+ * to be updated the limit might have been reached already.
+ */
+define('METADATA_RENDER_USING_CACHE', 2);
+/**
+ * Render metadata without limiting the number of pages for which metadata is
+ * rendered. Use this mode with care, normally it should only be used in places
+ * like the indexer or in cli scripts where the execution time normally isn't
+ * limited. This can be combined with the simple cache using
+ * METADATA_RENDER_USING_CACHE | METADATA_RENDER_UNLIMITED.
+ */
+define('METADATA_RENDER_UNLIMITED', 4);
/**
* Returns the parsed Wikitext in XHTML for the given id and revision.
@@ -229,14 +261,21 @@ 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
+ * METADATA_RENDER_UNLIMITED (also combined with the previous two options),
+ * default: METADATA_RENDER_USING_CACHE
* @return mixed The requested metadata fields
*
* @author Esther Brunner <esther@kaffeehaus.ch>
* @author Michael Hamann <michael@content-space.de>
*/
-function p_get_metadata($id, $key='', $render=true){
+function p_get_metadata($id, $key='', $render=METADATA_RENDER_USING_CACHE){
global $ID;
+ static $render_count = 0;
+ // track pages that have already been rendered in order to avoid rendering the same page
+ // again
+ static $rendered_pages = array();
// cache the current page
// Benchmarking shows the current page's metadata is generally the only page metadata
@@ -244,14 +283,36 @@ 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 && !isset($rendered_pages[$id])&& 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_UNLIMITED || $render_count < P_GET_METADATA_RENDER_LIMIT) {
+ 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) {
+ ++$render_count;
+ $rendered_pages[$id] = true;
$old_meta = $meta;
$meta = p_render_metadata($id, $meta);
// only update the file when the metadata has been changed
@@ -648,49 +709,18 @@ function & p_get_renderer($mode) {
* Gets the first heading from a file
*
* @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,
+ * METADATA_RENDER_UNLIMITED
*
* @author Andreas Gohr <andi@splitbrain.org>
* @author Michael Hamann <michael@content-space.de>
*/
-function p_get_first_heading($id, $render=true){
- // 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
- static $title_index = null;
- // cache for titles requested using p_get_metadata
- static $title_cache = array();
-
- $id = cleanID($id);
-
- // check if this title has already been requested
- if (isset($title_cache[$id]))
- return $title_cache[$id];
-
- // check if already too many titles have been requested and probably
- // using the title index is better
- if ($count > P_GET_FIRST_HEADING_METADATA_LIMIT) {
- if (is_null($title_index)) {
- $pages = array_map('rtrim', idx_getIndex('page', ''));
- $titles = array_map('rtrim', idx_getIndex('title', ''));
- // check for corrupt title index #FS2076
- if(count($pages) != count($titles)){
- $titles = array_fill(0,count($pages),'');
- @unlink($conf['indexdir'].'/title.idx'); // will be rebuilt in inc/init.php
- }
- $title_index = array_combine($pages, $titles);
- }
- return $title_index[$id];
- }
-
- ++$count;
- $title_cache[$id] = p_get_metadata($id,'title',$render);
- return $title_cache[$id];
+function p_get_first_heading($id, $render=METADATA_RENDER_USING_SIMPLE_CACHE){
+ return p_get_metadata(cleanID($id),'title',$render);
}
/**