summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBen Coburn <btcoburn@silicodon.net>2006-07-05 12:56:52 +0200
committerBen Coburn <btcoburn@silicodon.net>2006-07-05 12:56:52 +0200
commitcc7d0c94bfa9c4c59fad7c52eb7c9b0decffb885 (patch)
tree2fbf29ad89b91e4a138b2afb730a5a105e0a1b87
parentc9b4bd1e30a047b11d0beaa4458204126e0c1b92 (diff)
downloadrpg-cc7d0c94bfa9c4c59fad7c52eb7c9b0decffb885.tar.gz
rpg-cc7d0c94bfa9c4c59fad7c52eb7c9b0decffb885.tar.bz2
IO action events
Adds page and namespace events: IO_WIKIPAGE_READ IO_WIKIPAGE_WRITE IO_NAMESPACE_CREATED IO_NAMESPACE_DELETED The namespace events are purely advisory, while the wikipage events allow page content to be modified between DokuWiki and the disk. These events are primarily intended to simplify keeping other tools in sync with the semantic structure of a DokuWiki site. As an added benefit, the events allow plugins to conduct automated processing of raw wiki page content. The namespace events cover the separate namespace trees for both pages and media. The "name" of the tree that the event belongs to is included in the event data. darcs-hash:20060705105652-05dcb-f44024e852a2adf1a14b8a7d69c46db067e72307.gz
-rw-r--r--inc/common.php22
-rw-r--r--inc/io.php124
-rw-r--r--inc/media.php2
-rw-r--r--lib/exe/mediamanager.php2
4 files changed, 133 insertions, 17 deletions
diff --git a/inc/common.php b/inc/common.php
index b1246ba7f..564d1f666 100644
--- a/inc/common.php
+++ b/inc/common.php
@@ -614,7 +614,7 @@ function rawLocale($id){
* @author Andreas Gohr <andi@splitbrain.org>
*/
function rawWiki($id,$rev=''){
- return io_readFile(wikiFN($id,$rev));
+ return io_readWikiPage(wikiFN($id, $rev), $id, $rev);
}
/**
@@ -649,7 +649,7 @@ function pageTemplate($id){
*/
function rawWikiSlices($range,$id,$rev=''){
list($from,$to) = split('-',$range,2);
- $text = io_readFile(wikiFN($id,$rev));
+ $text = io_readWikiPage(wikiFN($id, $rev), $id, $rev);
if(!$from) $from = 0;
if(!$to) $to = strlen($text)+1;
@@ -1019,7 +1019,7 @@ function getRevisionInfo($id,$rev,$mem_cache=true){
/**
- * Saves a wikitext by calling io_saveFile
+ * Saves a wikitext by calling io_writeWikiPage
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
@@ -1045,13 +1045,12 @@ function saveWikiText($id,$text,$summary,$minor=false){
$del = true;
// autoset summary on deletion
if(empty($summary)) $summary = $lang['deleted'];
- // unlock early
- unlock($id);
// remove empty namespaces
- io_sweepNS($id);
+ io_sweepNS($id, 'datadir');
+ io_sweepNS($id, 'mediadir');
}else{
- // save file (datadir is created in io_saveFile)
- io_saveFile($file,$text);
+ // save file (namespace dir is created in io_writeWikiPage)
+ io_writeWikiPage($file, $text, $id);
saveMetadata($id, $file, $minor);
$del = false;
}
@@ -1100,12 +1099,7 @@ function saveOldRevision($id){
if(!@file_exists($oldf)) return '';
$date = filemtime($oldf);
$newf = wikiFN($id,$date);
- if(substr($newf,-3)=='.gz'){
- io_saveFile($newf,rawWiki($id));
- }else{
- io_makeFileDir($newf);
- copy($oldf, $newf);
- }
+ io_writeWikiPage($newf, rawWiki($id), $id, $date);
return $date;
}
diff --git a/inc/io.php b/inc/io.php
index aed27d88e..a71162c11 100644
--- a/inc/io.php
+++ b/inc/io.php
@@ -9,26 +9,74 @@
if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/');
require_once(DOKU_INC.'inc/common.php');
require_once(DOKU_INC.'inc/HTTPClient.php');
+ require_once(DOKU_INC.'inc/events.php');
+ require_once(DOKU_INC.'inc/utf8.php');
/**
* Removes empty directories
*
+ * Sends IO_NAMESPACE_DELETED events for 'pages' and 'media' namespaces.
+ * Event data:
+ * $data[0] ns: The colon separated namespace path minus the trailing page name.
+ * $data[1] ns_type: 'pages' or 'media' namespace tree.
+ *
* @todo use safemode hack
* @author Andreas Gohr <andi@splitbrain.org>
+ * @author Ben Coburn <btcoburn@silicodon.net>
*/
function io_sweepNS($id,$basedir='datadir'){
global $conf;
+ $types = array ('datadir'=>'pages', 'mediadir'=>'media');
+ $ns_type = (isset($types[$basedir])?$types[$basedir]:false);
//scan all namespaces
while(($id = getNS($id)) !== false){
$dir = $conf[$basedir].'/'.utf8_encodeFN(str_replace(':','/',$id));
//try to delete dir else return
- if(!@rmdir($dir)) return;
+ if(@rmdir($dir)) {
+ if ($ns_type!==false) {
+ $data = array($id, $ns_type);
+ trigger_event('IO_NAMESPACE_DELETED', $data);
+ }
+ } else { return; }
}
}
/**
+ * Used to read in a DokuWiki page from file, and send IO_WIKIPAGE_READ events.
+ *
+ * Generates the action event which delegates to io_readFile().
+ * Action plugins are allowed to modify the page content in transit.
+ * The file path should not be changed.
+ *
+ * Event data:
+ * $data[0] The raw arguments for io_readFile as an array.
+ * $data[1] ns: The colon separated namespace path minus the trailing page name. (false if root ns)
+ * $data[2] page_name: The wiki page name.
+ * $data[3] rev: The page revision, false for current wiki pages.
+ *
+ * @author Ben Coburn <btcoburn@silicodon.net>
+ */
+function io_readWikiPage($file, $id, $rev=false) {
+ if (empty($rev)) { $rev = false; }
+ $data = array(array($file, false), getNS($id), noNS($id), $rev);
+ return trigger_event('IO_WIKIPAGE_READ', $data, '_io_readWikiPage_action', false);
+}
+
+/**
+ * Callback adapter for io_readFile().
+ * @author Ben Coburn <btcoburn@silicodon.net>
+ */
+function _io_readWikiPage_action($data) {
+ if (is_array($data) && is_array($data[0]) && count($data[0])===2) {
+ return call_user_func_array('io_readFile', $data[0]);
+ } else {
+ return ''; //callback error
+ }
+}
+
+/**
* Returns content of $file as cleaned string.
*
* Uses gzip if extension is .gz
@@ -55,6 +103,41 @@ function io_readFile($file,$clean=true){
}
/**
+ * Used to write out a DokuWiki page to file, and send IO_WIKIPAGE_WRITE events.
+ *
+ * This generates an action event and delegates to io_saveFile().
+ * Action plugins are allowed to modify the page content in transit.
+ * The file path should not be changed.
+ * (The append parameter is set to false.)
+ *
+ * Event data:
+ * $data[0] The raw arguments for io_saveFile as an array.
+ * $data[1] ns: The colon separated namespace path minus the trailing page name. (false if root ns)
+ * $data[2] page_name: The wiki page name.
+ * $data[3] rev: The page revision, false for current wiki pages.
+ *
+ * @author Ben Coburn <btcoburn@silicodon.net>
+ */
+function io_writeWikiPage($file, $content, $id, $rev=false) {
+ if (empty($rev)) { $rev = false; }
+ if ($rev===false) { io_createNamespace($id); } // create namespaces as needed
+ $data = array(array($file, $content, false), getNS($id), noNS($id), $rev);
+ return trigger_event('IO_WIKIPAGE_WRITE', $data, '_io_writeWikiPage_action', false);
+}
+
+/**
+ * Callback adapter for io_saveFile().
+ * @author Ben Coburn <btcoburn@silicodon.net>
+ */
+function _io_writeWikiPage_action($data) {
+ if (is_array($data) && is_array($data[0]) && count($data[0])===3) {
+ return call_user_func_array('io_saveFile', $data[0]);
+ } else {
+ return false; //callback error
+ }
+}
+
+/**
* Saves $content to $file.
*
* If the third parameter is set to true the given content
@@ -205,6 +288,45 @@ function io_unlock($file){
}
/**
+ * Create missing namespace directories and send the IO_NAMESPACE_CREATED events
+ * in the order of directory creation. (Parent directories first.)
+ *
+ * Event data:
+ * $data[0] ns: The colon separated namespace path minus the trailing page name.
+ * $data[1] ns_type: 'pages' or 'media' namespace tree.
+ *
+ * @author Ben Coburn <btcoburn@silicodon.net>
+ */
+function io_createNamespace($id, $ns_type='pages') {
+ // verify ns_type
+ $types = array('pages'=>'wikiFN', 'media'=>'mediaFN');
+ if (!isset($types[$ns_type])) {
+ trigger_error('Bad $ns_type parameter for io_createNamespace().');
+ return;
+ }
+ // make event list
+ $missing = array();
+ $ns_stack = explode(':', $id);
+ $ns = $id;
+ $tmp = dirname( $file = call_user_func($types[$ns_type], $ns) );
+ while (!@is_dir($tmp) && !(@file_exists($tmp) && !is_dir($tmp))) {
+ array_pop($ns_stack);
+ $ns = implode(':', $ns_stack);
+ if (strlen($ns)==0) { break; }
+ $missing[] = $ns;
+ $tmp = dirname(call_user_func($types[$ns_type], $ns));
+ }
+ // make directories
+ io_makeFileDir($file);
+ // send the events
+ $missing = array_reverse($missing); // inside out
+ foreach ($missing as $ns) {
+ $data = array($ns, $ns_type);
+ trigger_event('IO_NAMESPACE_CREATED', $data);
+ }
+}
+
+/**
* Create the directory needed for the given file
*
* @author Andreas Gohr <andi@splitbrain.org>
diff --git a/inc/media.php b/inc/media.php
index e0b1f3747..384ecb580 100644
--- a/inc/media.php
+++ b/inc/media.php
@@ -218,7 +218,7 @@ function media_upload($ns,$auth){
return false;
}
// prepare directory
- io_makeFileDir($fn);
+ io_createNamespace($id, 'media');
if(move_uploaded_file($file['tmp_name'], $fn)) {
// Set the correct permission here.
// Always chmod media because they may be saved with different permissions than expected from the php umask.
diff --git a/lib/exe/mediamanager.php b/lib/exe/mediamanager.php
index b381fabf6..fc11ed36c 100644
--- a/lib/exe/mediamanager.php
+++ b/lib/exe/mediamanager.php
@@ -31,7 +31,7 @@
$AUTH = auth_quickaclcheck("$NS:*");
// create the given namespace (just for beautification)
- if($AUTH >= AUTH_UPLOAD) io_makeFileDir(mediaFN("$NS:xxx"));
+ if($AUTH >= AUTH_UPLOAD) { io_createNamespace("$NS:xxx", 'media'); }
// handle upload
if($_FILES['upload']['tmp_name']){