summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--_test/tests/inc/changelog_getlastrevisionat.test.php127
-rw-r--r--_test/tests/inc/common_ml.test.php11
-rw-r--r--_test/tests/inc/common_wl.test.php11
-rw-r--r--doku.php17
-rw-r--r--inc/changelog.php20
-rw-r--r--inc/common.php2
-rw-r--r--inc/html.php5
-rw-r--r--inc/lang/en/lang.php1
-rw-r--r--inc/parser/xhtml.php105
-rw-r--r--inc/parserutils.php12
-rw-r--r--inc/template.php5
-rw-r--r--lib/exe/detail.php3
-rw-r--r--lib/tpl/dokuwiki/detail.php2
13 files changed, 223 insertions, 98 deletions
diff --git a/_test/tests/inc/changelog_getlastrevisionat.test.php b/_test/tests/inc/changelog_getlastrevisionat.test.php
new file mode 100644
index 000000000..b4d0466b3
--- /dev/null
+++ b/_test/tests/inc/changelog_getlastrevisionat.test.php
@@ -0,0 +1,127 @@
+<?php
+
+/**
+ * Tests for requesting revisioninfo of a revision of a page with getRevisionInfo()
+ *
+ * This class uses the files:
+ * - data/pages/mailinglist.txt
+ * - data/meta/mailinglist.changes
+ */
+class changelog_getrelativerevision_test extends DokuWikiTest {
+
+ private $pageid = 'mailinglist';
+
+ function setup() {
+ parent::setup();
+ global $cache_revinfo;
+ $cache =& $cache_revinfo;
+ if(isset($cache['nonexist'])) {
+ unset($cache['nonexist']);
+ }
+ if(isset($cache['mailinglist'])) {
+ unset($cache['mailinglist']);
+ }
+ }
+
+
+ /**
+ * no nonexist.changes meta file available
+ */
+ function test_changemetadatanotexists() {
+ $rev = 1362525899;
+ $id = 'nonexist';
+ $revsexpected = false;
+
+ $pagelog = new PageChangeLog($id, $chunk_size = 8192);
+ $revs = $pagelog->getLastRevisionAt($rev);
+ $this->assertEquals($revsexpected, $revs);
+ }
+
+ /**
+ * start at exact current revision of mailinglist page
+ *
+ */
+ function test_startatexactcurrentrev() {
+ $rev = 1385051947;
+ $revsexpected = '';
+
+ //set a known timestamp
+ touch(wikiFN($this->pageid), $rev);
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getLastRevisionAt($rev);
+ $this->assertEquals($revsexpected, $revs);
+
+ }
+
+ /**
+ * test a future revision
+ *
+ */
+ function test_futurerev() {
+ $rev = 1385051947;
+ $revsexpected = '';
+
+ //set a known timestamp
+ touch(wikiFN($this->pageid), $rev);
+
+ $rev +=1;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getLastRevisionAt($rev);
+ $this->assertEquals($revsexpected, $revs);
+
+ }
+
+ /**
+ * start at exact last revision of mailinglist page
+ *
+ */
+ function test_exactlastrev() {
+ $rev = 1360110636;
+ $revsexpected = 1360110636;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revs = $pagelog->getLastRevisionAt($rev);
+ $this->assertEquals($revsexpected, $revs);
+ }
+
+
+ /**
+ * Request not existing revision
+ *
+ */
+ function test_olderrev() {
+ $rev = 1;
+ $revexpected = false;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revfound = $pagelog->getLastRevisionAt($rev);
+ $this->assertEquals($revexpected, $revfound);
+ }
+
+ /**
+ * Start at non existing revision somewhere between existing revisions
+ */
+ function test_notexistingrev() {
+ $rev = 1362525890;
+ $revexpected = 1362525359;
+
+ $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192);
+ $revfound = $pagelog->getLastRevisionAt($rev);
+ $this->assertEquals($revexpected, $revfound);
+ }
+
+ /**
+ * request nonexisting page
+ *
+ */
+ function test_notexistingpage() {
+ $rev = 1385051947;
+ $currentexpected = false;
+
+ $pagelog = new PageChangeLog('nonexistingpage', $chunk_size = 8192);
+ $current = $pagelog->getLastRevisionAt($rev);
+ $this->assertEquals($currentexpected, $current);
+ }
+} \ No newline at end of file
diff --git a/_test/tests/inc/common_ml.test.php b/_test/tests/inc/common_ml.test.php
index 415c0a88d..027dcaef2 100644
--- a/_test/tests/inc/common_ml.test.php
+++ b/_test/tests/inc/common_ml.test.php
@@ -146,4 +146,15 @@ class common_ml_test extends DokuWikiTest {
$this->assertEquals($expect, ml($id, $args));
}
+
+ function test_ml_empty_rev() {
+ global $conf;
+ $conf['useslash'] = 0;
+ $conf['userewrite'] = 0;
+
+ $args = array('a' => 'b', 'c' => 'd', 'rev' => '');
+
+ $expect = DOKU_BASE . $this->script . '?a=b&amp;c=d&amp;media=some:img.jpg';
+ $this->assertEquals($expect, ml('some:img.jpg', $args));
+ }
}
diff --git a/_test/tests/inc/common_wl.test.php b/_test/tests/inc/common_wl.test.php
index 2e34dcae3..4bfde3f39 100644
--- a/_test/tests/inc/common_wl.test.php
+++ b/_test/tests/inc/common_wl.test.php
@@ -142,6 +142,17 @@ class common_wl_test extends DokuWikiTest {
$expect = DOKU_BASE . DOKU_SCRIPT . '/some/one?a=b&c=d';
$this->assertEquals($expect, wl('some:one', 'a=b,c=d', false, '&'));
}
+
+ function test_wl_empty_rev() {
+ global $conf;
+ $conf['useslash'] = 0;
+ $conf['userewrite'] = 0;
+
+ $args = array('a' => 'b', 'c' => 'd', 'rev' => '');
+
+ $expect = DOKU_BASE . DOKU_SCRIPT . '?id=some:&amp;a=b&amp;c=d';
+ $this->assertEquals($expect, wl('some:', $args));
+ }
diff --git a/doku.php b/doku.php
index d861aa4fb..d984d90e8 100644
--- a/doku.php
+++ b/doku.php
@@ -34,6 +34,7 @@ $QUERY = trim($INPUT->str('id'));
$ID = getID();
$REV = $INPUT->int('rev');
+$DATE_AT = $INPUT->int('at');
$IDX = $INPUT->str('idx');
$DATE = $INPUT->int('date');
$RANGE = $INPUT->str('range');
@@ -47,7 +48,21 @@ $PRE = cleanText(substr($INPUT->post->str('prefix'), 0, -1));
$SUF = cleanText($INPUT->post->str('suffix'));
$SUM = $INPUT->post->str('summary');
-//make info about the selected page available
+if($DATE_AT) {
+ $pagelog = new PageChangeLog($ID);
+ $rev_t = $pagelog->getLastRevisionAt($DATE_AT);
+ if($rev_t === '') {
+ $REV = '';
+ } else if ($rev_t === false) {
+ $rev_n = $pagelog->getRelativeRevision($DATE_AT,+1);
+ msg(sprintf($lang['page_nonexist_rev'], $DATE_AT,$rev_n));
+ $REV = $DATE_AT;
+ } else {
+ $REV = $rev_t;
+ }
+}
+
+//make infos about the selected page available
$INFO = pageinfo();
//export minimal info to JS, plugins can add more
diff --git a/inc/changelog.php b/inc/changelog.php
index d2ad23c08..ba5618f84 100644
--- a/inc/changelog.php
+++ b/inc/changelog.php
@@ -817,6 +817,25 @@ abstract class ChangeLog {
public function isCurrentRevision($rev) {
return $rev == @filemtime($this->getFilename());
}
+
+ /**
+ * Return an existing revision for a specific date which is
+ * the current one or younger or equal then the date
+ *
+ * @param string $id
+ * @param number $date_at timestamp
+ * @return string revision ('' for current)
+ */
+ function getLastRevisionAt($date_at){
+ //requested date_at(timestamp) younger or equal then modified_time($this->id) => load current
+ if($date_at >= @filemtime($this->getFilename())) {
+ return '';
+ } else if ($rev = $this->getRelativeRevision($date_at+1, -1)) { //+1 to get also the requested date revision
+ return $rev;
+ } else {
+ return false;
+ }
+ }
/**
* Returns the next lines of the changelog of the chunck before head or after tail
@@ -1039,3 +1058,4 @@ function getRevisions($id, $first, $num, $chunk_size = 8192, $media = false) {
}
return $changelog->getRevisions($first, $num);
}
+
diff --git a/inc/common.php b/inc/common.php
index 7821cb3de..ce74717d0 100644
--- a/inc/common.php
+++ b/inc/common.php
@@ -383,6 +383,7 @@ function idfilter($id, $ue = true) {
function wl($id = '', $urlParameters = '', $absolute = false, $separator = '&amp;') {
global $conf;
if(is_array($urlParameters)) {
+ if(isset($urlParameters['rev']) && !$urlParameters['rev']) unset($urlParameters['rev']);
$urlParameters = buildURLparams($urlParameters, $separator);
} else {
$urlParameters = str_replace(',', $separator, $urlParameters);
@@ -483,6 +484,7 @@ function ml($id = '', $more = '', $direct = true, $sep = '&amp;', $abs = false)
if(empty($more['w'])) unset($more['w']);
if(empty($more['h'])) unset($more['h']);
if(isset($more['id']) && $direct) unset($more['id']);
+ if(isset($more['rev']) && !$more['rev']) unset($more['rev']);
$more = buildURLparams($more, $sep);
} else {
$matches = array();
diff --git a/inc/html.php b/inc/html.php
index 05688e0aa..6b6d026ee 100644
--- a/inc/html.php
+++ b/inc/html.php
@@ -208,6 +208,7 @@ function html_show($txt=null){
global $REV;
global $HIGH;
global $INFO;
+ global $DATE_AT;
//disable section editing for old revisions or in preview
if($txt || $REV){
$secedit = false;
@@ -227,8 +228,8 @@ function html_show($txt=null){
echo '</div></div>';
}else{
- if ($REV) print p_locale_xhtml('showrev');
- $html = p_wiki_xhtml($ID,$REV,true);
+ if ($REV||$DATE_AT) print p_locale_xhtml('showrev');
+ $html = p_wiki_xhtml($ID,$REV,true,$DATE_AT);
$html = html_secedit($html,$secedit);
if($INFO['prependTOC']) $html = tpl_toc(true).$html;
$html = html_hilight($html,$HIGH);
diff --git a/inc/lang/en/lang.php b/inc/lang/en/lang.php
index f76ce09ec..7986ebc00 100644
--- a/inc/lang/en/lang.php
+++ b/inc/lang/en/lang.php
@@ -366,4 +366,5 @@ $lang['currentns'] = 'Current namespace';
$lang['searchresult'] = 'Search Result';
$lang['plainhtml'] = 'Plain HTML';
$lang['wikimarkup'] = 'Wiki Markup';
+$lang['page_nonexist_rev'] = "Page has not existed with revision %d, try %d";
//Setup VIM: ex: et ts=2 :
diff --git a/inc/parser/xhtml.php b/inc/parser/xhtml.php
index 80701cd2e..1cf1acc32 100644
--- a/inc/parser/xhtml.php
+++ b/inc/parser/xhtml.php
@@ -28,6 +28,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
// @access public
var $doc = ''; // will contain the whole document
var $toc = array(); // will contain the Table of Contents
+ var $date_at = ''; // link pages and media against this revision
var $sectionedits = array(); // A stack of section edit data
private $lastsecid = 0; // last section edit id, used by startSectionEdit
@@ -618,6 +619,9 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
}
$link['more'] = '';
$link['class'] = $class;
+ if($this->date_at) {
+ $params['at'] = $this->date_at;
+ }
$link['url'] = wl($id, $params);
$link['name'] = $name;
$link['title'] = $id;
@@ -792,7 +796,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
list($ext,$mime,$dl) = mimetype($src,false);
if(substr($mime,0,5) == 'image' && $render){
- $link['url'] = ml($src,array('id'=>$ID,'cache'=>$cache),($linking=='direct'));
+ $link['url'] = ml($src,array('id'=>$ID,'cache'=>$cache,'rev'=>$this->_getLastMediaRevisionAt($src)),($linking=='direct'));
}elseif(($mime == 'application/x-shockwave-flash' || media_supportedav($mime)) && $render){
// don't link movies
$noLink = true;
@@ -800,7 +804,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
// add file icons
$class = preg_replace('/[^_\-a-z0-9]+/i','_',$ext);
$link['class'] .= ' mediafile mf_'.$class;
- $link['url'] = ml($src,array('id'=>$ID,'cache'=>$cache),true);
+ $link['url'] = ml($src,array('id'=>$ID,'cache'=>$cache,'rev'=>$this->_getLastMediaRevisionAt($src)),true);
if ($exists) $link['title'] .= ' (' . filesize_h(filesize(mediaFN($src))).')';
}
@@ -1078,7 +1082,7 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
return $title;
}
//add image tag
- $ret .= '<img src="'.ml($src,array('w'=>$width,'h'=>$height,'cache'=>$cache)).'"';
+ $ret .= '<img src="'.ml($src,array('w'=>$width,'h'=>$height,'cache'=>$cache,'rev'=>$this->_getLastMediaRevisionAt($src))).'"';
$ret .= ' class="media'.$align.'"';
if ($title) {
@@ -1268,95 +1272,22 @@ class Doku_Renderer_xhtml extends Doku_Renderer {
return $link;
}
-
-
+
/**
- * Embed video(s) in HTML
+ * _getLastMediaRevisionAt is a helperfunction to internalmedia() and _media()
+ * which returns an existing media revision less or equal to rev or date_at
*
- * @author Anika Henke <anika@selfthinker.org>
- *
- * @param string $src - ID of video to embed
- * @param int $width - width of the video in pixels
- * @param int $height - height of the video in pixels
- * @param array $atts - additional attributes for the <video> tag
- * @return string
+ * @author lisps
+ * @param string $media_id
+ * @access protected
+ * @return string revision ('' for current)
*/
- function _video($src,$width,$height,$atts=null){
-
- // prepare width and height
- if(is_null($atts)) $atts = array();
- $atts['width'] = (int) $width;
- $atts['height'] = (int) $height;
- if(!$atts['width']) $atts['width'] = 320;
- if(!$atts['height']) $atts['height'] = 240;
-
- // prepare alternative formats
- $extensions = array('webm', 'ogv', 'mp4');
- $alternatives = media_alternativefiles($src, $extensions);
- $poster = media_alternativefiles($src, array('jpg', 'png'), true);
- $posterUrl = '';
- if (!empty($poster)) {
- $posterUrl = ml(reset($poster),array('cache'=>$cache),true,'&');
- }
-
- $out = '';
- // open video tag
- $out .= '<video '.buildAttributes($atts).' controls="controls"';
- if ($posterUrl) $out .= ' poster="'.hsc($posterUrl).'"';
- $out .= '>'.NL;
- $fallback = '';
-
- // output source for each alternative video format
- foreach($alternatives as $mime => $file) {
- $url = ml($file,array('cache'=>$cache),true,'&');
- $title = $this->_xmlEntities(utf8_basename(noNS($file)));
-
- $out .= '<source src="'.hsc($url).'" type="'.$mime.'" />'.NL;
- // alternative content (just a link to the file)
- $fallback .= $this->internalmedia($file, $title, NULL, NULL, NULL, $cache=NULL, $linking='linkonly', $return=true);
- }
-
- // finish
- $out .= $fallback;
- $out .= '</video>'.NL;
- return $out;
+ function _getLastMediaRevisionAt($media_id){
+ if(!$this->date_at || media_isexternal($media_id)) return '';
+ $pagelog = new MediaChangeLog($media_id);
+ return $pagelog->getLastRevisionAt($this->date_at);
}
- /**
- * Embed audio in HTML
- *
- * @author Anika Henke <anika@selfthinker.org>
- *
- * @param string $src - ID of audio to embed
- * @param array $atts - additional attributes for the <audio> tag
- * @return string
- */
- function _audio($src,$atts=null){
-
- // prepare alternative formats
- $extensions = array('ogg', 'mp3', 'wav');
- $alternatives = media_alternativefiles($src, $extensions);
-
- $out = '';
- // open audio tag
- $out .= '<audio '.buildAttributes($atts).' controls="controls">'.NL;
- $fallback = '';
-
- // output source for each alternative audio format
- foreach($alternatives as $mime => $file) {
- $url = ml($file,array('cache'=>$cache),true,'&');
- $title = $this->_xmlEntities(utf8_basename(noNS($file)));
-
- $out .= '<source src="'.hsc($url).'" type="'.$mime.'" />'.NL;
- // alternative content (just a link to the file)
- $fallback .= $this->internalmedia($file, $title, NULL, NULL, NULL, $cache=NULL, $linking='linkonly', $return=true);
- }
-
- // finish
- $out .= $fallback;
- $out .= '</audio>'.NL;
- return $out;
- }
}
diff --git a/inc/parserutils.php b/inc/parserutils.php
index 4df273f11..75f259dca 100644
--- a/inc/parserutils.php
+++ b/inc/parserutils.php
@@ -56,7 +56,7 @@ define('METADATA_RENDER_UNLIMITED', 4);
*
* @author Andreas Gohr <andi@splitbrain.org>
*/
-function p_wiki_xhtml($id, $rev='', $excuse=true){
+function p_wiki_xhtml($id, $rev='', $excuse=true,$date_at=''){
$file = wikiFN($id,$rev);
$ret = '';
@@ -65,9 +65,9 @@ function p_wiki_xhtml($id, $rev='', $excuse=true){
$keep = $ID;
$ID = $id;
- if($rev){
+ if($rev || $date_at){
if(@file_exists($file)){
- $ret = p_render('xhtml',p_get_instructions(io_readWikiPage($file,$id,$rev)),$info); //no caching on old revisions
+ $ret = p_render('xhtml',p_get_instructions(io_readWikiPage($file,$id,$rev)),$info,$date_at); //no caching on old revisions
}elseif($excuse){
$ret = p_locale_xhtml('norev');
}
@@ -585,7 +585,7 @@ function p_sort_modes($a, $b){
* @author Harry Fuecks <hfuecks@gmail.com>
* @author Andreas Gohr <andi@splitbrain.org>
*/
-function p_render($mode,$instructions,&$info){
+function p_render($mode,$instructions,&$info,$date_at=''){
if(is_null($instructions)) return '';
$Renderer =& p_get_renderer($mode);
@@ -593,6 +593,10 @@ function p_render($mode,$instructions,&$info){
$Renderer->reset();
+ if($date_at) {
+ $Renderer->date_at = $date_at;
+ }
+
$Renderer->smileys = getSmileys();
$Renderer->entities = getEntities();
$Renderer->acronyms = getAcronyms();
diff --git a/inc/template.php b/inc/template.php
index 0a6a9e4aa..d98a66ebc 100644
--- a/inc/template.php
+++ b/inc/template.php
@@ -1031,6 +1031,7 @@ function tpl_img_getTag($tags, $alt = '', $src = null) {
function tpl_img($maxwidth = 0, $maxheight = 0, $link = true, $params = null) {
global $IMG;
global $INPUT;
+ global $REV;
$w = tpl_img_getTag('File.Width');
$h = tpl_img_getTag('File.Height');
@@ -1055,8 +1056,8 @@ function tpl_img($maxwidth = 0, $maxheight = 0, $link = true, $params = null) {
}
//prepare URLs
- $url = ml($IMG, array('cache'=> $INPUT->str('cache')), true, '&');
- $src = ml($IMG, array('cache'=> $INPUT->str('cache'), 'w'=> $w, 'h'=> $h), true, '&');
+ $url = ml($IMG, array('cache'=> $INPUT->str('cache'),'rev'=>$REV), true, '&');
+ $src = ml($IMG, array('cache'=> $INPUT->str('cache'),'rev'=>$REV, 'w'=> $w, 'h'=> $h), true, '&');
//prepare attributes
$alt = tpl_img_getTag('Simple.Title');
diff --git a/lib/exe/detail.php b/lib/exe/detail.php
index cd3f362ad..cc29d5b87 100644
--- a/lib/exe/detail.php
+++ b/lib/exe/detail.php
@@ -5,6 +5,7 @@ require_once(DOKU_INC.'inc/init.php');
$IMG = getID('media');
$ID = cleanID($INPUT->str('id'));
+$REV = $INPUT->int('rev');
// this makes some general info available as well as the info about the
// "parent" page
@@ -35,7 +36,7 @@ $ERROR = false;
$AUTH = auth_quickaclcheck($IMG);
if($AUTH >= AUTH_READ){
// check if image exists
- $SRC = mediaFN($IMG);
+ $SRC = mediaFN($IMG,$REV);
if(!@file_exists($SRC)){
//doesn't exist!
http_status(404);
diff --git a/lib/tpl/dokuwiki/detail.php b/lib/tpl/dokuwiki/detail.php
index ec846f6fd..49249612b 100644
--- a/lib/tpl/dokuwiki/detail.php
+++ b/lib/tpl/dokuwiki/detail.php
@@ -49,7 +49,7 @@ header('X-UA-Compatible: IE=edge,chrome=1');
if($ERROR):
echo '<h1>'.$ERROR.'</h1>';
else: ?>
-
+ <?php if($REV) echo p_locale_xhtml('showrev');?>
<h1><?php echo nl2br(hsc(tpl_img_getTag('simple.title'))); ?></h1>
<?php tpl_img(900,700); /* parameters: maximum width, maximum height (and more) */ ?>