Merge pull request #3607 from ssahara/revdiff2

add mechanism to track current revision, and other code improvements
This commit is contained in:
Andreas Gohr 2022-06-24 14:41:41 +02:00 committed by GitHub
commit aec2ae89d7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 602 additions and 545 deletions

View File

@ -67,7 +67,7 @@ abstract class ChangeLog
}
/**
* Return the current revision identifer
* Return the current revision identifier
*
* The "current" revision means current version of the page or media file. It is either
* identical with or newer than the "last" revision, that depends on whether the file
@ -87,7 +87,7 @@ abstract class ChangeLog
}
/**
* Return the last revision identifer, date value of the last entry of the changelog
* Return the last revision identifier, date value of the last entry of the changelog
*
* @return int|false revision timestamp
*/
@ -181,7 +181,7 @@ abstract class ChangeLog
* For efficiency, the log lines are parsed and cached for later
* calls to getRevisionInfo. Large changelog files are read
* backwards in chunks until the requested number of changelog
* lines are recieved.
* lines are received.
*
* @param int $first skip the first n changelog lines
* @param int $num number of revisions to return
@ -294,15 +294,15 @@ abstract class ChangeLog
}
/**
* Get the nth revision left or right handside for a specific page id and revision (timestamp)
* Get the nth revision left or right-hand side for a specific page id and revision (timestamp)
*
* For large changelog files, only the chunk containing the
* reference revision $rev is read and sometimes a next chunck.
* reference revision $rev is read and sometimes a next chunk.
*
* Adjacent changelog lines are optimistically parsed and cached to speed up
* consecutive calls to getRevisionInfo.
*
* @param int $rev revision timestamp used as startdate
* @param int $rev revision timestamp used as start date
* (doesn't need to be exact revision number)
* @param int $direction give position of returned revision with respect to $rev;
positive=next, negative=prev
@ -326,10 +326,10 @@ abstract class ChangeLog
// look for revisions later/earlier than $rev, when founded count till the wanted revision is reached
// also parse and cache changelog lines for getRevisionInfo().
$revcounter = 0;
$relativerev = false;
$checkotherchunck = true; //always runs once
while (!$relativerev && $checkotherchunck) {
$revCounter = 0;
$relativeRev = false;
$checkOtherChunk = true; //always runs once
while (!$relativeRev && $checkOtherChunk) {
$info = array();
//parse in normal or reverse order
$count = count($lines);
@ -345,20 +345,20 @@ abstract class ChangeLog
if ($this->cacheRevisionInfo($info)) {
//look for revs older/earlier then reference $rev and select $direction-th one
if (($direction > 0 && $info['date'] > $rev) || ($direction < 0 && $info['date'] < $rev)) {
$revcounter++;
if ($revcounter == abs($direction)) {
$relativerev = $info['date'];
$revCounter++;
if ($revCounter == abs($direction)) {
$relativeRev = $info['date'];
}
}
}
}
//true when $rev is found, but not the wanted follow-up.
$checkotherchunck = $fp
&& ($info['date'] == $rev || ($revcounter > 0 && !$relativerev))
$checkOtherChunk = $fp
&& ($info['date'] == $rev || ($revCounter > 0 && !$relativeRev))
&& !(($tail == $eof && $direction > 0) || ($head == 0 && $direction < 0));
if ($checkotherchunck) {
if ($checkOtherChunk) {
list($lines, $head, $tail) = $this->readAdjacentChunk($fp, $head, $tail, $direction);
if (empty($lines)) break;
@ -368,7 +368,7 @@ abstract class ChangeLog
fclose($fp);
}
return $relativerev;
return $relativeRev;
}
/**
@ -397,20 +397,20 @@ abstract class ChangeLog
$rev2 = $this->currentRevision();
}
//collect revisions around rev2
list($revs2, $allrevs, $fp, $lines, $head, $tail) = $this->retrieveRevisionsAround($rev2, $max);
list($revs2, $allRevs, $fp, $lines, $head, $tail) = $this->retrieveRevisionsAround($rev2, $max);
if (empty($revs2)) return array(array(), array());
//collect revisions around rev1
$index = array_search($rev1, $allrevs);
$index = array_search($rev1, $allRevs);
if ($index === false) {
//no overlapping revisions
list($revs1, , , , ,) = $this->retrieveRevisionsAround($rev1, $max);
if (empty($revs1)) $revs1 = array();
} else {
//revisions overlaps, reuse revisions around rev2
$lastrev = array_pop($allrevs); //keep last entry that could be external edit
$revs1 = $allrevs;
$lastRev = array_pop($allRevs); //keep last entry that could be external edit
$revs1 = $allRevs;
while ($head > 0) {
for ($i = count($lines) - 1; $i >= 0; $i--) {
$info = $this->parseLogLine($lines[$i]);
@ -425,7 +425,7 @@ abstract class ChangeLog
list($lines, $head, $tail) = $this->readAdjacentChunk($fp, $head, $tail, -1);
}
sort($revs1);
$revs1[] = $lastrev; //push back last entry
$revs1[] = $lastRev; //push back last entry
//return wanted selection
$revs1 = array_slice($revs1, max($index - intval($max / 2), 0), $max);
@ -460,33 +460,33 @@ abstract class ChangeLog
* Collect the $max revisions near to the timestamp $rev
*
* Ideally, half of retrieved timestamps are older than $rev, another half are newer.
* The returned array $requestedrevs may not contain the reference timestamp $rev
* The returned array $requestedRevs may not contain the reference timestamp $rev
* when it does not match any revision value recorded in changelog.
*
* @param int $rev revision timestamp
* @param int $max maximum number of revisions to be returned
* @return bool|array
* return array with entries:
* - $requestedrevs: array of with $max revision timestamps
* - $requestedRevs: array of with $max revision timestamps
* - $revs: all parsed revision timestamps
* - $fp: filepointer only defined for chuck reading, needs closing.
* - $fp: file pointer only defined for chuck reading, needs closing.
* - $lines: non-parsed changelog lines before the parsed revisions
* - $head: position of first readed changelogline
* - $lasttail: position of end of last readed changelogline
* - $head: position of first read changelog line
* - $lastTail: position of end of last read changelog line
* otherwise false
*/
protected function retrieveRevisionsAround($rev, $max)
{
$revs = array();
$aftercount = $beforecount = 0;
$afterCount = $beforeCount = 0;
//get lines from changelog
list($fp, $lines, $starthead, $starttail, $eof) = $this->readloglines($rev);
list($fp, $lines, $startHead, $startTail, $eof) = $this->readloglines($rev);
if (empty($lines)) return false;
//parse changelog lines in chunk, and read forward more chunks until $max/2 is reached
$head = $starthead;
$tail = $starttail;
$head = $startHead;
$tail = $startTail;
while (count($lines) > 0) {
foreach ($lines as $line) {
$info = $this->parseLogLine($line);
@ -494,27 +494,27 @@ abstract class ChangeLog
$revs[] = $info['date'];
if ($info['date'] >= $rev) {
//count revs after reference $rev
$aftercount++;
if ($aftercount == 1) $beforecount = count($revs);
$afterCount++;
if ($afterCount == 1) $beforeCount = count($revs);
}
//enough revs after reference $rev?
if ($aftercount > intval($max / 2)) break 2;
if ($afterCount > intval($max / 2)) break 2;
}
}
//retrieve next chunk
list($lines, $head, $tail) = $this->readAdjacentChunk($fp, $head, $tail, 1);
}
$lasttail = $tail;
$lastTail = $tail;
// add a possible revision of external edit, create or deletion
if ($lasttail == $eof && $aftercount <= intval($max / 2) &&
if ($lastTail == $eof && $afterCount <= intval($max / 2) &&
count($revs) && !$this->isCurrentRevision($revs[count($revs)-1])
) {
$revs[] = $this->currentRevision;
$aftercount++;
$afterCount++;
}
if ($aftercount == 0) {
if ($afterCount == 0) {
//given timestamp $rev is newer than the most recent line in chunk
return false; //FIXME: or proceed to collect older revisions?
}
@ -522,9 +522,9 @@ abstract class ChangeLog
//read more chunks backward until $max/2 is reached and total number of revs is equal to $max
$lines = array();
$i = 0;
if ($aftercount > 0) {
$head = $starthead;
$tail = $starttail;
if ($afterCount > 0) {
$head = $startHead;
$tail = $startTail;
while ($head > 0) {
list($lines, $head, $tail) = $this->readAdjacentChunk($fp, $head, $tail, -1);
@ -532,9 +532,9 @@ abstract class ChangeLog
$info = $this->parseLogLine($lines[$i]);
if ($this->cacheRevisionInfo($info)) {
$revs[] = $info['date'];
$beforecount++;
$beforeCount++;
//enough revs before reference $rev?
if ($beforecount > max(intval($max / 2), $max - $aftercount)) break 2;
if ($beforeCount > max(intval($max / 2), $max - $afterCount)) break 2;
}
}
}
@ -545,17 +545,17 @@ abstract class ChangeLog
sort($revs);
//trunk desired selection
$requestedrevs = array_slice($revs, -$max, $max);
$requestedRevs = array_slice($revs, -$max, $max);
return array($requestedrevs, $revs, $fp, $lines, $head, $lasttail);
return array($requestedRevs, $revs, $fp, $lines, $head, $lastTail);
}
/**
* Get the current revision information, considering external edit, create or deletion
*
* When the file has not modified since its last revision, the infomation of the last
* When the file has not modified since its last revision, the information of the last
* change that had already recorded in the changelog is returned as current change info.
* Otherwise, the change infomation since the last revision caused outside DokuWiki
* Otherwise, the change information since the last revision caused outside DokuWiki
* should be returned, which is referred as "external revision".
*
* The change date of the file can be determined by timestamp as far as the file exists,
@ -584,7 +584,7 @@ abstract class ChangeLog
if (isset($this->currentRevision)) return $this->getRevisionInfo($this->currentRevision);
// get revision id from the item file timestamp and chagelog
// get revision id from the item file timestamp and changelog
$fileLastMod = $this->getFilename();
$fileRev = @filemtime($fileLastMod); // false when the file not exist
$lastRev = $this->lastRevision(); // false when no changelog
@ -635,7 +635,7 @@ abstract class ChangeLog
$timestamp = $fileRev;
$sum = $lang['external_edit'];
} else {
// $fileRev is older than $lastRev, that is erroneous/incorrect occurence.
// $fileRev is older than $lastRev, that is erroneous/incorrect occurrence.
$msg = "Warning: current file modification time is older than last revision date";
$details = 'File revision: '.$fileRev.' '.dformat($fileRev, "%Y-%m-%d %H:%M:%S")."\n"
.'Last revision: '.$lastRev.' '.dformat($lastRev, "%Y-%m-%d %H:%M:%S");
@ -663,4 +663,16 @@ abstract class ChangeLog
$this->cache[$this->id][$this->currentRevision] = $revInfo;
return $this->getRevisionInfo($this->currentRevision);
}
/**
* Mechanism to trace no-actual external current revision
* @param int $rev
*/
public function traceCurrentRevision($rev)
{
if ($rev > $this->lastRevision()) {
$rev = $this->currentRevision();
}
return $rev;
}
}

View File

@ -12,7 +12,7 @@ trait ChangeLogTrait
/**
* Adds an entry to the changelog file
*
* @return array added logline as revision info
* @return array added log line as revision info
*/
abstract public function addLogEntry(array $info, $timestamp = null);
@ -47,7 +47,7 @@ trait ChangeLogTrait
* Build a changelog line from it's components
*
* @param array $info Revision info structure
* @param int $timestamp logline date (optional)
* @param int $timestamp log line date (optional)
* @return string changelog line
*/
public static function buildLogLine(array &$info, $timestamp = null)
@ -75,7 +75,7 @@ trait ChangeLogTrait
abstract protected function getChangelogFilename();
/**
* Checks if the ID has old revisons
* Checks if the ID has old revisions
* @return boolean
*/
public function hasRevisions()
@ -103,7 +103,7 @@ trait ChangeLogTrait
/**
* Returns lines from changelog.
* If file larger than $chuncksize, only chunck is read that could contain $rev.
* If file larger than $chunk_size, only chunk is read that could contain $rev.
*
* When reference timestamp $rev is outside time range of changelog, readloglines() will return
* lines in first or last chunk, but they obviously does not contain $rev.
@ -162,7 +162,7 @@ trait ChangeLogTrait
}
if ($tail - $head < 1) {
// cound not find chunk, assume requested rev is missing
// could not find chunk, assume requested rev is missing
fclose($fp);
return false;
}
@ -179,13 +179,13 @@ trait ChangeLogTrait
}
/**
* Read chunk and return array with lines of given chunck.
* Read chunk and return array with lines of given chunk.
* Has no check if $head and $tail are really at a new line
*
* @param resource $fp resource filepointer
* @param int $head start point chunck
* @param int $tail end point chunck
* @return array lines read from chunck
* @param resource $fp resource file pointer
* @param int $head start point chunk
* @param int $tail end point chunk
* @return array lines read from chunk
*/
protected function readChunk($fp, $head, $tail)
{
@ -209,7 +209,7 @@ trait ChangeLogTrait
/**
* Set pointer to first new line after $finger and return its position
*
* @param resource $fp filepointer
* @param resource $fp file pointer
* @param int $finger a pointer
* @return int pointer
*/
@ -225,14 +225,14 @@ trait ChangeLogTrait
}
/**
* Returns the next lines of the changelog of the chunck before head or after tail
* Returns the next lines of the changelog of the chunk before head or after tail
*
* @param resource $fp filepointer
* @param resource $fp file pointer
* @param int $head position head of last chunk
* @param int $tail position tail of last chunk
* @param int $direction positive forward, negative backward
* @return array with entries:
* - $lines: changelog lines of readed chunk
* - $lines: changelog lines of read chunk
* - $head: head of chunk
* - $tail: tail of chunk
*/
@ -261,7 +261,7 @@ trait ChangeLogTrait
}
}
//load next chunck
//load next chunk
$lines = $this->readChunk($fp, $head, $tail);
return array($lines, $head, $tail);
}

