/** * Start the reversion process */ function _revert($revert, $filter) { echo '<hr /><br />'; echo '<p>' . $this->getLang('revstart') . '</p>'; echo '<ul>'; foreach ($revert as $id) { global $REV; // find the last non-spammy revision $data = ''; $pagelog = new PageChangeLog($id); $old = $pagelog->getRevisions(0, $this->max_revs); if (count($old)) { foreach ($old as $REV) { $data = rawWiki($id, $REV); if (strpos($data, $filter) === false) { break; } } } if ($data) { saveWikiText($id, $data, 'old revision restored', false); printf('<li><div class="li">' . $this->getLang('reverted') . '</div></li>', $id, $REV); } else { saveWikiText($id, '', '', false); printf('<li><div class="li">' . $this->getLang('removed') . '</div></li>', $id); } @set_time_limit(10); flush(); } echo '</ul>'; echo '<p>' . $this->getLang('revstop') . '</p>'; }
/** * Create html for revision navigation * * @param PageChangeLog $pagelog changelog object of current page * @param string $type inline vs sidebyside * @param int $l_rev left revision timestamp * @param int $r_rev right revision timestamp * @return string[] html of left and right navigation elements */ function html_diff_navigation($pagelog, $type, $l_rev, $r_rev) { global $INFO, $ID; // last timestamp is not in changelog, retrieve timestamp from metadata // note: when page is removed, the metadata timestamp is zero if (!$r_rev) { if (isset($INFO['meta']['last_change']['date'])) { $r_rev = $INFO['meta']['last_change']['date']; } else { $r_rev = 0; } } //retrieve revisions with additional info list($l_revs, $r_revs) = $pagelog->getRevisionsAround($l_rev, $r_rev); $l_revisions = array(); if (!$l_rev) { $l_revisions[0] = array(0, "", false); //no left revision given, add dummy } foreach ($l_revs as $rev) { $info = $pagelog->getRevisionInfo($rev); $l_revisions[$rev] = array($rev, dformat($info['date']) . ' ' . editorinfo($info['user'], true) . ' ' . $info['sum'], $r_rev ? $rev >= $r_rev : false); } $r_revisions = array(); if (!$r_rev) { $r_revisions[0] = array(0, "", false); //no right revision given, add dummy } foreach ($r_revs as $rev) { $info = $pagelog->getRevisionInfo($rev); $r_revisions[$rev] = array($rev, dformat($info['date']) . ' ' . editorinfo($info['user'], true) . ' ' . $info['sum'], $rev <= $l_rev); } //determine previous/next revisions $l_index = array_search($l_rev, $l_revs); $l_prev = $l_revs[$l_index + 1]; $l_next = $l_revs[$l_index - 1]; if ($r_rev) { $r_index = array_search($r_rev, $r_revs); $r_prev = $r_revs[$r_index + 1]; $r_next = $r_revs[$r_index - 1]; } else { //removed page if ($l_next) { $r_prev = $r_revs[0]; } else { $r_prev = null; } $r_next = null; } /* * Left side: */ $l_nav = ''; //move back if ($l_prev) { $l_nav .= html_diff_navigationlink($type, 'diffbothprevrev', $l_prev, $r_prev); $l_nav .= html_diff_navigationlink($type, 'diffprevrev', $l_prev, $r_rev); } //dropdown $form = new Doku_Form(array('action' => wl())); $form->addHidden('id', $ID); $form->addHidden('difftype', $type); $form->addHidden('rev2[1]', $r_rev); $form->addHidden('do', 'diff'); $form->addElement(form_makeListboxField('rev2[0]', $l_revisions, $l_rev, '', '', '', array('class' => 'quickselect'))); $form->addElement(form_makeButton('submit', 'diff', 'Go')); $l_nav .= $form->getForm(); //move forward if ($l_next && ($l_next < $r_rev || !$r_rev)) { $l_nav .= html_diff_navigationlink($type, 'diffnextrev', $l_next, $r_rev); } /* * Right side: */ $r_nav = ''; //move back if ($l_rev < $r_prev) { $r_nav .= html_diff_navigationlink($type, 'diffprevrev', $l_rev, $r_prev); } //dropdown $form = new Doku_Form(array('action' => wl())); $form->addHidden('id', $ID); $form->addHidden('rev2[0]', $l_rev); $form->addHidden('difftype', $type); $form->addHidden('do', 'diff'); $form->addElement(form_makeListboxField('rev2[1]', $r_revisions, $r_rev, '', '', '', array('class' => 'quickselect'))); $form->addElement(form_makeButton('submit', 'diff', 'Go')); $r_nav .= $form->getForm(); //move forward if ($r_next) { if ($pagelog->isCurrentRevision($r_next)) { $r_nav .= html_diff_navigationlink($type, 'difflastrev', $l_rev); //last revision is diff with current page } else { $r_nav .= html_diff_navigationlink($type, 'diffnextrev', $l_rev, $r_next); } $r_nav .= html_diff_navigationlink($type, 'diffbothnextrev', $l_next, $r_next); } return array($l_nav, $r_nav); }
/** * Returns a full page id * * @author Andreas Gohr <*****@*****.**> * * @param string $ns namespace which is context of id * @param string &$page (reference) relative page id, updated to resolved id * @param bool &$exists (reference) updated with existance of media */ function resolve_pageid($ns, &$page, &$exists, $rev = '', $date_at = false) { global $conf; global $ID; $exists = false; //empty address should point to current page if ($page === "") { $page = $ID; } //keep hashlink if exists then clean both parts if (strpos($page, '#')) { list($page, $hash) = explode('#', $page, 2); } else { $hash = ''; } $hash = cleanID($hash); $page = resolve_id($ns, $page, false); // resolve but don't clean, yet // get filename (calls clean itself) if ($rev !== '' && $date_at) { $pagelog = new PageChangeLog($page); $pagelog_rev = $pagelog->getLastRevisionAt($rev); if ($pagelog_rev !== false) { //something found $rev = $pagelog_rev; } } $file = wikiFN($page, $rev); // if ends with colon or slash we have a namespace link if (in_array(substr($page, -1), array(':', ';')) || $conf['useslash'] && substr($page, -1) == '/') { if (page_exists($page . $conf['start'], $rev, true, $date_at)) { // start page inside namespace $page = $page . $conf['start']; $exists = true; } elseif (page_exists($page . noNS(cleanID($page)), $rev, true, $date_at)) { // page named like the NS inside the NS $page = $page . noNS(cleanID($page)); $exists = true; } elseif (page_exists($page, $rev, true, $date_at)) { // page like namespace exists $page = $page; $exists = true; } else { // fall back to default $page = $page . $conf['start']; } } else { //check alternative plural/nonplural form if (!@file_exists($file)) { if ($conf['autoplural']) { if (substr($page, -1) == 's') { $try = substr($page, 0, -1); } else { $try = $page . 's'; } if (page_exists($try, $rev, true, $date_at)) { $page = $try; $exists = true; } } } else { $exists = true; } } // now make sure we have a clean page $page = cleanID($page); //add hash if any if (!empty($hash)) { $page .= '#' . $hash; } }
if ($DATE_AT) { $date_parse = strtotime($DATE_AT); if ($date_parse) { $DATE_AT = $date_parse; } else { // check for UNIX Timestamp $date_parse = @date('Ymd', $DATE_AT); if (!$date_parse || $date_parse === '19700101') { msg(sprintf($lang['unable_to_parse_date'], $DATE_AT)); $DATE_AT = null; } } } //check for existing $REV related to $DATE_AT if ($DATE_AT) { $pagelog = new PageChangeLog($ID); $rev_t = $pagelog->getLastRevisionAt($DATE_AT); if ($rev_t === '') { //current revision $REV = null; $DATE_AT = null; } else { if ($rev_t === false) { //page did not exist $rev_n = $pagelog->getRelativeRevision($DATE_AT, +1); msg(sprintf($lang['page_nonexist_rev'], strftime($conf['dformat'], $DATE_AT), wl($ID, array('rev' => $rev_n)), strftime($conf['dformat'], $rev_n))); $REV = $DATE_AT; //will result in a page not exists message } else { $REV = $rev_t; }
/** * Checks if the current page version is newer than the last entry in the page's * changelog. If so, we assume it has been an external edit and we create an * attic copy and add a proper changelog line. * * This check is only executed when the page is about to be saved again from the * wiki, triggered in @see saveWikiText() * * @param string $id the page ID */ function detectExternalEdit($id) { global $lang; $fileLastMod = wikiFN($id); $lastMod = @filemtime($fileLastMod); // from page $pagelog = new PageChangeLog($id, 1024); $lastRev = $pagelog->getRevisions(-1, 1); // from changelog $lastRev = (int) (empty($lastRev) ? 0 : $lastRev[0]); if (!file_exists(wikiFN($id, $lastMod)) && file_exists($fileLastMod) && $lastMod >= $lastRev) { // add old revision to the attic if missing saveOldRevision($id); // add a changelog entry if this edit came from outside dokuwiki if ($lastMod > $lastRev) { $fileLastRev = wikiFN($id, $lastRev); $revinfo = $pagelog->getRevisionInfo($lastRev); if (empty($lastRev) || !file_exists($fileLastRev) || $revinfo['type'] == DOKU_CHANGE_TYPE_DELETE) { $filesize_old = 0; } else { $filesize_old = io_getSizeFile($fileLastRev); } $filesize_new = filesize($fileLastMod); $sizechange = $filesize_new - $filesize_old; addLogEntry($lastMod, $id, DOKU_CHANGE_TYPE_EDIT, $lang['external_edit'], '', array('ExternalEdit' => true), $sizechange); // remove soon to be stale instructions $cache = new cache_instructions($id, $fileLastMod); $cache->removeCache(); } } }
/** * sometimes chuncksize is set to true */ function test_chuncksizetrue() { $rev = 1362525899; $infoexpected = parseChangelogLine($this->logline); $pagelog = new PageChangeLog($this->pageid, true); $info = $pagelog->getRevisionInfo($rev); $this->assertEquals($infoexpected, $info); }
/** * Send a digest mail * * Sends a digest mail showing a bunch of changes of a single page. Basically the same as send_diff() * but determines the last known revision first * * @author Adrian Lang <*****@*****.**> * * @param string $subscriber_mail The target mail address * @param string $id The ID * @param int $lastupdate Time of the last notification * @return bool */ protected function send_digest($subscriber_mail, $id, $lastupdate) { $pagelog = new PageChangeLog($id); $n = 0; do { $rev = $pagelog->getRevisions($n++, 1); $rev = count($rev) > 0 ? $rev[0] : null; } while (!is_null($rev) && $rev > $lastupdate); return $this->send_diff($subscriber_mail, 'subscr_digest', $id, $rev); }
/** * Add recent changed pages to a feed object * * @author Andreas Gohr <*****@*****.**> * @param FeedCreator $rss the FeedCreator Object * @param array $data the items to add * @param array $opt the feed options */ function rss_buildItems(&$rss, &$data, $opt) { global $conf; global $lang; /* @var DokuWiki_Auth_Plugin $auth */ global $auth; $eventData = array('rss' => &$rss, 'data' => &$data, 'opt' => &$opt); $event = new Doku_Event('FEED_DATA_PROCESS', $eventData); if ($event->advise_before(false)) { foreach ($data as $ditem) { if (!is_array($ditem)) { // not an array? then only a list of IDs was given $ditem = array('id' => $ditem); } $item = new FeedItem(); $id = $ditem['id']; if (!$ditem['media']) { $meta = p_get_metadata($id); } else { $meta = array(); } // add date if ($ditem['date']) { $date = $ditem['date']; } elseif ($ditem['media']) { $date = @filemtime(mediaFN($id)); } elseif (file_exists(wikiFN($id))) { $date = @filemtime(wikiFN($id)); } elseif ($meta['date']['modified']) { $date = $meta['date']['modified']; } else { $date = 0; } if ($date) { $item->date = date('r', $date); } // add title if ($conf['useheading'] && $meta['title']) { $item->title = $meta['title']; } else { $item->title = $ditem['id']; } if ($conf['rss_show_summary'] && !empty($ditem['sum'])) { $item->title .= ' - ' . strip_tags($ditem['sum']); } // add item link switch ($opt['link_to']) { case 'page': if ($ditem['media']) { $item->link = media_managerURL(array('image' => $id, 'ns' => getNS($id), 'rev' => $date), '&', true); } else { $item->link = wl($id, 'rev=' . $date, true, '&'); } break; case 'rev': if ($ditem['media']) { $item->link = media_managerURL(array('image' => $id, 'ns' => getNS($id), 'rev' => $date, 'tab_details' => 'history'), '&', true); } else { $item->link = wl($id, 'do=revisions&rev=' . $date, true, '&'); } break; case 'current': if ($ditem['media']) { $item->link = media_managerURL(array('image' => $id, 'ns' => getNS($id)), '&', true); } else { $item->link = wl($id, '', true, '&'); } break; case 'diff': default: if ($ditem['media']) { $item->link = media_managerURL(array('image' => $id, 'ns' => getNS($id), 'rev' => $date, 'tab_details' => 'history', 'mediado' => 'diff'), '&', true); } else { $item->link = wl($id, 'rev=' . $date . '&do=diff', true, '&'); } } // add item content switch ($opt['item_content']) { case 'diff': case 'htmldiff': if ($ditem['media']) { $medialog = new MediaChangeLog($id); $revs = $medialog->getRevisions(0, 1); $rev = $revs[0]; $src_r = ''; $src_l = ''; if ($size = media_image_preview_size($id, '', new JpegMeta(mediaFN($id)), 300)) { $more = 'w=' . $size[0] . '&h=' . $size[1] . '&t=' . @filemtime(mediaFN($id)); $src_r = ml($id, $more, true, '&', true); } if ($rev && ($size = media_image_preview_size($id, $rev, new JpegMeta(mediaFN($id, $rev)), 300))) { $more = 'rev=' . $rev . '&w=' . $size[0] . '&h=' . $size[1]; $src_l = ml($id, $more, true, '&', true); } $content = ''; if ($src_r) { $content = '<table>'; $content .= '<tr><th width="50%">' . $rev . '</th>'; $content .= '<th width="50%">' . $lang['current'] . '</th></tr>'; $content .= '<tr align="center"><td><img src="' . $src_l . '" alt="" /></td><td>'; $content .= '<img src="' . $src_r . '" alt="' . $id . '" /></td></tr>'; $content .= '</table>'; } } else { require_once DOKU_INC . 'inc/DifferenceEngine.php'; $pagelog = new PageChangeLog($id); $revs = $pagelog->getRevisions(0, 1); $rev = $revs[0]; if ($rev) { $df = new Diff(explode("\n", rawWiki($id, $rev)), explode("\n", rawWiki($id, ''))); } else { $df = new Diff(array(''), explode("\n", rawWiki($id, ''))); } if ($opt['item_content'] == 'htmldiff') { // note: no need to escape diff output, TableDiffFormatter provides 'safe' html $tdf = new TableDiffFormatter(); $content = '<table>'; $content .= '<tr><th colspan="2" width="50%">' . $rev . '</th>'; $content .= '<th colspan="2" width="50%">' . $lang['current'] . '</th></tr>'; $content .= $tdf->format($df); $content .= '</table>'; } else { // note: diff output must be escaped, UnifiedDiffFormatter provides plain text $udf = new UnifiedDiffFormatter(); $content = "<pre>\n" . hsc($udf->format($df)) . "\n</pre>"; } } break; case 'html': if ($ditem['media']) { if ($size = media_image_preview_size($id, '', new JpegMeta(mediaFN($id)))) { $more = 'w=' . $size[0] . '&h=' . $size[1] . '&t=' . @filemtime(mediaFN($id)); $src = ml($id, $more, true, '&', true); $content = '<img src="' . $src . '" alt="' . $id . '" />'; } else { $content = ''; } } else { if (@filemtime(wikiFN($id)) === $date) { $content = p_wiki_xhtml($id, '', false); } else { $content = p_wiki_xhtml($id, $date, false); } // no TOC in feeds $content = preg_replace('/(<!-- TOC START -->).*(<!-- TOC END -->)/s', '', $content); // add alignment for images $content = preg_replace('/(<img .*?class="medialeft")/s', '\\1 align="left"', $content); $content = preg_replace('/(<img .*?class="mediaright")/s', '\\1 align="right"', $content); // make URLs work when canonical is not set, regexp instead of rerendering! if (!$conf['canonical']) { $base = preg_quote(DOKU_REL, '/'); $content = preg_replace('/(<a href|<img src)="(' . $base . ')/s', '$1="' . DOKU_URL, $content); } } break; case 'abstract': default: if ($ditem['media']) { if ($size = media_image_preview_size($id, '', new JpegMeta(mediaFN($id)))) { $more = 'w=' . $size[0] . '&h=' . $size[1] . '&t=' . @filemtime(mediaFN($id)); $src = ml($id, $more, true, '&', true); $content = '<img src="' . $src . '" alt="' . $id . '" />'; } else { $content = ''; } } else { $content = $meta['description']['abstract']; } } $item->description = $content; //FIXME a plugin hook here could be senseful // add user # FIXME should the user be pulled from metadata as well? $user = @$ditem['user']; // the @ spares time repeating lookup $item->author = ''; if ($user && $conf['useacl'] && $auth) { $userInfo = $auth->getUserData($user); if ($userInfo) { switch ($conf['showuseras']) { case 'username': case 'username_link': $item->author = $userInfo['name']; break; default: $item->author = $user; break; } } else { $item->author = $user; } if ($userInfo && !$opt['guardmail']) { $item->authorEmail = $userInfo['mail']; } else { //cannot obfuscate because some RSS readers may check validity $item->authorEmail = $user . '@' . $ditem['ip']; } } elseif ($user) { // this happens when no ACL but some Apache auth is used $item->author = $user; $item->authorEmail = $user . '@' . $ditem['ip']; } else { $item->authorEmail = 'anonymous@' . $ditem['ip']; } // add category if (isset($meta['subject'])) { $item->category = $meta['subject']; } else { $cat = getNS($id); if ($cat) { $item->category = $cat; } } // finally add the item to the feed object, after handing it to registered plugins $evdata = array('item' => &$item, 'opt' => &$opt, 'ditem' => &$ditem, 'rss' => &$rss); $evt = new Doku_Event('FEED_ITEM_ADD', $evdata); if ($evt->advise_before()) { $rss->addItem($item); } $evt->advise_after(); // for completeness } } $event->advise_after(); }
/** * Returns a list of available revisions of a given wiki page * * @author Michael Klier <*****@*****.**> * * @param string $id page id * @param int $first skip the first n changelog lines * @return array * @throws RemoteAccessDeniedException no read access for page * @throws RemoteException empty id */ function pageVersions($id, $first) { $id = $this->resolvePageId($id); if (auth_quickaclcheck($id) < AUTH_READ) { throw new RemoteAccessDeniedException('You are not allowed to read this page', 111); } global $conf; $versions = array(); if (empty($id)) { throw new RemoteException('Empty page ID', 131); } $pagelog = new PageChangeLog($id); $revisions = $pagelog->getRevisions($first, $conf['recent'] + 1); if (count($revisions) == 0 && $first != 0) { $first = 0; $revisions = $pagelog->getRevisions($first, $conf['recent'] + 1); } if (count($revisions) > 0 && $first == 0) { array_unshift($revisions, ''); // include current revision if (count($revisions) > $conf['recent']) { array_pop($revisions); // remove extra log entry } } if (count($revisions) > $conf['recent']) { array_pop($revisions); // remove extra log entry } if (!empty($revisions)) { foreach ($revisions as $rev) { $file = wikiFN($id, $rev); $time = @filemtime($file); // we check if the page actually exists, if this is not the // case this can lead to less pages being returned than // specified via $conf['recent'] if ($time) { $pagelog->setChunkSize(1024); $info = $pagelog->getRevisionInfo($time); if (!empty($info)) { $data = array(); $data['user'] = $info['user']; $data['ip'] = $info['ip']; $data['type'] = $info['type']; $data['sum'] = $info['sum']; $data['modified'] = $this->api->toDate($info['date']); $data['version'] = $info['date']; array_push($versions, $data); } } } return $versions; } else { return array(); } }
/** * Return a list of page revisions numbers * Does not guarantee that the revision exists in the attic, * only that a line with the date exists in the changelog. * By default the current revision is skipped. * * The current revision is automatically skipped when the page exists. * See $INFO['meta']['last_change'] for the current revision. * * 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. * * @deprecated 2013-11-20 * * @author Ben Coburn <*****@*****.**> * @author Kate Arzamastseva <*****@*****.**> * * @param string $id the page of interest * @param int $first skip the first n changelog lines * @param int $num number of revisions to return * @param int $chunk_size * @param bool $media * @return array */ function getRevisions($id, $first, $num, $chunk_size = 8192, $media = false) { dbg_deprecated('class PageChangeLog or class MediaChangelog'); if ($media) { $changelog = new MediaChangeLog($id, $chunk_size); } else { $changelog = new PageChangeLog($id, $chunk_size); } return $changelog->getRevisions($first, $num); }
/** * * Show diff * between current page version and provided $text * or between the revisions provided via GET or POST * * @author Andreas Gohr <*****@*****.**> * @param string $text when non-empty: compare with this text with most current version * @param bool $intro display the intro text * @param string $type type of the diff (inline or sidebyside) */ function revisionsfull_html_diff($text = '', $intro = true, $type = null) { global $ID; global $REV; global $lang; global $INPUT; global $INFO; $pagelog = new PageChangeLog($ID); /* * Determine diff type */ if (!$type) { $type = $INPUT->str('difftype'); if (empty($type)) { $type = get_doku_pref('difftype', $type); if (empty($type) && $INFO['ismobile']) { $type = 'inline'; } } } if (!in_array($type, array('inline', 'sidebyside'))) { $type = 'full'; } /* * Determine requested revision(s) */ // we're trying to be clever here, revisions to compare can be either // given as rev and rev2 parameters, with rev2 being optional. Or in an // array in rev2. $rev1 = $REV; $rev2 = $INPUT->ref('rev2'); if (is_array($rev2)) { $rev1 = (int) $rev2[0]; $rev2 = (int) $rev2[1]; if (!$rev1) { $rev1 = $rev2; unset($rev2); } } else { $rev2 = $INPUT->int('rev2'); } /* * Determine left and right revision, its texts and the header */ $r_minor = ''; $l_minor = ''; if ($text) { // compare text to the most current revision $l_rev = ''; $l_text = rawWiki($ID, ''); $l_head = '<a class="wikilink1" href="' . wl($ID) . '">' . $ID . ' ' . dformat((int) @filemtime(wikiFN($ID))) . '</a> ' . $lang['current']; $r_rev = ''; $r_text = cleanText($text); $r_head = $lang['yours']; } else { if ($rev1 && isset($rev2) && $rev2) { // two specific revisions wanted // make sure order is correct (older on the left) if ($rev1 < $rev2) { $l_rev = $rev1; $r_rev = $rev2; } else { $l_rev = $rev2; $r_rev = $rev1; } } elseif ($rev1) { // single revision given, compare to current $r_rev = ''; $l_rev = $rev1; } else { // no revision was given, compare previous to current $r_rev = ''; $revs = $pagelog->getRevisions(0, 1); $l_rev = $revs[0]; $REV = $l_rev; // store revision back in $REV } // when both revisions are empty then the page was created just now if (!$l_rev && !$r_rev) { $l_text = ''; } else { $l_text = rawWiki($ID, $l_rev); } $r_text = rawWiki($ID, $r_rev); list($l_head, $r_head, $l_minor, $r_minor) = html_diff_head($l_rev, $r_rev, null, false, $type == 'inline'); } /* * Build navigation */ $l_nav = ''; $r_nav = ''; if (!$text) { list($l_nav, $r_nav) = html_diff_navigation($pagelog, $type, $l_rev, $r_rev); } /* * Create diff object and the formatter */ $diff = new Diff(explode("\n", $l_text), explode("\n", $r_text)); if ($type == 'inline') { $diffformatter = new InlineDiffFormatter(); } elseif ($type == 'sidebyside') { $diffformatter = new TableDiffFormatter(); } else { $diffformatter = new FullTableDiffFormatter(); } /* * Display intro */ if ($intro) { print p_locale_xhtml('diff'); } /* * Display type and exact reference */ if (!$text) { ptln('<div class="diffoptions group">'); $form = new Doku_Form(array('action' => wl())); $form->addHidden('id', $ID); $form->addHidden('rev2[0]', $l_rev); $form->addHidden('rev2[1]', $r_rev); $form->addHidden('do', 'diff'); $form->addElement(form_makeListboxField('difftype', array('full' => 'Full Side by Side', 'sidebyside' => $lang['diff_side'], 'inline' => $lang['diff_inline']), $type, $lang['diff_type'], '', '', array('class' => 'quickselect'))); $form->addElement(form_makeButton('submit', 'diff', 'Go')); $form->printForm(); ptln('<p>'); // link to exactly this view FS#2835 echo html_diff_navigationlink($type, 'difflink', $l_rev, $r_rev ? $r_rev : $INFO['currentrev']); ptln('</p>'); ptln('</div>'); // .diffoptions } /* * Display diff view table */ ?> <div class="table"> <table class="diff diff_<?php echo $type; ?> "> <?php //navigation and header if ($type == 'inline') { if (!$text) { ?> <tr> <td class="diff-lineheader">-</td> <td class="diffnav"><?php echo $l_nav; ?> </td> </tr> <tr> <th class="diff-lineheader">-</th> <th <?php echo $l_minor; ?> > <?php echo $l_head; ?> </th> </tr> <?php } ?> <tr> <td class="diff-lineheader">+</td> <td class="diffnav"><?php echo $r_nav; ?> </td> </tr> <tr> <th class="diff-lineheader">+</th> <th <?php echo $r_minor; ?> > <?php echo $r_head; ?> </th> </tr> <?php } else { if (!$text) { ?> <tr> <td colspan="2" class="diffnav"><?php echo $l_nav; ?> </td> <td colspan="2" class="diffnav"><?php echo $r_nav; ?> </td> </tr> <?php } ?> <tr> <th colspan="2" <?php echo $l_minor; ?> > <?php echo $l_head; ?> </th> <th colspan="2" <?php echo $r_minor; ?> > <?php echo $r_head; ?> </th> </tr> <?php } //diff view echo html_insert_softbreaks($diffformatter->format($diff)); ?> </table> </div> <?php }
function handle_display_banner(&$event, $param) { global $ID, $REV, $INFO; if ($event->data != 'show') { return; } if (!$INFO['exists']) { return; } $m = p_get_metadata($ID); $changelog = new PageChangeLog($ID); //sprawdź status aktualnej strony if ($REV != 0) { $ch = $changelog->getRevisionInfo($REV); $sum = $ch['sum']; } else { $sum = $m['last_change']['sum']; } if ($sum != APPRVOED) { $class = 'approved_no'; $last_approved_rev = $this->find_lastest_approved(); } ptln('<div class="approval ' . ($sum == APPROVED ? 'approved_yes' : 'approved_no') . '">'); tpl_pageinfo(); ptln(' | '); if ($sum == APPROVED) { ptln('<span>' . $this->getLang('approved') . '</span>'); if ($REV != 0 && auth_quickaclcheck($ID) > AUTH_READ) { ptln('<a href="' . wl($ID) . '">'); ptln($this->getLang($m['last_change']['sum'] == APPROVED ? 'newest_approved' : 'newest_draft')); ptln('</a>'); } else { if ($REV != 0 && $REV != $last_approved_rev) { ptln('<a href="' . wl($ID) . '">'); ptln($this->getLang('newest_approved')); ptln('</a>'); } } } else { ptln('<span>' . $this->getLang('draft') . '</span>'); if (isset($last_approved_rev)) { if ($last_approved_rev != 0) { ptln('<a href="' . wl($ID, array('rev' => $last_approved_rev)) . '">'); } else { ptln('<a href="' . wl($ID) . '">'); } ptln($this->getLang('newest_approved')); ptln('</a>'); } else { ptln('<a href="' . wl($ID) . '">'); ptln($this->getLang('newest_draft')); ptln('</a>'); } //można zatwierdzać tylko najnowsze strony if ($REV == 0 && $this->can_approve()) { ptln('<a href="' . wl($ID, array('rev' => $last_approved_rev, 'do' => 'diff', 'approve' => 'approve')) . '">'); ptln($this->getLang('approve')); ptln('</a>'); } } ptln('</div>'); }
/** * When rev1 > rev2, their order is changed */ function test_request_wrong_order_revs() { $rev1 = 1362527164; $rev2 = 1362526767; $max = 10; $revsexpected = array(array_slice($this->revsexpected, 8, 11), array_slice($this->revsexpected, 5, 11)); $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192); $revs = $pagelog->getRevisionsAround($rev1, $rev2, $max); $this->assertEquals($revsexpected, $revs); $pagelog = new PageChangeLog($this->pageid, $chunk_size = 512); $revs = $pagelog->getRevisionsAround($rev1, $rev2, $max); $this->assertEquals($revsexpected, $revs); $pagelog = new PageChangeLog($this->pageid, $chunk_size = 20); $revs = $pagelog->getRevisionsAround($rev1, $rev2, $max); $this->assertEquals($revsexpected, $revs); }
function test_notexistingcurrentpage() { $rev = 1385051947; $currentexpected = false; $pagelog = new PageChangeLog('nonexistingpage', $chunk_size = 8192); $current = $pagelog->isCurrentRevision($rev); $this->assertEquals($currentexpected, $current); }
function _exportPostcontent($exporter) { global $ID, $INFO, $REV, $conf; $exporter->setParameters('Article: ' . $INFO['meta']['title'] . ($REV ? ' (rev ' . $REV . ')' : ''), $this->_getDokuUrl(), $this->_getDokuUrl() . 'doku.php?', 'utf-8', $this->agentlink); // create user object // $id, $uri, $name, $email, $homepage='', $foaf_uri='', $role=false, $nick='', $sioc_url='', $foaf_url='' $dwuserpage_id = cleanID($this->getConf('userns')) . ($conf['useslash'] ? '/' : ':') . $INFO['editor']; /* if ($INFO['editor'] && $this->getConf('userns')) $pageuser = new SIOCUser($INFO['editor'], normalizeUri(getAbsUrl(exportlink($dwuserpage_id, 'siocxml', array('type'=>'user'), false, '&'))), // user page $INFO['meta']['contributor'][$INFO['editor']], getDwUserInfo($dwuserpage_id,$this,'mail'), '', // no homepage is saved for dokuwiki user '#'.$INFO['editor'], // local uri false, // no roles right now '', // no nick name is saved for dokuwiki user normalizeUri($exporter->siocURL('user', $dwuserpage_id)) ); */ // create wiki page object $wikipage = new SIOCDokuWikiArticle($ID, normalizeUri($exporter->siocURL('post', $ID . ($REV ? $exporter->_urlseparator . 'rev' . $exporter->_urlequal . $REV : ''))), $INFO['meta']['title'] . ($REV ? ' (rev ' . $REV . ')' : ''), rawWiki($ID, $REV)); /* encoded content */ $wikipage->addContentEncoded(p_cached_output(wikiFN($ID, $REV), 'xhtml')); /* created */ if (isset($INFO['meta']['date']['created'])) { $wikipage->addCreated(date('c', $INFO['meta']['date']['created'])); } /* or modified */ if (isset($INFO['meta']['date']['modified'])) { $wikipage->addModified(date('c', $INFO['meta']['date']['modified'])); } /* creator/modifier */ if ($INFO['editor'] && $this->getConf('userns')) { $wikipage->addCreator(array('foaf:maker' => '#' . $INFO['editor'], 'sioc:modifier' => $dwuserpage_id)); } /* is creator */ if (isset($INFO['meta']['date']['created'])) { $wikipage->isCreator(); } /* intern wiki links */ $wikipage->addLinks($INFO['meta']['relation']['references']); // contributors - only for last revision b/c of wrong meta data for older revisions if (!$REV && $this->getConf('userns') && isset($INFO['meta']['contributor'])) { $cont_temp = array(); $cont_ns = $this->getConf('userns') . ($conf['useslash'] ? '/' : ':'); foreach ($INFO['meta']['contributor'] as $cont_id => $cont_name) { $cont_temp[$cont_ns . $cont_id] = $cont_name; } $wikipage->addContributors($cont_temp); } // backlinks - only for last revision if (!$REV) { require_once DOKU_INC . 'inc/fulltext.php'; $backlinks = ft_backlinks($ID); if (count($backlinks) > 0) { $wikipage->addBacklinks($backlinks); } } // TODO: addLinksExtern /* previous and next revision */ $changelog = new PageChangeLog($ID); $pagerevs = $changelog->getRevisions(0, $conf['recent'] + 1); $prevrev = false; $nextrev = false; if (!$REV) { // latest revision, previous rev is on top in array $prevrev = 0; } else { // other revision $currentrev = array_search($REV, $pagerevs); if ($currentrev !== false) { $prevrev = $currentrev + 1; $nextrev = $currentrev - 1; } } if ($prevrev !== false && $prevrev > -1 && page_exists($ID, $pagerevs[$prevrev])) { /* previous revision*/ $wikipage->addVersionPrevious($pagerevs[$prevrev]); } if ($nextrev !== false && $nextrev > -1 && page_exists($ID, $pagerevs[$nextrev])) { /* next revision*/ $wikipage->addVersionNext($pagerevs[$nextrev]); } /* latest revision */ if ($REV) { $wikipage->addVersionLatest(); } // TODO: topics /* has_container */ if ($INFO['namespace']) { $wikipage->addContainer($INFO['namespace']); } /* has_space */ if ($this->getConf('owners')) { $wikipage->addSite($this->getConf('owners')); } // TODO: dc:contributor / has_modifier // TODO: attachment (e.g. pictures in that dwns) // add wiki page to exporter $exporter->addObject($wikipage); //if ($INFO['editor'] && $this->getConf('userns')) $exporter->addObject($pageuser); return $exporter; }
/** * Saves a wikitext by calling io_writeWikiPage. * Also directs changelog and attic updates. * * @author Andreas Gohr <*****@*****.**> * @author Ben Coburn <*****@*****.**> * * @param string $id page id * @param string $text wikitext being saved * @param string $summary summary of text update * @param bool $minor mark this saved version as minor update */ function saveWikiText($id, $text, $summary, $minor = false) { /* Note to developers: This code is subtle and delicate. Test the behavior of the attic and changelog with dokuwiki and external edits after any changes. External edits change the wiki page directly without using php or dokuwiki. */ global $conf; global $lang; global $REV; /* @var Input $INPUT */ global $INPUT; // ignore if no changes were made if ($text == rawWiki($id, '')) { return; } $file = wikiFN($id); $old = @filemtime($file); // from page $wasRemoved = trim($text) == ''; // check for empty or whitespace only $wasCreated = !file_exists($file); $wasReverted = $REV == true; $pagelog = new PageChangeLog($id, 1024); $newRev = false; $oldRev = $pagelog->getRevisions(-1, 1); // from changelog $oldRev = (int) (empty($oldRev) ? 0 : $oldRev[0]); if (!file_exists(wikiFN($id, $old)) && file_exists($file) && $old >= $oldRev) { // add old revision to the attic if missing saveOldRevision($id); // add a changelog entry if this edit came from outside dokuwiki if ($old > $oldRev) { addLogEntry($old, $id, DOKU_CHANGE_TYPE_EDIT, $lang['external_edit'], '', array('ExternalEdit' => true)); // remove soon to be stale instructions $cache = new cache_instructions($id, $file); $cache->removeCache(); } } if ($wasRemoved) { // Send "update" event with empty data, so plugins can react to page deletion $data = array(array($file, '', false), getNS($id), noNS($id), false); trigger_event('IO_WIKIPAGE_WRITE', $data); // pre-save deleted revision @touch($file); clearstatcache(); $newRev = saveOldRevision($id); // remove empty file @unlink($file); // don't remove old meta info as it should be saved, plugins can use IO_WIKIPAGE_WRITE for removing their metadata... // purge non-persistant meta data p_purge_metadata($id); $del = true; // autoset summary on deletion if (empty($summary)) { $summary = $lang['deleted']; } // remove empty namespaces io_sweepNS($id, 'datadir'); io_sweepNS($id, 'mediadir'); } else { // save file (namespace dir is created in io_writeWikiPage) io_writeWikiPage($file, $text, $id); // pre-save the revision, to keep the attic in sync $newRev = saveOldRevision($id); $del = false; } // select changelog line type $extra = ''; $type = DOKU_CHANGE_TYPE_EDIT; if ($wasReverted) { $type = DOKU_CHANGE_TYPE_REVERT; $extra = $REV; } else { if ($wasCreated) { $type = DOKU_CHANGE_TYPE_CREATE; } else { if ($wasRemoved) { $type = DOKU_CHANGE_TYPE_DELETE; } else { if ($minor && $conf['useacl'] && $INPUT->server->str('REMOTE_USER')) { $type = DOKU_CHANGE_TYPE_MINOR_EDIT; } } } } //minor edits only for logged in users addLogEntry($newRev, $id, $type, $summary, $extra); // send notify mails notify($id, 'admin', $old, $summary, $minor); notify($id, 'subscribers', $old, $summary, $minor); // update the purgefile (timestamp of the last time anything within the wiki was changed) io_saveFile($conf['cachedir'] . '/purgefile', time()); // if useheading is enabled, purge the cache of all linking pages if (useHeading('content')) { $pages = ft_backlinks($id, true); foreach ($pages as $page) { $cache = new cache_renderer($page, wikiFN($page), 'xhtml'); $cache->removeCache(); } } }
/** * request with too large offset and range */ function test_requesttoolargenumberrevs() { $first = 50; $num = 50; $revsexpected = array(); $pagelog = new PageChangeLog($this->pageid, $chunk_size = 8192); $revs = $pagelog->getRevisions($first, $num); $this->assertEquals($revsexpected, $revs); }
/** * Return a list of page revisions numbers * Does not guarantee that the revision exists in the attic, * only that a line with the date exists in the changelog. * By default the current revision is skipped. * * id: the page of interest * first: skip the first n changelog lines * num: number of revisions to return * * The current revision is automatically skipped when the page exists. * See $INFO['meta']['last_change'] for the current revision. * * 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. * * @deprecated 20-11-2013 * * @author Ben Coburn <*****@*****.**> * @author Kate Arzamastseva <*****@*****.**> */ function getRevisions($id, $first, $num, $chunk_size = 8192, $media = false) { if ($media) { $changelog = new MediaChangeLog($id, $chunk_size); } else { $changelog = new PageChangeLog($id, $chunk_size); } return $changelog->getRevisions($first, $num); }