diff options
author | Michael Hamann <michael@content-space.de> | 2011-02-06 13:03:00 +0100 |
---|---|---|
committer | Michael Hamann <michael@content-space.de> | 2011-02-06 13:12:54 +0100 |
commit | 0e5fde485b65b5a64fef50214496ad24bed17cef (patch) | |
tree | 1bee9543ddc3df84ac6e309a0a037ee81ed60d1b | |
parent | 87229c84afbda98679146558235bc7212ea404ee (diff) | |
download | rpg-0e5fde485b65b5a64fef50214496ad24bed17cef.tar.gz rpg-0e5fde485b65b5a64fef50214496ad24bed17cef.tar.bz2 |
Allow p_set_metadata during rendering, test cases included. FS#1827
-rw-r--r-- | _test/cases/inc/parserutils_set_metadata_during_rendering.test.php | 93 | ||||
-rw-r--r-- | inc/parserutils.php | 46 |
2 files changed, 128 insertions, 11 deletions
diff --git a/_test/cases/inc/parserutils_set_metadata_during_rendering.test.php b/_test/cases/inc/parserutils_set_metadata_during_rendering.test.php new file mode 100644 index 000000000..8319da298 --- /dev/null +++ b/_test/cases/inc/parserutils_set_metadata_during_rendering.test.php @@ -0,0 +1,93 @@ +<?php + +require_once DOKU_INC.'inc/init.php'; + +class parserutils_set_metadata_during_rendering_test extends UnitTestCase { + // the id used for this test case + private $id; + // if the test case is currently running + private $active = false; + // the original plugin controller + private $plugin_controller; + + // the actual test + function test_p_set_metadata_during_rendering() { + global $EVENT_HANDLER; + $this->id = 'test:p_set_metadata_during_rendering'; + $this->active = true; + + // write the wiki page so it exists and needs to be rendered + saveWikiText($this->id, 'Test '.time(), 'Test data setup'); + + $EVENT_HANDLER->register_hook('PARSER_METADATA_RENDER', 'BEFORE', $this, 'helper_set_metadata', array('test_before_set' => 'test')); + $EVENT_HANDLER->register_hook('PARSER_METADATA_RENDER', 'AFTER', $this, 'helper_set_metadata', array('test_after_set' => 'test')); + $EVENT_HANDLER->register_hook('PARSER_HANDLER_DONE', 'BEFORE', $this, 'helper_inject_test_instruction'); + + // Change the global plugin controller so this test can be a fake syntax plugin + global $plugin_controller; + $this->plugin_controller = $plugin_controller; + $plugin_controller = $this; + + // the actual rendering, all hooks should be executed here + $newMeta = p_get_metadata($this->id); + + // restore the plugin controller + $plugin_controller = $this->plugin_controller; + + // assert that all three calls to p_set_metadata have been successful + $this->assertEqual($newMeta['test_before_set'], 'test'); + $this->assertEqual($newMeta['test_after_set'], 'test'); + $this->assertEqual($newMeta['test_during_rendering'], 'test'); + + // clean up + $this->active = false; + + // make sure the saved metadata is the one that has been rendered + $this->assertEqual($newMeta, p_get_metadata($this->id)); + + saveWikiText($this->id, '', 'Test data remove'); + } + + // helper for the action plugin part of the test, tries executing p_set_metadata during rendering + function helper_set_metadata($event, $meta) { + if ($this->active) { + p_set_metadata($this->id, $meta, false, true); + $key = array_pop(array_keys($meta)); + $this->assertTrue(is_string($meta[$key])); // ensure we really have a key + // ensure that the metadata property hasn't been set previously + $this->assertNotEqual($meta[$key], p_get_metadata($this->id, $key)); + } + } + + // helper for injecting an instruction for this test case + function helper_inject_test_instruction($event) { + if ($this->active) + $event->data->calls[] = array('plugin', array('parserutils_test', array())); + } + + // fake syntax plugin rendering method that tries calling p_set_metadata during the actual rendering process + function render($format, &$renderer, $data) { + if ($this->active) { + $key = 'test_during_rendering'; + p_set_metadata($this->id, array($key => 'test'), false, true); + // ensure that the metadata property hasn't been set previously + $this->assertNotEqual($key, p_get_metadata($this->id, $key)); + } + } + + // wrapper function for the fake plugin controller + function getList($type='',$all=false){ + return $this->plugin_controller->getList(); + } + + // wrapper function for the fake plugin controller, return $this for the fake syntax of this test + function &load($type,$name,$new=false,$disabled=false){ + if ($name == 'parserutils_test') { + return $this; + } else { + return $this->plugin_controller->load($type, $name, $new, $disabled); + } + } +} + +// vim:ts=4:sw=4:et: diff --git a/inc/parserutils.php b/inc/parserutils.php index 6e349e984..86297da8b 100644 --- a/inc/parserutils.php +++ b/inc/parserutils.php @@ -291,18 +291,25 @@ function p_get_metadata($id, $key='', $render=true){ * @return boolean true on success * * @author Esther Brunner <esther@kaffeehaus.ch> + * @author Michael Hamann <michael@content-space.de> */ function p_set_metadata($id, $data, $render=false, $persistent=true){ if (!is_array($data)) return false; - global $ID; + global $ID, $METADATA_RENDERERS; - // cache the current page - $cache = ($ID == $id); - $orig = p_read_metadata($id, $cache); + // if there is currently a renderer change the data in the renderer instead + if (isset($METADATA_RENDERERS[$id])) { + $orig =& $METADATA_RENDERERS[$id]; + $meta = $orig; + } else { + // cache the current page + $cache = ($ID == $id); + $orig = p_read_metadata($id, $cache); - // render metadata first? - $meta = $render ? p_render_metadata($id, $orig) : $orig; + // render metadata first? + $meta = $render ? p_render_metadata($id, $orig) : $orig; + } // now add the passed metadata $protected = array('description', 'date', 'contributor'); @@ -339,7 +346,13 @@ function p_set_metadata($id, $data, $render=false, $persistent=true){ // save only if metadata changed if ($meta == $orig) return true; - return p_save_metadata($id, $meta); + if (isset($METADATA_RENDERERS[$id])) { + // set both keys individually as the renderer has references to the individual keys + $METADATA_RENDERERS[$id]['current'] = $meta['current']; + $METADATA_RENDERERS[$id]['persistent'] = $meta['persistent']; + } else { + return p_save_metadata($id, $meta); + } } /** @@ -413,7 +426,15 @@ function p_save_metadata($id, $meta) { */ function p_render_metadata($id, $orig){ // make sure the correct ID is in global ID - global $ID; + global $ID, $METADATA_RENDERERS; + + // avoid recursive rendering processes for the same id + if (isset($METADATA_RENDERERS[$id])) + return $orig; + + // store the original metadata in the global $METADATA_RENDERERS so p_set_metadata can use it + $METADATA_RENDERERS[$id] =& $orig; + $keep = $ID; $ID = $id; @@ -428,13 +449,14 @@ function p_render_metadata($id, $orig){ $instructions = p_cached_instructions(wikiFN($id),false,$id); if(is_null($instructions)){ $ID = $keep; + unset($METADATA_RENDERERS[$id]); return null; // something went wrong with the instructions } // set up the renderer $renderer = new Doku_Renderer_metadata(); - $renderer->meta = $orig['current']; - $renderer->persistent = $orig['persistent']; + $renderer->meta =& $orig['current']; + $renderer->persistent =& $orig['persistent']; // loop through the instructions foreach ($instructions as $instruction){ @@ -442,11 +464,13 @@ function p_render_metadata($id, $orig){ call_user_func_array(array(&$renderer, $instruction[0]), (array) $instruction[1]); } - $evt->result = array('current'=>$renderer->meta,'persistent'=>$renderer->persistent); + $evt->result = array('current'=>&$renderer->meta,'persistent'=>&$renderer->persistent); } $evt->advise_after(); + // clean up $ID = $keep; + unset($METADATA_RENDERERS[$id]); return $evt->result; } |