View File

@ -35,8 +35,8 @@ class MediaChangeLog extends ChangeLog
* Adds an entry to the changelog
*
* @param array $info Revision info structure of a media file
* @param int $timestamp logline date (optional)
* @return array revision info of added logline
* @param int $timestamp log line date (optional)
* @return array revision info of added log line
*
* @see also addMediaLogEntry() in inc/changelog.php file
*/

View File

@ -35,8 +35,8 @@ class PageChangeLog extends ChangeLog
* Adds an entry to the changelog
*
* @param array $info Revision info structure of a page
* @param int $timestamp logline date (optional)
* @return array revision info of added logline
* @param int $timestamp log line date (optional)
* @return array revision info of added log line
*
* @see also addLogEntry() in inc/changelog.php file
*/

View File

@ -5,19 +5,20 @@ namespace dokuwiki\ChangeLog;
/**
* Class RevisionInfo
*
* Provides methods to show Revision Information in DokuWiki Ui compoments:
* Provides methods to show Revision Information in DokuWiki Ui components:
* - Ui\Recent
* - Ui\PageRevisions
* - Ui\MediaRevisions
*/
class RevisionInfo
{
/* @var array */
protected $info;
/**
* Constructor
*
* @param array $info Revision Infomation structure with entries:
* @param array $info Revision Information structure with entries:
* - date: unix timestamp
* - ip: IPv4 or IPv6 address
* - type: change type (log line type)
@ -29,36 +30,88 @@ class RevisionInfo
* additionally,
* - current: (optional) whether current revision or not
* - timestamp: (optional) set only when external edits occurred
* - mode: (internal use) ether "media" or "page"
*/
public function __construct(array $info)
public function __construct($info = null)
{
$info['item'] = strrpos($info['id'], '.') ? 'media' : 'page';
// current is always true for items shown in Ui\Recents
$info['current'] = $info['current'] ?? true;
// revision info may have timestamp key when external edits occurred
$info['timestamp'] = $info['timestamp'] ?? true;
if (is_array($info) && isset($info['id'])) {
// define strategy context
$info['mode'] = strrpos($info['id'], '.') ? 'media' : 'page';
} else {
$info = [
'mode' => 'page',
'date' => false,
];
}
$this->info = $info;
}
/**
* fileicon of the page or media file
* Set or return whether this revision is current page or media file
*
* This method does not check exactly whether the revision is current or not. Instead,
* set value of associated "current" key for internal use. Some UI element like diff
* link button depend on relation to current page or media file. A changelog line does
* not indicate whether it corresponds to current page or media file.
*
* @param bool $value true if the revision is current, otherwise false
* @return bool
*/
public function isCurrent($value = null)
{
return (bool) $this->val('current', $value);
}
/**
* Return or set a value of associated key of revision information
* but does not allow to change values of existing keys
*
* @param string $key
* @param mixed $value
* @return string|null
*/
public function val($key, $value = null)
{
if (isset($value) && !array_key_exists($key, $this->info)) {
// setter, only for new keys
$this->info[$key] = $value;
}
if (array_key_exists($key, $this->info)) {
// getter
return $this->info[$key];
}
return null;
}
/**
* Set extra key-value to the revision information
* but does not allow to change values of existing keys
* @param array $info
* @return void
*/
public function append(array $info)
{
foreach ($info as $key => $value) {
$this->val($key, $value);
}
}
/**
* file icon of the page or media file
* used in [Ui\recent]
*
* @return string
*/
public function itemIcon()
public function showFileIcon()
{
$id = $this->info['id'];
$html = '';
switch ($this->info['item']) {
$id = $this->val('id');
switch ($this->val('mode')) {
case 'media': // media file revision
$html = media_printicon($id);
break;
return media_printicon($id);
case 'page': // page revision
$html = '<img class="icon" src="'.DOKU_BASE.'lib/images/fileicons/file.png" alt="'.$id.'" />';
return '<img class="icon" src="'.DOKU_BASE.'lib/images/fileicons/file.png" alt="'.$id.'" />';
}
return $html;
}
/**
@ -68,11 +121,11 @@ class RevisionInfo
* @param bool $checkTimestamp enable timestamp check, alter formatted string when timestamp is false
* @return string
*/
public function editDate($checkTimestamp = false)
public function showEditDate($checkTimestamp = false)
{
$formatted = dformat($this->info['date']);
if ($checkTimestamp && $this->info['timestamp'] === false) {
// exact date is unknown for item has externally deleted or older file restored
$formatted = dformat($this->val('date'));
if ($checkTimestamp && $this->val('timestamp') === false) {
// exact date is unknown for externally deleted file
// when unknown, alter formatted string "YYYY-mm-DD HH:MM" to "____-__-__ __:__"
$formatted = preg_replace('/[0-9a-zA-Z]/','_', $formatted);
}
@ -85,9 +138,9 @@ class RevisionInfo
*
* @return string
*/
public function editSummary()
public function showEditSummary()
{
return '<span class="sum">'.' '. hsc($this->info['sum']).'</span>';
return '<span class="sum">'.' '. hsc($this->val('sum')).'</span>';
}
/**
@ -96,17 +149,15 @@ class RevisionInfo
*
* @return string
*/
public function editor()
public function showEditor()
{
$html = '<span class="user">';
if ($this->info['user']) {
$html.= '<bdi>'. editorinfo($this->info['user']) .'</bdi>';
if (auth_ismanager()) $html.= ' <bdo dir="ltr">('. $this->info['ip'] .')</bdo>';
if ($this->val('user')) {
$html = '<bdi>'. editorinfo($this->val('user')) .'</bdi>';
if (auth_ismanager()) $html .= ' <bdo dir="ltr">('. $this->val('ip') .')</bdo>';
} else {
$html.= '<bdo dir="ltr">'. $this->info['ip'] .'</bdo>';
$html = '<bdo dir="ltr">'. $this->val('ip') .'</bdo>';
}
$html.= '</span>';
return $html;
return '<span class="user">'. $html. '</span>';
}
/**
@ -115,146 +166,191 @@ class RevisionInfo
*
* @return string
*/
public function itemName()
public function showFileName()
{
$id = $this->info['id'];
$rev = ($this->info['current']) ? '' : $this->info['date'];
$id = $this->val('id');
$rev = $this->isCurrent() ? '' : $this->val('date');
switch ($this->info['item']) {
switch ($this->val('mode')) {
case 'media': // media file revision
$params = ['tab_details'=> 'view', 'ns'=> getNS($id), 'image'=> $id];
if ($rev) $params += ['rev'=> $rev];
$href = media_managerURL($params, '&');
if(file_exists(mediaFN($id, $rev))) {
$class = 'wikilink1';
} else {
$class = 'wikilink2';
if(!$this->info['current']) {
//revision is not in attic
return $id;
}
}
return '<a href="'.$href.'" class="'.$class.'">'.$id.'</a>';
$display_name = $id;
$exists = file_exists(mediaFN($id, $rev));
break;
case 'page': // page revision
$params = $rev ? ['rev'=> $rev] : [];
$href = wl($id, $params, false, '&');
$display_name = useHeading('navigation') ? hsc(p_get_first_heading($id)) : $id;
if (!$display_name) $display_name = $id;
if(page_exists($id, $rev)) {
$class = 'wikilink1';
} else {
$class = 'wikilink2';
if(!$this->info['current']) {
//revision is not in attic
return $display_name;
}
}
return '<a href="'.$href.'" class="'.$class.'">'.$display_name.'</a>';
$exists = page_exists($id, $rev);
}
return '';
if($exists) {
$class = 'wikilink1';
} else {
if($this->isCurrent()) {
//show only not-existing link for current page, which allows for directly create a new page/upload
$class = 'wikilink2';
} else {
//revision is not in attic
return $display_name;
}
}
if ($this->val('type') == DOKU_CHANGE_TYPE_DELETE) {
$class = 'wikilink2';
}
return '<a href="'.$href.'" class="'.$class.'">'.$display_name.'</a>';
}
/**
* difflink icon in recents list
* all items in the recents are "current" revision of the page or media
* Revision Title for PageDiff table headline
*
* @return string
*/
public function difflinkRecent()
public function showRevisionTitle()
{
global $lang;
$id = $this->info['id'];
if (!$this->val('date')) return '&mdash;';
$id = $this->val('id');
$rev = $this->isCurrent() ? '' : $this->val('date');
$params = ($rev) ? ['rev'=> $rev] : [];
// revision info may have timestamp key when external edits occurred
$date = ($this->val('timestamp') === false)
? $lang['unknowndate']
: dformat($this->val('date'));
switch ($this->val('mode')) {
case 'media': // media file revision
$href = ml($id, $params, false, '&');
$exists = file_exists(mediaFN($id, $rev));
break;
case 'page': // page revision
$href = wl($id, $params, false, '&');
$exists = page_exists($id, $rev);
}
if($exists) {
$class = 'wikilink1';
} else {
if($this->isCurrent()) {
//show only not-existing link for current page, which allows for directly create a new page/upload
$class = 'wikilink2';
} else {
//revision is not in attic
return $id.' ['.$date.']';
}
}
if ($this->val('type') == DOKU_CHANGE_TYPE_DELETE) {
$class = 'wikilink2';
}
return '<bdi><a class="'.$class.'" href="'.$href.'">'.$id.' ['.$date.']'.'</a></bdi>';
}
/**
* diff link icon in recent changes list, to compare (this) current revision with previous one
* all items in "recent changes" are current revision of the page or media
*
* @return string
*/
public function showIconCompareWithPrevious()
{
global $lang;
$id = $this->val('id');
$href = '';
switch ($this->info['item']) {
switch ($this->val('mode')) {
case 'media': // media file revision
// unlike page, media file does not copied to media_attic when uploaded.
// diff icon will not be shown when external edit occurred
// because no attic file to be compared with current.
$revs = (new MediaChangeLog($id))->getRevisions(0, 1);
$showLink = (count($revs) && file_exists(mediaFN($id)));
$showLink = (count($revs) && file_exists(mediaFN($id,$revs[0])) && file_exists(mediaFN($id)));
if ($showLink) {
$href = media_managerURL(
['tab_details'=>'history', 'mediado'=>'diff', 'image'=> $id, 'ns'=> getNS($id)], '&'
);
$param = ['tab_details'=>'history', 'mediado'=>'diff', 'ns'=> getNS($id), 'image'=> $id];
$href = media_managerURL($param, '&');
}
break;
case 'page': // page revision
if($this->info['type'] !== DOKU_CHANGE_TYPE_CREATE) {
$href = wl($id, "do=diff", false, '&');
// when a page just created anyway, it is natural to expect no older revisions
// even if it had once existed but deleted before. Simply ignore to check changelog.
if ($this->val('type') !== DOKU_CHANGE_TYPE_CREATE) {
$href = wl($id, ['do'=>'diff'], false, '&');
}
}
if ($href) {
$html = '<a href="'.$href.'" class="diff_link">'
. '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
. ' title="'.$lang['diff'].'" alt="'.$lang['diff'].'" />'
. '</a>';
return '<a href="'.$href.'" class="diff_link">'
.'<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
.' title="'. $lang['diff'] .'" alt="'.$lang['diff'] .'" />'
.'</a>';
} else {
$html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
return '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
}
return $html;
}
/**
* difflink icon in revsions list
* diff link icon in revisions list, compare this revision with current one
* the icon does not displayed for the current revision
*
* @return string
*/
public function difflinkRevision()
public function showIconCompareWithCurrent()
{
global $lang;
$id = $this->info['id'];
$rev = $this->info['date'];
$id = $this->val('id');
$rev = $this->isCurrent() ? '' : $this->val('date');
switch ($this->info['item']) {
$href = '';
switch ($this->val('mode')) {
case 'media': // media file revision
if ($this->info['current'] || !file_exists(mediaFN($id, $rev))) {
$html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
} else {
$href = media_managerURL(['image'=> $id, 'rev'=> $rev, 'mediado'=>'diff'], '&');
$html = '<a href="'.$href.'" class="diff_link">'
. '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
. ' title="'. $lang['diff'] .'" alt="'.$lang['diff'] .'" />'
. '</a> ';
if (!$this->isCurrent() && file_exists(mediaFN($id, $rev))) {
$param = ['mediado'=>'diff', 'image'=> $id, 'rev'=> $rev];
$href = media_managerURL($param, '&');
}
return $html;
break;
case 'page': // page revision
if ($this->info['current'] || !page_exists($id, $rev)) {
$html = '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
} else {
$href = wl($id, "rev=$rev,do=diff", false, '&');
$html = '<a href="'.$href.'" class="diff_link">'
. '<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
. ' title="'.$lang['diff'].'" alt="'.$lang['diff'].'" />'
. '</a>';
if (!$this->isCurrent()) {
$href = wl($id, ['rev'=> $rev, 'do'=>'diff'], false, '&');
}
return $html;
}
return '';
if ($href) {
return '<a href="'.$href.'" class="diff_link">'
.'<img src="'.DOKU_BASE.'lib/images/diff.png" width="15" height="11"'
.' title="'. $lang['diff'] .'" alt="'.$lang['diff'] .'" />'
.'</a>';
} else {
return '<img src="'.DOKU_BASE.'lib/images/blank.gif" width="15" height="11" alt="" />';
}
}
/**
* icon revision link
* icon for revision action
* used in [Ui\recent]
*
* @return string
*/
public function revisionlink()
public function showIconRevisions()
{
global $lang;
if (!actionOK('revisions')) {
return ''; //FIXME check page, media
return '';
}
$id = $this->info['id'];
$href = '';
switch ($this->info['item']) {
$id = $this->val('id');
switch ($this->val('mode')) {
case 'media': // media file revision
$href = media_managerURL(['tab_details'=>'history', 'image'=> $id, 'ns'=> getNS($id)], '&');
$param = ['tab_details'=>'history', 'ns'=> getNS($id), 'image'=> $id];
$href = media_managerURL($param, '&');
break;
case 'page': // page revision
$href = wl($id, "do=revisions", false, '&');
$href = wl($id, ['do'=>'revisions'], false, '&');
}
return '<a href="'.$href.'" class="revisions_link">'
. '<img src="'.DOKU_BASE.'lib/images/history.png" width="12" height="14"'
@ -268,14 +364,14 @@ class RevisionInfo
*
* @return string
*/
public function sizeChange()
public function showSizeChange()
{
$class = 'sizechange';
$value = filesize_h(abs($this->info['sizechange']));
if ($this->info['sizechange'] > 0) {
$value = filesize_h(abs($this->val('sizechange')));
if ($this->val('sizechange') > 0) {
$class .= ' positive';
$value = '+' . $value;
} elseif ($this->info['sizechange'] < 0) {
} elseif ($this->val('sizechange') < 0) {
$class .= ' negative';
$value = '-' . $value;
} else {
@ -285,15 +381,15 @@ class RevisionInfo
}
/**
* current indicator, used in revison list
* not used in Ui\Recents because recent items are always current one
* current indicator, used in revision list
* not used in Ui\Recent because recent files are always current one
*
* @return string
*/
public function currentIndicator()
public function showCurrentIndicator()
{
global $lang;
return ($this->info['current']) ? '('.$lang['current'].')' : '';
return $this->isCurrent() ? '('.$lang['current'].')' : '';
}

View File

@ -15,9 +15,10 @@ abstract class Diff extends Ui
/* @var string */
protected $id; // page id or media id
/* @var int */
protected $oldRev; // timestamp of older revision
protected $newRev; // timestamp of newer revision
/* @var int|false */
protected $rev1; // timestamp of older revision
/* @var int|false */
protected $rev2; // timestamp of newer revision
/* @var array */
protected $preference = [];
@ -49,17 +50,15 @@ abstract class Diff extends Ui
/**
* Set a pair of revisions to be compared
*
* @param int $oldRev
* @param int $newRev
* @param int $rev1 older revision
* @param int $rev2 newer revision
* @return $this
*/
public function compare($oldRev, $newRev)
public function compare($rev1, $rev2)
{
if ($oldRev < $newRev) {
[$this->oldRev, $this->newRev] = [$oldRev, $newRev];
} else {
[$this->oldRev, $this->newRev] = [$newRev, $oldRev];
}
if ($rev2 < $rev1) [$rev1, $rev2] = [$rev2, $rev1];
$this->rev1 = (int)$rev1;
$this->rev2 = (int)$this->changelog->traceCurrentRevision($rev2);
return $this;
}
@ -95,27 +94,36 @@ abstract class Diff extends Ui
{
global $INPUT;
// difflink icon click, eg. ?rev=123456789&do=diff
// diff link icon click, eg. &do=diff&rev=#
if ($INPUT->has('rev')) {
$this->oldRev = $INPUT->int('rev');
$this->newRev = $this->changelog->currentRevision();
}
// submit button with two checked boxes
$rev2 = $INPUT->arr('rev2', []);
if (count($rev2) > 1) {
if ($rev2[0] < $rev2[1]) {
[$this->oldRev, $this->newRev] = [$rev2[0], $rev2[1]];
} else {
[$this->oldRev, $this->newRev] = [$rev2[1], $rev2[0]];
$this->rev1 = $INPUT->int('rev');
$this->rev2 = $this->changelog->currentRevision();
if ($this->rev2 <= $this->rev1) {
// fallback to compare previous with current
unset($this->rev1, $this->rev2);
}
}
if (!isset($this->oldRev, $this->newRev)) {
// no revision was given, compare previous to current
$revs = $this->changelog->getRevisions(-1, 2);
$this->newRev = $this->changelog->currentRevision();
$this->oldRev = ($revs[0] == $this->newRev) ? $revs[1] : $revs[0];
// submit button with two checked boxes, eg. &do=diff&rev2[0]=#&rev2[1]=#
$revs = $INPUT->arr('rev2', []);
if (count($revs) > 1) {
list($rev1, $rev2) = $revs;
if ($rev2 < $rev1) [$rev1, $rev2] = [$rev2, $rev1];
$this->rev1 = (int)$rev1;
$this->rev2 = (int)$this->changelog->traceCurrentRevision($rev2);
}
// no revision was given, compare previous to current
if (!isset($this->rev1, $this->rev2)) {
$rev2 = $this->changelog->currentRevision();
if ($rev2 > $this->changelog->lastRevision()) {
$rev1 = $this->changelog->lastRevision();
} else {
$revs = $this->changelog->getRevisions(0, 1);
$rev1 = count($revs) ? $revs[0] : false;
}
$this->rev1 = $rev1;
$this->rev2 = $rev2;
}
}
}

View File

@ -18,9 +18,10 @@ class MediaDiff extends Diff
/* @var MediaChangeLog */
protected $changelog;
/* @var array */
protected $oldRevInfo;
protected $newRevInfo;
/* @var RevisionInfo older revision */
protected $RevInfo1;
/* @var RevisionInfo newer revision */
protected $RevInfo2;
/* @var bool */
protected $is_img;
@ -59,7 +60,7 @@ class MediaDiff extends Diff
{
global $INPUT;
// requested rev or rev2
// retrieve requested rev or rev2
parent::handle();
// requested diff view type
@ -75,37 +76,32 @@ class MediaDiff extends Diff
{
$changelog =& $this->changelog;
// revision info of older file (left side)
$this->oldRevInfo = $changelog->getRevisionInfo($this->oldRev);
// revision info of newer file (right side)
$this->newRevInfo = $changelog->getRevisionInfo($this->newRev);
// create revision info object for older and newer sides
// RevInfo1 : older, left side
// RevInfo2 : newer, right side
$this->RevInfo1 = new RevisionInfo($changelog->getRevisionInfo($this->rev1));
$this->RevInfo2 = new RevisionInfo($changelog->getRevisionInfo($this->rev2));
$this->is_img = preg_match('/\.(jpe?g|gif|png)$/', $this->id);
foreach ([&$this->oldRevInfo, &$this->newRevInfo] as &$revInfo) {
// use timestamp and '' properly as $rev for the current file
$isCurrent = $changelog->isCurrentRevision($revInfo['date']);
$revInfo += [
'current' => $isCurrent,
'rev' => $isCurrent ? '' : $revInfo['date'],
];
// headline in the Diff view navigation
$revInfo['navTitle'] = $this->revisionTitle($revInfo);
foreach ([$this->RevInfo1, $this->RevInfo2] as $RevInfo) {
$isCurrent = $changelog->isCurrentRevision($RevInfo->val('date'));
$RevInfo->isCurrent($isCurrent);
if ($this->is_img) {
$rev = $revInfo['rev'];
$rev = $isCurrent ? '' : $RevInfo->val('date');
$meta = new JpegMeta(mediaFN($this->id, $rev));
// get image width and height for the mediamanager preview panel
$revInfo['previewSize'] = media_image_preview_size($this->id, $rev, $meta);
// get image width and height for the media manager preview panel
$RevInfo->append([
'previewSize' => media_image_preview_size($this->id, $rev, $meta)
]);
}
}
unset($revInfo);
// re-check image, ensure minimum image width for showImageDiff()
$this->is_img = ($this->is_img
&& ($this->oldRevInfo['previewSize'][0] ?? 0) >= 30
&& ($this->newRevInfo['previewSize'][0] ?? 0) >= 30
&& ($this->RevInfo1->val('previewSize')[0] ?? 0) >= 30
&& ($this->RevInfo2->val('previewSize')[0] ?? 0) >= 30
);
// adjust requested diff view type
if (!$this->is_img) {
@ -164,8 +160,8 @@ class MediaDiff extends Diff
*/
protected function showDiffViewSelector()
{
// use timestamp for current revision
[$oldRev, $newRev] = [(int)$this->oldRevInfo['date'], (int)$this->newRevInfo['date']];
// use timestamp for current revision, date may be false when revisions < 2
[$rev1, $rev2] = [(int)$this->RevInfo1->val('date'), (int)$this->RevInfo2->val('date')];
echo '<div class="diffoptions group">';
@ -178,8 +174,8 @@ class MediaDiff extends Diff
$form->addTagOpen('div')->addClass('no');
$form->setHiddenField('sectok', null);
$form->setHiddenField('mediado', 'diff');
$form->setHiddenField('rev2[0]', $oldRev);
$form->setHiddenField('rev2[1]', $newRev);
$form->setHiddenField('rev2[0]', $rev1);
$form->setHiddenField('rev2[1]', $rev2);
$form->addTagClose('div');
echo $form->toHTML();
@ -194,34 +190,34 @@ class MediaDiff extends Diff
*/
protected function showImageDiff()
{
$rev1 = $this->RevInfo1->isCurrent() ? '' : $this->RevInfo1->val('date');
$rev2 = $this->RevInfo2->isCurrent() ? '' : $this->RevInfo2->val('date');
// diff view type: opacity or portions
$type = $this->preference['difftype'];
// use '' for current revision
[$oldRev, $newRev] = [$this->oldRevInfo['rev'], $this->newRevInfo['rev']];
// adjust image width, right side (newer) has priority
$oldRevSize = $this->oldRevInfo['previewSize'];
$newRevSize = $this->newRevInfo['previewSize'];
if ($oldRevSize != $newRevSize) {
if ($newRevSize[0] > $oldRevSize[0]) {
$oldRevSize = $newRevSize;
$rev1Size = $this->RevInfo1->val('previewSize');
$rev2Size = $this->RevInfo2->val('previewSize');
if ($rev1Size != $rev2Size) {
if ($rev2Size[0] > $rev1Size[0]) {
$rev1Size = $rev2Size;
}
}
$oldRevSrc = ml($this->id, ['rev' => $oldRev, 'h' => $oldRevSize[1], 'w' => $oldRevSize[0]]);
$newRevSrc = ml($this->id, ['rev' => $newRev, 'h' => $oldRevSize[1], 'w' => $oldRevSize[0]]);
$rev1Src = ml($this->id, ['rev' => $rev1, 'h' => $rev1Size[1], 'w' => $rev1Size[0]]);
$rev2Src = ml($this->id, ['rev' => $rev2, 'h' => $rev1Size[1], 'w' => $rev1Size[0]]);
// slider
echo '<div class="slider" style="max-width: '.($oldRevSize[0]-20).'px;" ></div>';
echo '<div class="slider" style="max-width: '.($rev1Size[0]-20).'px;" ></div>';
// two images in divs
echo '<div class="imageDiff '.$type.'">';
echo '<div class="image1" style="max-width: '.$oldRevSize[0].'px;">';
echo '<img src="'.$oldRevSrc.'" alt="" />';
echo '<div class="image1" style="max-width: '.$rev1Size[0].'px;">';
echo '<img src="'.$rev1Src.'" alt="" />';
echo '</div>';
echo '<div class="image2" style="max-width: '.$oldRevSize[0].'px;">';
echo '<img src="'.$newRevSrc.'" alt="" />';
echo '<div class="image2" style="max-width: '.$rev1Size[0].'px;">';
echo '<img src="'.$rev2Src.'" alt="" />';
echo '</div>';
echo '</div>';
}
@ -238,55 +234,65 @@ class MediaDiff extends Diff
$ns = getNS($this->id);
$auth = auth_quickaclcheck("$ns:*");
// use '' for current revision
[$oldRev, $newRev] = [$this->oldRevInfo['rev'], $this->newRevInfo['rev']];
$rev1 = $this->RevInfo1->isCurrent() ? '' : (int)$this->RevInfo1->val('date');
$rev2 = $this->RevInfo2->isCurrent() ? '' : (int)$this->RevInfo2->val('date');
$oldRevMeta = new JpegMeta(mediaFN($this->id, $oldRev));
$newRevMeta = new JpegMeta(mediaFN($this->id, $newRev));
// revision title
$rev1Title = trim($this->RevInfo1->showRevisionTitle() .' '. $this->RevInfo1->showCurrentIndicator());
$rev1Summary = ($this->RevInfo1->val('date'))
? $this->RevInfo1->showEditSummary() .' '. $this->RevInfo1->showEditor()
: '';
$rev2Title = trim($this->RevInfo2->showRevisionTitle() .' '. $this->RevInfo2->showCurrentIndicator());
$rev2Summary = ($this->RevInfo2->val('date'))
? $this->RevInfo2->showEditSummary() .' '. $this->RevInfo2->showEditor()
: '';
$rev1Meta = new JpegMeta(mediaFN($this->id, $rev1));
$rev2Meta = new JpegMeta(mediaFN($this->id, $rev2));
// display diff view table
echo '<div class="table">';
echo '<table>';
echo '<tr>';
echo '<th>'. $this->oldRevInfo['navTitle'] .'</th>';
echo '<th>'. $this->newRevInfo['navTitle'] .'</th>';
echo '<th>'. $rev1Title .' '. $rev1Summary .'</th>';
echo '<th>'. $rev2Title .' '. $rev2Summary .'</th>';
echo '</tr>';
echo '<tr class="image">';
echo '<td>';
media_preview($this->id, $auth, $oldRev, $oldRevMeta); // $auth not used in media_preview()?
media_preview($this->id, $auth, $rev1, $rev1Meta); // $auth not used in media_preview()?
echo '</td>';
echo '<td>';
media_preview($this->id, $auth, $newRev, $newRevMeta);
media_preview($this->id, $auth, $rev2, $rev2Meta);
echo '</td>';
echo '</tr>';
echo '<tr class="actions">';
echo '<td>';
media_preview_buttons($this->id, $auth, $oldRev); // $auth used in media_preview_buttons()
media_preview_buttons($this->id, $auth, $rev1); // $auth used in media_preview_buttons()
echo '</td>';
echo '<td>';
media_preview_buttons($this->id, $auth, $newRev);
media_preview_buttons($this->id, $auth, $rev2);
echo '</td>';
echo '</tr>';
$l_tags = media_file_tags($oldRevMeta);
$r_tags = media_file_tags($newRevMeta);
// FIXME r_tags-only stuff
foreach ($l_tags as $key => $l_tag) {
if ($l_tag['value'] != $r_tags[$key]['value']) {
$r_tags[$key]['highlighted'] = true;
$l_tags[$key]['highlighted'] = true;
} elseif (!$l_tag['value'] || !$r_tags[$key]['value']) {
unset($r_tags[$key]);
unset($l_tags[$key]);
$rev1Tags = media_file_tags($rev1Meta);
$rev2Tags = media_file_tags($rev2Meta);
// FIXME rev2Tags-only stuff ignored
foreach ($rev1Tags as $key => $tag) {
if ($tag['value'] != $rev2Tags[$key]['value']) {
$rev2Tags[$key]['highlighted'] = true;
$rev1Tags[$key]['highlighted'] = true;
} elseif (!$tag['value'] || !$rev2Tags[$key]['value']) {
unset($rev2Tags[$key]);
unset($rev1Tags[$key]);
}
}
echo '<tr>';
foreach (array($l_tags, $r_tags) as $tags) {
foreach ([$rev1Tags, $rev2Tags] as $tags) {
echo '<td>';
echo '<dl class="img_tags">';
@ -295,13 +301,13 @@ class MediaDiff extends Diff
if (!$value) $value = '-';
echo '<dt>'.$lang[$tag['tag'][1]].'</dt>';
echo '<dd>';
if ($tag['highlighted']) echo '<strong>';
if (!empty($tag['highlighted'])) echo '<strong>';
if ($tag['tag'][2] == 'date') {
echo dformat($value);
} else {
echo hsc($value);
}
if ($tag['highlighted']) echo '</strong>';
if (!empty($tag['highlighted'])) echo '</strong>';
echo '</dd>';
}
echo '</dl>';
@ -314,37 +320,4 @@ class MediaDiff extends Diff
echo '</div>';
}
/**
* Revision Title for MediaDiff table headline
*
* @param array $info Revision info structure of a media file
* @return string
*/
protected function revisionTitle(array $info)
{
global $lang, $INFO;
if (isset($info['date'])) {
$rev = $info['date'];
$title = '<bdi><a class="wikilink1" href="'.ml($this->id, ['rev' => $rev]).'">'
. dformat($rev).'</a></bdi>';
} else {
$rev = false;
$title = '&mdash;';
}
if (isset($info['current']) || ($rev && $rev == $INFO['currentrev'])) {
$title .= '&nbsp;('.$lang['current'].')';
}
// append separator
$title .= ($this->preference['difftype'] === 'inline') ? ' ' : '<br />';
// supplement
if (isset($info['date'])) {
$RevInfo = new RevisionInfo($info);
$title .= $RevInfo->editSummary().' '.$RevInfo->editor();
}
return $title;
}
}

View File

@ -52,7 +52,7 @@ class MediaRevisions extends Revisions
global $lang;
$changelog =& $this->changelog;
// get revisions, and set correct pagenation parameters (first, hasNext)
// get revisions, and set correct pagination parameters (first, hasNext)
if ($first === null) $first = 0;
$hasNext = false;
$revisions = $this->getRevisions($first, $hasNext);
@ -70,13 +70,14 @@ class MediaRevisions extends Revisions
$form->addTagOpen('ul');
foreach ($revisions as $info) {
$rev = $info['date'];
$info['current'] = $changelog->isCurrentRevision($rev);
$RevInfo = new RevisionInfo($info);
$RevInfo->isCurrent($changelog->isCurrentRevision($rev));
$class = ($info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) ? 'minor' : '';
$class = ($RevInfo->val('type') === DOKU_CHANGE_TYPE_MINOR_EDIT) ? 'minor' : '';
$form->addTagOpen('li')->addClass($class);
$form->addTagOpen('div')->addClass('li');
if (isset($info['current'])) {
if ($RevInfo->isCurrent()) {
$form->addCheckbox('rev2[]')->val($rev);
} elseif (file_exists(mediaFN($this->id, $rev))) {
$form->addCheckbox('rev2[]')->val($rev);
@ -85,16 +86,15 @@ class MediaRevisions extends Revisions
}
$form->addHTML(' ');
$RevInfo = new RevisionInfo($info);
$html = implode(' ', [
$RevInfo->editDate(), // edit date and time
$RevInfo->difflinkRevision(), // link to diffview icon
$RevInfo->itemName(), // name of page or media
$RevInfo->showEditDate(), // edit date and time
$RevInfo->showIconCompareWithCurrent(), // link to diff view icon
$RevInfo->showFileName(), // name of page or media
'<div>',
$RevInfo->editSummary(), // edit summary
$RevInfo->editor(), // editor info
$RevInfo->sizechange(), // size change indicator
$RevInfo->currentIndicator(), // current indicator (only when k=1)
$RevInfo->showEditSummary(), // edit summary
$RevInfo->showEditor(), // editor info
$RevInfo->showSizechange(), // size change indicator
$RevInfo->showCurrentIndicator(), // current indicator (only when k=1)
'</div>',
]);
$form->addHTML($html);
@ -111,7 +111,7 @@ class MediaRevisions extends Revisions
print $form->toHTML('Revisions');
// provide navigation for pagenated revision list (of pages and/or media files)
// provide navigation for paginated revision list (of pages and/or media files)
print $this->navigation($first, $hasNext, function ($n) {
return media_managerURL(['first' => $n], '&', false, true);
});

View File

@ -20,9 +20,10 @@ class PageDiff extends Diff
/* @var PageChangeLog */
protected $changelog;
/* @var array */
protected $oldRevInfo;
protected $newRevInfo;
/* @var RevisionInfo older revision */
protected $RevInfo1;
/* @var RevisionInfo newer revision */
protected $RevInfo2;
/* @var string */
protected $text;
@ -60,36 +61,31 @@ class PageDiff extends Diff
*/
public function compareWith($text = null)
{
global $lang;
if (isset($text)) {
$this->text = $text;
$changelog =& $this->changelog;
// revision info of older file (left side)
$this->oldRevInfo = $changelog->getCurrentRevisionInfo() + [
// revision info object of older file (left side)
$this->RevInfo1 = new RevisionInfo($changelog->getCurrentRevisionInfo());
$this->RevInfo1->append([
'current' => true,
'rev' => '',
'navTitle' => $this->revisionTitle($changelog->getCurrentRevisionInfo()),
'text' => rawWiki($this->id),
];
]);
// revision info of newer file (right side)
$this->newRevInfo = [
'date' => null,
// revision info object of newer file (right side)
$this->RevInfo2 = new RevisionInfo();
$this->RevInfo2->append([
'date' => false,
//'ip' => '127.0.0.1',
//'type' => DOKU_CHANGE_TYPE_CREATE,
'id' => $this->id,
//'user' => '',
//'sum' => '',
//'extra' => '',
'sizechange' => strlen($this->text) - io_getSizeFile(wikiFN($this->id)),
'timestamp' => false,
'extra' => 'compareWith',
//'sizechange' => strlen($this->text) - io_getSizeFile(wikiFN($this->id)),
'current' => false,
'rev' => false,
'navTitle' => $lang['yours'],
'text' => cleanText($this->text),
];
]);
}
return $this;
}
@ -103,8 +99,8 @@ class PageDiff extends Diff
{
global $INPUT;
// requested rev or rev2
if (!isset($this->oldRevInfo, $this->newRevInfo)) {
// retrieve requested rev or rev2
if (!isset($this->RevInfo1, $this->RevInfo2)) {
parent::handle();
}
@ -120,7 +116,7 @@ class PageDiff extends Diff
if (!$INPUT->has('rev') && !$INPUT->has('rev2')) {
global $INFO, $REV;
if ($this->id == $INFO['id'])
$REV = $this->oldRev; // store revision back in $REV
$REV = $this->rev1; // store revision back in $REV
}
}
@ -133,51 +129,34 @@ class PageDiff extends Diff
$changelog =& $this->changelog;
// check validity of $this->{oldRev, newRev}
foreach (['oldRev','newRev'] as $rev) {
$revInfo = $rev.'Info';
$this->$revInfo = $changelog->getRevisionInfo((int)$this->$rev);
if (!$this->$revInfo) {
// invalid revision number, set dummy revInfo
$this->$revInfo = array(
'date' => time(),
'type' => '',
'timestamp' => false,
'rev' => false,
'text' => '',
'navTitle' => '&mdash;',
);
// create revision info object for older and newer sides
// RevInfo1 : older, left side
// RevInfo2 : newer, right side
$this->RevInfo1 = new RevisionInfo($changelog->getRevisionInfo($this->rev1));
$this->RevInfo2 = new RevisionInfo($changelog->getRevisionInfo($this->rev2));
foreach ([$this->RevInfo1, $this->RevInfo2] as $RevInfo) {
$isCurrent = $changelog->isCurrentRevision($RevInfo->val('date'));
$RevInfo->isCurrent($isCurrent);
if ($RevInfo->val('type') == DOKU_CHANGE_TYPE_DELETE || empty($RevInfo->val('type'))) {
$text = '';
} else {
$rev = $isCurrent ? '' : $RevInfo->val('date');
$text = rawWiki($this->id, $rev);
}
$RevInfo->append(['text' => $text]);
}
if ($this->newRev === false) {
// msg could displayed only when wrong url typed in browser address bar
if ($this->rev2 === false) {
msg(sprintf($lang['page_nonexist_rev'],
$this->id,
wl($this->id, ['do'=>'edit']),
$this->id), -1);
} elseif ($this->oldRevInfo == $this->newRevInfo) {
} elseif (!$this->rev1 || $this->rev1 == $this->rev2) {
msg('no way to compare when less than two revisions', -1);
}
foreach ([&$this->oldRevInfo, &$this->newRevInfo] as &$revInfo) {
// use timestamp and '' properly as $rev for the current file
$isCurrent = $changelog->isCurrentRevision($revInfo['date']);
$revInfo += [
'current' => $isCurrent,
'rev' => $isCurrent ? '' : $revInfo['date'],
];
// headline in the Diff view navigation
if (!isset($revInfo['navTitle'])) {
$revInfo['navTitle'] = $this->revisionTitle($revInfo);
}
if ($revInfo['type'] == DOKU_CHANGE_TYPE_DELETE) {
//attic stores complete last page version for a deleted page
$revInfo['text'] = '';
} else {
$revInfo['text'] = rawWiki($this->id, $revInfo['rev']);
}
}
}
/**
@ -191,33 +170,49 @@ class PageDiff extends Diff
*/
public function show()
{
if (!isset($this->oldRevInfo, $this->newRevInfo)) {
global $lang;
if (!isset($this->RevInfo1, $this->RevInfo2)) {
// retrieve form parameters: rev, rev2, difftype
$this->handle();
// prepare revision info of comparison pair, except PageConfrict or PageDraft
$this->preProcess();
}
// revision title
$rev1Title = trim($this->RevInfo1->showRevisionTitle() .' '. $this->RevInfo1->showCurrentIndicator());
$rev1Summary = ($this->RevInfo1->val('date'))
? $this->RevInfo1->showEditSummary() .' '. $this->RevInfo1->showEditor()
: '';
if ($this->RevInfo2->val('extra') == 'compareWith') {
$rev2Title = $lang['yours'];
$rev2Summary = '';
} else {
$rev2Title = trim($this->RevInfo2->showRevisionTitle() .' '. $this->RevInfo2->showCurrentIndicator());
$rev2Summary = ($this->RevInfo2->val('date'))
? $this->RevInfo2->showEditSummary() .' '. $this->RevInfo2->showEditor()
: '';
}
// create difference engine object
$Difference = new \Diff(
explode("\n", $this->oldRevInfo['text']),
explode("\n", $this->newRevInfo['text'])
explode("\n", $this->RevInfo1->val('text')),
explode("\n", $this->RevInfo2->val('text'))
);
// build paired navigation
[$navOlderRevisions, $navNewerRevisions] = $this->buildRevisionsNavigation();
[$rev1Navi, $rev2Navi] = $this->buildRevisionsNavigation();
// display intro
if ($this->preference['showIntro']) echo p_locale_xhtml('diff');
// print form to choose diff view type, and exact url reference to the view
if ($this->newRevInfo['rev'] !== false) {
$this->showDiffViewSelector();
}
$this->showDiffViewSelector();
// assign minor edit checker to the variable
$classEditType = function ($info) {
return ($info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) ? ' class="minor"' : '';
$classEditType = function ($changeType) {
return ($changeType === DOKU_CHANGE_TYPE_MINOR_EDIT) ? ' class="minor"' : '';
};
// display diff view table
@ -227,23 +222,26 @@ class PageDiff extends Diff
//navigation and header
switch ($this->preference['difftype']) {
case 'inline':
if ($this->newRevInfo['rev'] !== false) {
$title1 = $rev1Title . ($rev1Summary ? '<br />'.$rev1Summary : '');
$title2 = $rev2Title . ($rev2Summary ? '<br />'.$rev2Summary : '');
// no navigation for PageConflict or PageDraft
if ($this->RevInfo2->val('extra') !== 'compareWith') {
echo '<tr>'
.'<td class="diff-lineheader">-</td>'
.'<td class="diffnav">'. $navOlderRevisions .'</td>'
.'<td class="diffnav">'. $rev1Navi .'</td>'
.'</tr>';
echo '<tr>'
.'<th class="diff-lineheader">-</th>'
.'<th'.$classEditType($this->oldRevInfo).'>'.$this->oldRevInfo['navTitle'].'</th>'
.'<th'.$classEditType($this->RevInfo1->val('type')).'>'. $title1 .'</th>'
.'</tr>';
}
echo '<tr>'
.'<td class="diff-lineheader">+</td>'
.'<td class="diffnav">'. $navNewerRevisions .'</td>'
.'<td class="diffnav">'. $rev2Navi .'</td>'
.'</tr>';
echo '<tr>'
.'<th class="diff-lineheader">+</th>'
.'<th'.$classEditType($this->newRevInfo).'>'.$this->newRevInfo['navTitle'].'</th>'
.'<th'.$classEditType($this->RevInfo2->val('type')).'>'. $title2 .'</th>'
.'</tr>';
// create formatter object
$DiffFormatter = new InlineDiffFormatter();
@ -251,15 +249,18 @@ class PageDiff extends Diff
case 'sidebyside':
default:
if ($this->newRevInfo['rev'] !== false) {
$title1 = $rev1Title . ($rev1Summary ? ' '.$rev1Summary : '');
$title2 = $rev2Title . ($rev2Summary ? ' '.$rev2Summary : '');
// no navigation for PageConflict or PageDraft
if ($this->RevInfo2->val('extra') !== 'compareWith') {
echo '<tr>'
.'<td colspan="2" class="diffnav">'. $navOlderRevisions .'</td>'
.'<td colspan="2" class="diffnav">'. $navNewerRevisions .'</td>'
.'<td colspan="2" class="diffnav">'. $rev1Navi .'</td>'
.'<td colspan="2" class="diffnav">'. $rev2Navi .'</td>'
.'</tr>';
}
echo '<tr>'
.'<th colspan="2"'.$classEditType($this->oldRevInfo).'>'.$this->oldRevInfo['navTitle'].'</th>'
.'<th colspan="2"'.$classEditType($this->newRevInfo).'>'.$this->newRevInfo['navTitle'].'</th>'
.'<th colspan="2"'.$classEditType($this->RevInfo1->val('type')).'>'.$title1.'</th>'
.'<th colspan="2"'.$classEditType($this->RevInfo2->val('type')).'>'.$title2.'</th>'
.'</tr>';
// create formatter object
$DiffFormatter = new TableDiffFormatter();
@ -273,52 +274,6 @@ class PageDiff extends Diff
echo '</div>';
}
/**
* Revision Title for PageDiff table headline
*
* @param array $info Revision info structure of a page
* @return string
*/
protected function revisionTitle(array $info)
{
global $lang;
// use designated title when compare current page source with given text
if (array_key_exists('date', $info) && is_null($info['date'])) {
return $lang['yours'];
}
// revision info may have timestamp key when external edits occurred
$info['timestamp'] = $info['timestamp'] ?? true;
if (isset($info['date'])) {
$rev = $info['date'];
if ($info['timestamp'] === false) {
// exteranlly deleted or older file restored
$title = '<bdi><a class="wikilink2" href="'.wl($this->id).'">'
. $this->id .' ['. $lang['unknowndate'] .']'.'</a></bdi>';
} else {
$title = '<bdi><a class="wikilink1" href="'.wl($this->id, ['rev' => $rev]).'">'
. $this->id .' ['. dformat($rev) .']'.'</a></bdi>';
}
} else {
$title = '&mdash;';
}
if ($info['current']) {
$title .= '&nbsp;('.$lang['current'].')';
}
// append separator
$title .= ($this->preference['difftype'] === 'inline') ? ' ' : '<br />';
// supplement
if (isset($info['date'])) {
$RevInfo = new RevisionInfo($info);
$title .= $RevInfo->editSummary().' '.$RevInfo->editor();
}
return $title;
}
/**
* Print form to choose diff view type, and exact url reference to the view
*/
@ -326,16 +281,19 @@ class PageDiff extends Diff
{
global $lang;
// use timestamp for current revision
[$oldRev, $newRev] = [(int)$this->oldRevInfo['date'], (int)$this->newRevInfo['date']];
// no revisions selector for PageConflict or PageDraft
if ($this->RevInfo2->val('extra') == 'compareWith') return;
// use timestamp for current revision, date may be false when revisions < 2
[$rev1, $rev2] = [(int)$this->RevInfo1->val('date'), (int)$this->RevInfo2->val('date')];
echo '<div class="diffoptions group">';
// create the form to select difftype
$form = new Form(['action' => wl()]);
$form->setHiddenField('id', $this->id);
$form->setHiddenField('rev2[0]', $oldRev);
$form->setHiddenField('rev2[1]', $newRev);
$form->setHiddenField('rev2[0]', $rev1);
$form->setHiddenField('rev2[1]', $rev2);
$form->setHiddenField('do', 'diff');
$options = array(
'sidebyside' => $lang['diff_side'],
@ -350,14 +308,14 @@ class PageDiff extends Diff
// show exact url reference to the view when it is meaningful
echo '<p>';
if ($oldRev && $newRev) {
if ($rev1 && $rev2) {
// link to exactly this view FS#2835
$viewUrl = $this->diffViewlink('difflink', $oldRev, $newRev);
$viewUrl = $this->diffViewlink('difflink', $rev1, $rev2);
}
echo $viewUrl ?? '<br />';
echo '</p>';
echo '</div>'; // .diffoptions
echo '</div>';
}
/**
@ -372,67 +330,75 @@ class PageDiff extends Diff
{
$changelog =& $this->changelog;
if ($this->newRevInfo['rev'] === false) {
if ($this->RevInfo2->val('extra') == 'compareWith') {
// no revisions selector for PageConflict or PageDraft
return array('', '');
}
// use timestamp for current revision
[$oldRev, $newRev] = [(int)$this->oldRevInfo['date'], (int)$this->newRevInfo['date']];
// use timestamp for current revision, date may be false when revisions < 2
[$rev1, $rev2] = [(int)$this->RevInfo1->val('date'), (int)$this->RevInfo2->val('date')];
// retrieve revisions with additional info
[$oldRevs, $newRevs] = $changelog->getRevisionsAround($oldRev, $newRev);
// retrieve revisions used in dropdown selectors, even when rev1 or rev2 is false
[$revs1, $revs2] = $changelog->getRevisionsAround(
($rev1 ?: $changelog->currentRevision()),
($rev2 ?: $changelog->currentRevision())
);
// build options for dropdown selector
$olderRevisions = $this->buildRevisionOptions('older', $oldRevs);
$newerRevisions = $this->buildRevisionOptions('newer', $newRevs);
$rev1Options = $this->buildRevisionOptions('older', $revs1);
$rev2Options = $this->buildRevisionOptions('newer', $revs2);
// determine previous/next revisions
$index = array_search($oldRev, $oldRevs);
$oldPrevRev = ($index +1 < count($oldRevs)) ? $oldRevs[$index +1] : false;
$oldNextRev = ($index > 0) ? $oldRevs[$index -1] : false;
$index = array_search($newRev, $newRevs);
$newPrevRev = ($index +1 < count($newRevs)) ? $newRevs[$index +1] : false;
$newNextRev = ($index > 0) ? $newRevs[$index -1] : false;
// determine previous/next revisions (older/left side)
$rev1Prev = $rev1Next = false;
if (($index = array_search($rev1, $revs1)) !== false) {
$rev1Prev = ($index +1 < count($revs1)) ? $revs1[$index +1] : false;
$rev1Next = ($index > 0) ? $revs1[$index -1] : false;
}
// determine previous/next revisions (newer/right side)
$rev2Prev = $rev2Next = false;
if (($index = array_search($rev2, $revs2)) !== false) {
$rev2Prev = ($index +1 < count($revs2)) ? $revs2[$index +1] : false;
$rev2Next = ($index > 0) ? $revs2[$index -1] : false;
}
/*
* navigation UI for older revisions / Left side:
*/
$navOlderRevs = '';
$rev1Navi = '';
// move backward both side: ◀◀
if ($oldPrevRev && $newPrevRev)
$navOlderRevs .= $this->diffViewlink('diffbothprevrev', $oldPrevRev, $newPrevRev);
if ($rev1Prev && $rev2Prev)
$rev1Navi .= $this->diffViewlink('diffbothprevrev', $rev1Prev, $rev2Prev);
// move backward left side: ◀
if ($oldPrevRev)
$navOlderRevs .= $this->diffViewlink('diffprevrev', $oldPrevRev, $newRev);
if ($rev1Prev)
$rev1Navi .= $this->diffViewlink('diffprevrev', $rev1Prev, $rev2);
// dropdown
$navOlderRevs .= $this->buildDropdownSelector('older', $olderRevisions);
$rev1Navi .= $this->buildDropdownSelector('older', $rev1Options);
// move forward left side: ▶
if ($oldNextRev && ($oldNextRev < $newRev))
$navOlderRevs .= $this->diffViewlink('diffnextrev', $oldNextRev, $newRev);
if ($rev1Next && ($rev1Next < $rev2))
$rev1Navi .= $this->diffViewlink('diffnextrev', $rev1Next, $rev2);
/*
* navigation UI for newer revisions / Right side:
*/
$navNewerRevs = '';
$rev2Navi = '';
// move backward right side: ◀
if ($newPrevRev && ($oldRev < $newPrevRev))
$navNewerRevs .= $this->diffViewlink('diffprevrev', $oldRev, $newPrevRev);
if ($rev2Prev && ($rev1 < $rev2Prev))
$rev2Navi .= $this->diffViewlink('diffprevrev', $rev1, $rev2Prev);
// dropdown
$navNewerRevs .= $this->buildDropdownSelector('newer', $newerRevisions);
$rev2Navi .= $this->buildDropdownSelector('newer', $rev2Options);
// move forward right side: ▶
if ($newNextRev) {
if ($changelog->isCurrentRevision($newNextRev)) {
$navNewerRevs .= $this->diffViewlink('difflastrev', $oldRev, $newNextRev);
if ($rev2Next) {
if ($changelog->isCurrentRevision($rev2Next)) {
$rev2Navi .= $this->diffViewlink('difflastrev', $rev1, $rev2Next);
} else {
$navNewerRevs .= $this->diffViewlink('diffnextrev', $oldRev, $newNextRev);
$rev2Navi .= $this->diffViewlink('diffnextrev', $rev1, $rev2Next);
}
}
// move forward both side: ▶▶
if ($oldNextRev && $newNextRev)
$navNewerRevs .= $this->diffViewlink('diffbothnextrev', $oldNextRev, $newNextRev);
if ($rev1Next && $rev2Next)
$rev2Navi .= $this->diffViewlink('diffbothnextrev', $rev1Next, $rev2Next);
return array($navOlderRevs, $navNewerRevs);
return array($rev1Navi, $rev2Navi);
}
/**
@ -444,11 +410,11 @@ class PageDiff extends Diff
*/
protected function buildRevisionOptions($side, $revs)
{
$changelog =& $this->changelog;
$revisions = array();
// use timestamp for current revision, date may be false when revisions < 2
[$rev1, $rev2] = [(int)$this->RevInfo1->val('date'), (int)$this->RevInfo2->val('date')];
// use timestamp for current revision
[$oldRev, $newRev] = [(int)$this->oldRevInfo['date'], (int)$this->newRevInfo['date']];
$changelog =& $this->changelog;
$options = [];
foreach ($revs as $rev) {
$info = $changelog->getRevisionInfo($rev);
@ -459,7 +425,7 @@ class PageDiff extends Diff
// exteranlly deleted or older file restored
$date = preg_replace('/[0-9a-zA-Z]/','_', $date);
}
$revisions[$rev] = array(
$options[$rev] = array(
'label' => implode(' ', [
$date,
editorinfo($info['user'], true),
@ -467,13 +433,13 @@ class PageDiff extends Diff
]),
'attrs' => ['title' => $rev],
);
if (($side == 'older' && ($newRev && $rev >= $newRev))
||($side == 'newer' && ($rev <= $oldRev))
if (($side == 'older' && ($rev2 && $rev >= $rev2))
||($side == 'newer' && ($rev <= $rev1))
) {
$revisions[$rev]['attrs']['disabled'] = 'disabled';
$options[$rev]['attrs']['disabled'] = 'disabled';
}
}
return $revisions;
return $options;
}
/**
@ -485,25 +451,25 @@ class PageDiff extends Diff
*/
protected function buildDropdownSelector($side, $options)
{
// use timestamp for current revision, date may be false when revisions < 2
[$rev1, $rev2] = [(int)$this->RevInfo1->val('date'), (int)$this->RevInfo2->val('date')];
$form = new Form(['action' => wl($this->id)]);
$form->setHiddenField('id', $this->id);
$form->setHiddenField('do', 'diff');
$form->setHiddenField('difftype', $this->preference['difftype']);
// use timestamp for current revision
[$oldRev, $newRev] = [(int)$this->oldRevInfo['date'], (int)$this->newRevInfo['date']];
switch ($side) {
case 'older': // left side
$form->setHiddenField('rev2[1]', $newRev);
$form->setHiddenField('rev2[1]', $rev2);
$input = $form->addDropdown('rev2[0]', $options)
->val($oldRev)->addClass('quickselect');
->val($rev1)->addClass('quickselect');
$input->useInput(false); // inhibit prefillInput() during toHTML() process
break;
case 'newer': // right side
$form->setHiddenField('rev2[0]', $oldRev);
$form->setHiddenField('rev2[0]', $rev1);
$input = $form->addDropdown('rev2[1]', $options)
->val($newRev)->addClass('quickselect');
->val($rev2)->addClass('quickselect');
$input->useInput(false); // inhibit prefillInput() during toHTML() process
break;
}
@ -515,24 +481,26 @@ class PageDiff extends Diff
* Create html link to a diff view defined by two revisions
*
* @param string $linktype
* @param int $oldRev older revision
* @param int $newRev newer revision or null for diff with current revision
* @param int $rev1 older revision
* @param int $rev2 newer revision or null for diff with current revision
* @return string html of link to a diff view
*/
protected function diffViewlink($linktype, $oldRev, $newRev = null)
protected function diffViewlink($linktype, $rev1, $rev2 = null)
{
global $lang;
if ($newRev === null) {
if ($rev1 === false) return '';
if ($rev2 === null) {
$urlparam = array(
'do' => 'diff',
'rev' => $oldRev,
'rev' => $rev1,
'difftype' => $this->preference['difftype'],
);
} else {
$urlparam = array(
'do' => 'diff',
'rev2[0]' => $oldRev,
'rev2[1]' => $newRev,
'rev2[0]' => $rev1,
'rev2[1]' => $rev2,
'difftype' => $this->preference['difftype'],
);
}

View File

@ -50,7 +50,7 @@ class PageRevisions extends Revisions
global $lang, $REV;
$changelog =& $this->changelog;
// get revisions, and set correct pagenation parameters (first, hasNext)
// get revisions, and set correct pagination parameters (first, hasNext)
if ($first === null) $first = 0;
$hasNext = false;
$revisions = $this->getRevisions($first, $hasNext);
@ -69,13 +69,14 @@ class PageRevisions extends Revisions
$form->addTagOpen('ul');
foreach ($revisions as $info) {
$rev = $info['date'];
$info['current'] = $changelog->isCurrentRevision($rev);
$RevInfo = new RevisionInfo($info);
$RevInfo->isCurrent($changelog->isCurrentRevision($rev));
$class = ($info['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) ? 'minor' : '';
$class = ($RevInfo->val('type') === DOKU_CHANGE_TYPE_MINOR_EDIT) ? 'minor' : '';
$form->addTagOpen('li')->addClass($class);
$form->addTagOpen('div')->addClass('li');
if (isset($info['current'])) {
if ($RevInfo->isCurrent()) {
$form->addCheckbox('rev2[]')->val($rev);
} elseif ($rev == $REV) {
$form->addCheckbox('rev2[]')->val($rev)->attr('checked','checked');
@ -86,15 +87,14 @@ class PageRevisions extends Revisions
}
$form->addHTML(' ');
$RevInfo = new RevisionInfo($info);
$html = implode(' ', [
$RevInfo->editDate(true), // edit date and time
$RevInfo->difflinkRevision(), // link to diffview icon
$RevInfo->itemName(), // name of page or media
$RevInfo->editSummary(), // edit summary
$RevInfo->editor(), // editor info
$RevInfo->sizechange(), // size change indicator
$RevInfo->currentIndicator(), // current indicator (only when k=1)
$RevInfo->showEditDate(true), // edit date and time
$RevInfo->showIconCompareWithCurrent(), // link to diff view icon
$RevInfo->showFileName(), // name of page or media
$RevInfo->showEditSummary(), // edit summary
$RevInfo->showEditor(), // editor info
$RevInfo->showSizechange(), // size change indicator
$RevInfo->showCurrentIndicator(), // current indicator (only when k=1)
]);
$form->addHTML($html);
$form->addTagClose('div');

View File

@ -21,7 +21,7 @@ class Recent extends Ui
* Recent Ui constructor
*
* @param int $first skip the first n changelog lines
* @param string $show_changes type of changes to show; pages, mediafiles, or both
* @param string $show_changes type of changes to show; 'pages', 'mediafiles', or 'both'
*/
public function __construct($first = 0, $show_changes = 'both')
{
@ -45,7 +45,7 @@ class Recent extends Ui
global $conf, $lang;
global $ID;
// get recent items, and set correct pagenation parameters (first, hasNext)
// get recent items, and set correct pagination parameters (first, hasNext)
$first = $this->first;
$hasNext = false;
$recents = $this->getRecents($first, $hasNext);
@ -76,21 +76,21 @@ class Recent extends Ui
foreach ($recents as $recent) {
// check possible external edition for current page or media
$this->checkCurrentRevision($recent);
$recent['current'] = true;
$RevInfo = new RevisionInfo($recent);
$class = ($recent['type'] === DOKU_CHANGE_TYPE_MINOR_EDIT) ? 'minor': '';
$RevInfo->isCurrent(true);
$class = ($RevInfo->val('type') === DOKU_CHANGE_TYPE_MINOR_EDIT) ? 'minor': '';
$form->addTagOpen('li')->addClass($class);
$form->addTagOpen('div')->addClass('li');
$html = implode(' ', [
$RevInfo->itemIcon(), // filetype icon
$RevInfo->editDate(), // edit date and time
$RevInfo->difflinkRecent(), // link to diffview icon
$RevInfo->revisionlink(), // linkto revisions icon
$RevInfo->itemName(), // name of page or media
$RevInfo->editSummary(), // edit summary
$RevInfo->editor(), // editor info
$RevInfo->sizechange(), // size change indicator
$RevInfo->showFileIcon(), // filetype icon
$RevInfo->showEditDate(), // edit date and time
$RevInfo->showIconCompareWithPrevious(), // link to diff view icon
$RevInfo->showIconRevisions(), // link to revisions icon
$RevInfo->showFileName(), // name of page or media
$RevInfo->showEditSummary(), // edit summary
$RevInfo->showEditor(), // editor info
$RevInfo->showSizechange(), // size change indicator
]);
$form->addHTML($html);
$form->addTagClose('div');
@ -100,18 +100,18 @@ class Recent extends Ui
$form->addTagClose('div'); // close div class=no
// provide navigation for pagenated recent list (of pages and/or media files)
// provide navigation for paginated recent list (of pages and/or media files)
$form->addHTML($this->htmlNavigation($first, $hasNext));
print $form->toHTML('Recent');
}
/**
* Get recent items, and set correct pagenation parameters (first, hasNext)
* Get recent items, and set correct pagination parameters (first, hasNext)
*
* @param int $first
* @param bool $hasNext
* @return array recent items to be shown in a pagenated list
* @return array recent items to be shown in a paginated list
*
* @see also dokuwiki\Changelog::getRevisionInfo()
*/
@ -173,7 +173,7 @@ class Recent extends Ui
}
/**
* Navigation buttons for Pagenation (prev/next)
* Navigation buttons for Pagination (prev/next)
*
* @param int $first
* @param bool $hasNext

View File

@ -39,7 +39,7 @@ abstract class Revisions extends Ui
*
* @param int $first
* @param bool $hasNext
* @return array revisions to be shown in a pagenated list
* @return array revisions to be shown in a paginated list
* @see also https://www.dokuwiki.org/devel:changelog
*/
protected function getRevisions(&$first, &$hasNext)
@ -54,7 +54,7 @@ abstract class Revisions extends Ui
$num = $conf['recent'];
if ($first == 0) {
// add extrenal or existing last revision that is excluded from $changelog->getRevisions()
// add external or existing last revision that is excluded from $changelog->getRevisions()
if (array_key_exists('timestamp', $currentRevInfo) || (
$currentRevInfo['type'] != DOKU_CHANGE_TYPE_DELETE &&
$currentRevInfo['date'] == $changelog->lastRevision() )
@ -81,7 +81,7 @@ abstract class Revisions extends Ui
array_pop($revlist); // remove one additional log entry
}
// append each revison info array to the revisions
// append each revision info array to the revisions
foreach ($revlist as $rev) {
$revisions[] = $changelog->getRevisionInfo($rev);
}
@ -89,7 +89,7 @@ abstract class Revisions extends Ui
}
/**
* Navigation buttons for Pagenation (prev/next)
* Navigation buttons for Pagination (prev/next)
*
* @param int $first
* @param bool $hasNext

View File

@ -31,7 +31,7 @@ function parseChangelogLine($line) {
* @param String $id Name of the affected page
* @param String $type Type of the change see DOKU_CHANGE_TYPE_*
* @param String $summary Summary of the change
* @param mixed $extra In case of a revert the revision (timestmp) of the reverted page
* @param mixed $extra In case of a revert the revision (timestamp) of the reverted page
* @param array $flags Additional flags in a key value array.
* Available flags:
* - ExternalEdit - mark as an external edit.
@ -86,7 +86,7 @@ function addLogEntry(
}
/**
* Add's an entry to the media changelog
* Adds an entry to the media changelog
*
* @author Michael Hamann <michael@content-space.de>
* @author Andreas Gohr <andi@splitbrain.org>
@ -97,7 +97,7 @@ function addLogEntry(
* @param String $id Name of the affected page
* @param String $type Type of the change see DOKU_CHANGE_TYPE_*
* @param String $summary Summary of the change
* @param mixed $extra In case of a revert the revision (timestmp) of the reverted page
* @param mixed $extra In case of a revert the revision (timestamp) of the reverted page
* @param array $flags Additional flags in a key value array.
* Available flags:
* - (none, so far)
@ -343,7 +343,7 @@ function _handleRecent($line, $ns, $flags, &$seen) {
}
if ($recent['perms'] < AUTH_READ) return false;
// check existance
// check existence
if ($flags & RECENTS_SKIP_DELETED) {
$fn = (($flags & RECENTS_MEDIA_CHANGES) ? mediaFN($recent['id']) : wikiFN($recent['id']));
if (!file_exists($fn)) return false;