From 7d559c7f2292c82b8d5072fad951b8e33cdced05 Mon Sep 17 00:00:00 2001
From: Ben Coburn <btcoburn@silicodon.net>
Date: Mon, 11 Sep 2006 04:38:22 +0200
Subject: [PATCH] reorganize changelog code

Moves changelog code to 'inc/changelog.php'
and includes it from 'inc/common.php'.

darcs-hash:20060911023822-05dcb-e727737011163cbf04f0a4c682cb9fd8a985e597.gz
---
 inc/changelog.php | 359 ++++++++++++++++++++++++++++++++++++++++++++++
 inc/common.php    | 352 +--------------------------------------------
 2 files changed, 360 insertions(+), 351 deletions(-)
 create mode 100644 inc/changelog.php

diff --git a/inc/changelog.php b/inc/changelog.php
new file mode 100644
index 000000000..fdb18253c
--- /dev/null
+++ b/inc/changelog.php
@@ -0,0 +1,359 @@
+<?php
+/**
+ * Changelog handling functions
+ *
+ * @license    GPL 2 (http://www.gnu.org/licenses/gpl.html)
+ * @author     Andreas Gohr <andi@splitbrain.org>
+ */
+
+/**
+ * parses a changelog line into it's components
+ *
+ * @author Ben Coburn <btcoburn@silicodon.net>
+ */
+function parseChangelogLine($line) {
+  $tmp = explode("\t", $line);
+    if ($tmp!==false && count($tmp)>1) {
+      $info = array();
+      $info['date']  = $tmp[0]; // unix timestamp
+      $info['ip']    = $tmp[1]; // IPv4 address (127.0.0.1)
+      $info['type']  = $tmp[2]; // log line type
+      $info['id']    = $tmp[3]; // page id
+      $info['user']  = $tmp[4]; // user name
+      $info['sum']   = $tmp[5]; // edit summary (or action reason)
+      $info['extra'] = rtrim($tmp[6], "\n"); // extra data (varies by line type)
+      return $info;
+  } else { return false; }
+}
+
+/**
+ * Add's an entry to the changelog and saves the metadata for the page
+ *
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Esther Brunner <wikidesign@gmail.com>
+ * @author Ben Coburn <btcoburn@silicodon.net>
+ */
+function addLogEntry($date, $id, $type='E', $summary='', $extra=''){
+  global $conf, $INFO;
+
+  $id = cleanid($id);
+  $file = wikiFN($id);
+  $created = @filectime($file);
+  $minor = ($type==='e');
+  $wasRemoved = ($type==='D');
+
+  if(!$date) $date = time(); //use current time if none supplied
+  $remote = $_SERVER['REMOTE_ADDR'];
+  $user   = $_SERVER['REMOTE_USER'];
+
+  $strip = array("\t", "\n");
+  $logline = array(
+    'date'  => $date,
+    'ip'    => $remote,
+    'type'  => str_replace($strip, '', $type),
+    'id'    => $id,
+    'user'  => $user,
+    'sum'   => str_replace($strip, '', $summary),
+    'extra' => str_replace($strip, '', $extra)
+  );
+
+  // update metadata
+  if (!$wasRemoved) {
+    $meta = array();
+    if (!$INFO['exists']){ // newly created
+      $meta['date']['created'] = $created;
+      if ($user) $meta['creator'] = $INFO['userinfo']['name'];
+    } elseif (!$minor) {   // non-minor modification
+      $meta['date']['modified'] = $date;
+      if ($user) $meta['contributor'][$user] = $INFO['userinfo']['name'];
+    }
+    $meta['last_change'] = $logline;
+    p_set_metadata($id, $meta, true);
+  }
+
+  // add changelog lines
+  $logline = implode("\t", $logline)."\n";
+  io_saveFile(metaFN($id,'.changes'),$logline,true); //page changelog
+  io_saveFile($conf['changelog'],$logline,true); //global changelog cache
+}
+
+/**
+ * returns an array of recently changed files using the
+ * changelog
+ *
+ * The following constants can be used to control which changes are
+ * included. Add them together as needed.
+ *
+ * RECENTS_SKIP_DELETED   - don't include deleted pages
+ * RECENTS_SKIP_MINORS    - don't include minor changes
+ * RECENTS_SKIP_SUBSPACES - don't include subspaces
+ *
+ * @param int    $first   number of first entry returned (for paginating
+ * @param int    $num     return $num entries
+ * @param string $ns      restrict to given namespace
+ * @param bool   $flags   see above
+ *
+ * @author Ben Coburn <btcoburn@silicodon.net>
+ */
+function getRecents($first,$num,$ns='',$flags=0){
+  global $conf;
+  $recent = array();
+  $count  = 0;
+
+  if(!$num)
+    return $recent;
+
+  // read all recent changes. (kept short)
+  $lines = file($conf['changelog']);
+
+  // handle lines
+  for($i = count($lines)-1; $i >= 0; $i--){
+    $rec = _handleRecent($lines[$i], $ns, $flags);
+    if($rec !== false) {
+      if(--$first >= 0) continue; // skip first entries
+      $recent[] = $rec;
+      $count++;
+      // break when we have enough entries
+      if($count >= $num){ break; }
+    }
+  }
+
+  return $recent;
+}
+
+/**
+ * Internal function used by getRecents
+ *
+ * don't call directly
+ *
+ * @see getRecents()
+ * @author Andreas Gohr <andi@splitbrain.org>
+ * @author Ben Coburn <btcoburn@silicodon.net>
+ */
+function _handleRecent($line,$ns,$flags){
+  static $seen  = array();         //caches seen pages and skip them
+  if(empty($line)) return false;   //skip empty lines
+
+  // split the line into parts
+  $recent = parseChangelogLine($line);
+  if ($recent===false) { return false; }
+
+  // skip seen ones
+  if(isset($seen[$recent['id']])) return false;
+
+  // skip minors
+  if($recent['type']==='e' && ($flags & RECENTS_SKIP_MINORS)) return false;
+
+  // remember in seen to skip additional sights
+  $seen[$recent['id']] = 1;
+
+  // check if it's a hidden page
+  if(isHiddenPage($recent['id'])) return false;
+
+  // filter namespace
+  if (($ns) && (strpos($recent['id'],$ns.':') !== 0)) return false;
+
+  // exclude subnamespaces
+  if (($flags & RECENTS_SKIP_SUBSPACES) && (getNS($recent['id']) != $ns)) return false;
+
+  // check ACL
+  if (auth_quickaclcheck($recent['id']) < AUTH_READ) return false;
+
+  // check existance
+  if((!@file_exists(wikiFN($recent['id']))) && ($flags & RECENTS_SKIP_DELETED)) return false;
+
+  return $recent;
+}
+
+/**
+ * Get the changelog information for a specific page id
+ * and revision (timestamp). Adjacent changelog lines
+ * are optimistically parsed and cached to speed up
+ * consecutive calls to getRevisionInfo. For large
+ * changelog files, only the chunk containing the
+ * requested changelog line is read.
+ *
+ * @author Ben Coburn <btcoburn@silicodon.net>
+ */
+function getRevisionInfo($id, $rev, $chunk_size=8192) {
+  global $cache_revinfo;
+  $cache =& $cache_revinfo;
+  if (!isset($cache[$id])) { $cache[$id] = array(); }
+  $rev = max($rev, 0);
+
+  // check if it's already in the memory cache
+  if (isset($cache[$id]) && isset($cache[$id][$rev])) {
+    return $cache[$id][$rev];
+  }
+
+  $file = metaFN($id, '.changes');
+  if (!@file_exists($file)) { return false; }
+  if (filesize($file)<$chunk_size || $chunk_size==0) {
+    // read whole file
+    $lines = file($file);
+    if ($lines===false) { return false; }
+  } else {
+    // read by chunk
+    $fp = fopen($file, 'rb'); // "file pointer"
+    if ($fp===false) { return false; }
+    $head = 0;
+    fseek($fp, 0, SEEK_END);
+    $tail = ftell($fp);
+    $finger = 0;
+    $finger_rev = 0;
+
+    // find chunk
+    while ($tail-$head>$chunk_size) {
+      $finger = $head+floor(($tail-$head)/2.0);
+      fseek($fp, $finger);
+      fgets($fp); // slip the finger forward to a new line
+      $finger = ftell($fp);
+      $tmp = fgets($fp); // then read at that location
+      $tmp = parseChangelogLine($tmp);
+      $finger_rev = $tmp['date'];
+      if ($finger==$head || $finger==$tail) { break; }
+      if ($finger_rev>$rev) {
+        $tail = $finger;
+      } else {
+        $head = $finger;
+      }
+    }
+
+    if ($tail-$head<1) {
+      // cound not find chunk, assume requested rev is missing
+      fclose($fp);
+      return false;
+    }
+
+    // read chunk
+    $chunk = '';
+    $chunk_size = max($tail-$head, 0); // found chunk size
+    $got = 0;
+    fseek($fp, $head);
+    while ($got<$chunk_size && !feof($fp)) {
+      $tmp = fread($fp, max($chunk_size-$got, 0));
+      if ($tmp===false) { break; } //error state
+      $got += strlen($tmp);
+      $chunk .= $tmp;
+    }
+    $lines = explode("\n", $chunk);
+    array_pop($lines); // remove trailing newline
+    fclose($fp);
+  }
+
+  // parse and cache changelog lines
+  foreach ($lines as $value) {
+    $tmp = parseChangelogLine($value);
+    if ($tmp!==false) {
+      $cache[$id][$tmp['date']] = $tmp;
+    }
+  }
+  if (!isset($cache[$id][$rev])) { return false; }
+  return $cache[$id][$rev];
+}
+
+/**
+ * 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 untill the requested number of changelog
+ * lines are recieved.
+ *
+ * @author Ben Coburn <btcoburn@silicodon.net>
+ */
+function getRevisions($id, $first, $num, $chunk_size=8192) {
+  global $cache_revinfo;
+  $cache =& $cache_revinfo;
+  if (!isset($cache[$id])) { $cache[$id] = array(); }
+
+  $revs = array();
+  $lines = array();
+  $count  = 0;
+  $file = metaFN($id, '.changes');
+  $num = max($num, 0);
+  $chunk_size = max($chunk_size, 0);
+  if ($first<0) { $first = 0; }
+  else if (@file_exists(wikiFN($id))) {
+     // skip current revision if the page exists
+    $first = max($first+1, 0);
+  }
+
+  if (!@file_exists($file)) { return $revs; }
+  if (filesize($file)<$chunk_size || $chunk_size==0) {
+    // read whole file
+    $lines = file($file);
+    if ($lines===false) { return $revs; }
+  } else {
+    // read chunks backwards
+    $fp = fopen($file, 'rb'); // "file pointer"
+    if ($fp===false) { return $revs; }
+    fseek($fp, 0, SEEK_END);
+    $tail = ftell($fp);
+
+    // chunk backwards
+    $finger = max($tail-$chunk_size, 0);
+    while ($count<$num+$first) {
+      fseek($fp, $finger);
+      if ($finger>0) {
+        fgets($fp); // slip the finger forward to a new line
+        $finger = ftell($fp);
+      }
+
+      // read chunk
+      if ($tail<=$finger) { break; }
+      $chunk = '';
+      $read_size = max($tail-$finger, 0); // found chunk size
+      $got = 0;
+      while ($got<$read_size && !feof($fp)) {
+        $tmp = fread($fp, max($read_size-$got, 0));
+        if ($tmp===false) { break; } //error state
+        $got += strlen($tmp);
+        $chunk .= $tmp;
+      }
+      $tmp = explode("\n", $chunk);
+      array_pop($tmp); // remove trailing newline
+
+      // combine with previous chunk
+      $count += count($tmp);
+      $lines = array_merge($tmp, $lines);
+
+      // next chunk
+      if ($finger==0) { break; } // already read all the lines
+      else {
+        $tail = $finger;
+        $finger = max($tail-$chunk_size, 0);
+      }
+    }
+    fclose($fp);
+  }
+
+  // skip parsing extra lines
+  $num = max(min(count($lines)-$first, $num), 0);
+  if      ($first>0 && $num>0)  { $lines = array_slice($lines, max(count($lines)-$first-$num, 0), $num); }
+  else if ($first>0 && $num==0) { $lines = array_slice($lines, 0, max(count($lines)-$first, 0)); }
+  else if ($first==0 && $num>0) { $lines = array_slice($lines, max(count($lines)-$num, 0)); }
+
+  // handle lines in reverse order
+  for ($i = count($lines)-1; $i >= 0; $i--) {
+    $tmp = parseChangelogLine($lines[$i]);
+    if ($tmp!==false) {
+      $cache[$id][$tmp['date']] = $tmp;
+      $revs[] = $tmp['date'];
+    }
+  }
+
+  return $revs;
+}
+
+
diff --git a/inc/common.php b/inc/common.php
index 7c20c0b8f..cfff848f6 100644
--- a/inc/common.php
+++ b/inc/common.php
@@ -9,6 +9,7 @@
   if(!defined('DOKU_INC')) define('DOKU_INC',realpath(dirname(__FILE__).'/../').'/');
   require_once(DOKU_CONF.'dokuwiki.php');
   require_once(DOKU_INC.'inc/io.php');
+  require_once(DOKU_INC.'inc/changelog.php');
   require_once(DOKU_INC.'inc/utf8.php');
   require_once(DOKU_INC.'inc/mail.php');
   require_once(DOKU_INC.'inc/parserutils.php');
@@ -717,357 +718,6 @@ function dbglog($msg){
   }
 }
 
-/**
- * Add's an entry to the changelog and saves the metadata for the page
- *
- * @author Andreas Gohr <andi@splitbrain.org>
- * @author Esther Brunner <wikidesign@gmail.com>
- * @author Ben Coburn <btcoburn@silicodon.net>
- */
-function addLogEntry($date, $id, $type='E', $summary='', $extra=''){
-  global $conf, $INFO;
-
-  $id = cleanid($id);
-  $file = wikiFN($id);
-  $created = @filectime($file);
-  $minor = ($type==='e');
-  $wasRemoved = ($type==='D');
-
-  if(!$date) $date = time(); //use current time if none supplied
-  $remote = $_SERVER['REMOTE_ADDR'];
-  $user   = $_SERVER['REMOTE_USER'];
-
-  $strip = array("\t", "\n");
-  $logline = array(
-    'date'  => $date,
-    'ip'    => $remote,
-    'type'  => str_replace($strip, '', $type),
-    'id'    => $id,
-    'user'  => $user,
-    'sum'   => str_replace($strip, '', $summary),
-    'extra' => str_replace($strip, '', $extra)
-  );
-
-  // update metadata
-  if (!$wasRemoved) {
-    $meta = array();
-    if (!$INFO['exists']){ // newly created
-      $meta['date']['created'] = $created;
-      if ($user) $meta['creator'] = $INFO['userinfo']['name'];
-    } elseif (!$minor) {   // non-minor modification
-      $meta['date']['modified'] = $date;
-      if ($user) $meta['contributor'][$user] = $INFO['userinfo']['name'];
-    }
-    $meta['last_change'] = $logline;
-    p_set_metadata($id, $meta, true);
-  }
-
-  // add changelog lines
-  $logline = implode("\t", $logline)."\n";
-  io_saveFile(metaFN($id,'.changes'),$logline,true); //page changelog
-  io_saveFile($conf['changelog'],$logline,true); //global changelog cache
-}
-
-/**
- * Internal function used by getRecents
- *
- * don't call directly
- *
- * @see getRecents()
- * @author Andreas Gohr <andi@splitbrain.org>
- * @author Ben Coburn <btcoburn@silicodon.net>
- */
-function _handleRecent($line,$ns,$flags){
-  static $seen  = array();         //caches seen pages and skip them
-  if(empty($line)) return false;   //skip empty lines
-
-  // split the line into parts
-  $recent = parseChangelogLine($line);
-  if ($recent===false) { return false; }
-
-  // skip seen ones
-  if(isset($seen[$recent['id']])) return false;
-
-  // skip minors
-  if($recent['type']==='e' && ($flags & RECENTS_SKIP_MINORS)) return false;
-
-  // remember in seen to skip additional sights
-  $seen[$recent['id']] = 1;
-
-  // check if it's a hidden page
-  if(isHiddenPage($recent['id'])) return false;
-
-  // filter namespace
-  if (($ns) && (strpos($recent['id'],$ns.':') !== 0)) return false;
-
-  // exclude subnamespaces
-  if (($flags & RECENTS_SKIP_SUBSPACES) && (getNS($recent['id']) != $ns)) return false;
-
-  // check ACL
-  if (auth_quickaclcheck($recent['id']) < AUTH_READ) return false;
-
-  // check existance
-  if((!@file_exists(wikiFN($recent['id']))) && ($flags & RECENTS_SKIP_DELETED)) return false;
-
-  return $recent;
-}
-
-
-/**
- * returns an array of recently changed files using the
- * changelog
- *
- * The following constants can be used to control which changes are
- * included. Add them together as needed.
- *
- * RECENTS_SKIP_DELETED   - don't include deleted pages
- * RECENTS_SKIP_MINORS    - don't include minor changes
- * RECENTS_SKIP_SUBSPACES - don't include subspaces
- *
- * @param int    $first   number of first entry returned (for paginating
- * @param int    $num     return $num entries
- * @param string $ns      restrict to given namespace
- * @param bool   $flags   see above
- *
- * @author Ben Coburn <btcoburn@silicodon.net>
- */
-function getRecents($first,$num,$ns='',$flags=0){
-  global $conf;
-  $recent = array();
-  $count  = 0;
-
-  if(!$num)
-    return $recent;
-
-  // read all recent changes. (kept short)
-  $lines = file($conf['changelog']);
-
-  // handle lines
-  for($i = count($lines)-1; $i >= 0; $i--){
-    $rec = _handleRecent($lines[$i], $ns, $flags);
-    if($rec !== false) {
-      if(--$first >= 0) continue; // skip first entries
-      $recent[] = $rec;
-      $count++;
-      // break when we have enough entries
-      if($count >= $num){ break; }
-    }
-  }
-
-  return $recent;
-}
-
-/**
- * parses a changelog line into it's components
- *
- * @author Ben Coburn <btcoburn@silicodon.net>
- */
-function parseChangelogLine($line) {
-  $tmp = explode("\t", $line);
-    if ($tmp!==false && count($tmp)>1) {
-      $info = array();
-      $info['date']  = $tmp[0]; // unix timestamp
-      $info['ip']    = $tmp[1]; // IPv4 address (127.0.0.1)
-      $info['type']  = $tmp[2]; // log line type
-      $info['id']    = $tmp[3]; // page id
-      $info['user']  = $tmp[4]; // user name
-      $info['sum']   = $tmp[5]; // edit summary (or action reason)
-      $info['extra'] = rtrim($tmp[6], "\n"); // extra data (varies by line type)
-      return $info;
-  } else { return false; }
-}
-
-/**
- * Get the changelog information for a specific page id
- * and revision (timestamp). Adjacent changelog lines
- * are optimistically parsed and cached to speed up
- * consecutive calls to getRevisionInfo. For large
- * changelog files, only the chunk containing the
- * requested changelog line is read.
- *
- * @author Ben Coburn <btcoburn@silicodon.net>
- */
-function getRevisionInfo($id, $rev, $chunk_size=8192) {
-  global $cache_revinfo;
-  $cache =& $cache_revinfo;
-  if (!isset($cache[$id])) { $cache[$id] = array(); }
-  $rev = max($rev, 0);
-
-  // check if it's already in the memory cache
-  if (isset($cache[$id]) && isset($cache[$id][$rev])) {
-    return $cache[$id][$rev];
-  }
-
-  $file = metaFN($id, '.changes');
-  if (!@file_exists($file)) { return false; }
-  if (filesize($file)<$chunk_size || $chunk_size==0) {
-    // read whole file
-    $lines = file($file);
-    if ($lines===false) { return false; }
-  } else {
-    // read by chunk
-    $fp = fopen($file, 'rb'); // "file pointer"
-    if ($fp===false) { return false; }
-    $head = 0;
-    fseek($fp, 0, SEEK_END);
-    $tail = ftell($fp);
-    $finger = 0;
-    $finger_rev = 0;
-
-    // find chunk
-    while ($tail-$head>$chunk_size) {
-      $finger = $head+floor(($tail-$head)/2.0);
-      fseek($fp, $finger);
-      fgets($fp); // slip the finger forward to a new line
-      $finger = ftell($fp);
-      $tmp = fgets($fp); // then read at that location
-      $tmp = parseChangelogLine($tmp);
-      $finger_rev = $tmp['date'];
-      if ($finger==$head || $finger==$tail) { break; }
-      if ($finger_rev>$rev) {
-        $tail = $finger;
-      } else {
-        $head = $finger;
-      }
-    }
-
-    if ($tail-$head<1) {
-      // cound not find chunk, assume requested rev is missing
-      fclose($fp);
-      return false;
-    }
-
-    // read chunk
-    $chunk = '';
-    $chunk_size = max($tail-$head, 0); // found chunk size
-    $got = 0;
-    fseek($fp, $head);
-    while ($got<$chunk_size && !feof($fp)) {
-      $tmp = fread($fp, max($chunk_size-$got, 0));
-      if ($tmp===false) { break; } //error state
-      $got += strlen($tmp);
-      $chunk .= $tmp;
-    }
-    $lines = explode("\n", $chunk);
-    array_pop($lines); // remove trailing newline
-    fclose($fp);
-  }
-
-  // parse and cache changelog lines
-  foreach ($lines as $value) {
-    $tmp = parseChangelogLine($value);
-    if ($tmp!==false) {
-      $cache[$id][$tmp['date']] = $tmp;
-    }
-  }
-  if (!isset($cache[$id][$rev])) { return false; }
-  return $cache[$id][$rev];
-}
-
-/**
- * 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 untill the requested number of changelog
- * lines are recieved.
- *
- * @author Ben Coburn <btcoburn@silicodon.net>
- */
-function getRevisions($id, $first, $num, $chunk_size=8192) {
-  global $cache_revinfo;
-  $cache =& $cache_revinfo;
-  if (!isset($cache[$id])) { $cache[$id] = array(); }
-
-  $revs = array();
-  $lines = array();
-  $count  = 0;
-  $file = metaFN($id, '.changes');
-  $num = max($num, 0);
-  $chunk_size = max($chunk_size, 0);
-  if ($first<0) { $first = 0; }
-  else if (@file_exists(wikiFN($id))) {
-     // skip current revision if the page exists
-    $first = max($first+1, 0);
-  }
-
-  if (!@file_exists($file)) { return $revs; }
-  if (filesize($file)<$chunk_size || $chunk_size==0) {
-    // read whole file
-    $lines = file($file);
-    if ($lines===false) { return $revs; }
-  } else {
-    // read chunks backwards
-    $fp = fopen($file, 'rb'); // "file pointer"
-    if ($fp===false) { return $revs; }
-    fseek($fp, 0, SEEK_END);
-    $tail = ftell($fp);
-
-    // chunk backwards
-    $finger = max($tail-$chunk_size, 0);
-    while ($count<$num+$first) {
-      fseek($fp, $finger);
-      if ($finger>0) {
-        fgets($fp); // slip the finger forward to a new line
-        $finger = ftell($fp);
-      }
-
-      // read chunk
-      if ($tail<=$finger) { break; }
-      $chunk = '';
-      $read_size = max($tail-$finger, 0); // found chunk size
-      $got = 0;
-      while ($got<$read_size && !feof($fp)) {
-        $tmp = fread($fp, max($read_size-$got, 0));
-        if ($tmp===false) { break; } //error state
-        $got += strlen($tmp);
-        $chunk .= $tmp;
-      }
-      $tmp = explode("\n", $chunk);
-      array_pop($tmp); // remove trailing newline
-
-      // combine with previous chunk
-      $count += count($tmp);
-      $lines = array_merge($tmp, $lines);
-
-      // next chunk
-      if ($finger==0) { break; } // already read all the lines
-      else {
-        $tail = $finger;
-        $finger = max($tail-$chunk_size, 0);
-      }
-    }
-    fclose($fp);
-  }
-
-  // skip parsing extra lines
-  $num = max(min(count($lines)-$first, $num), 0);
-  if      ($first>0 && $num>0)  { $lines = array_slice($lines, max(count($lines)-$first-$num, 0), $num); }
-  else if ($first>0 && $num==0) { $lines = array_slice($lines, 0, max(count($lines)-$first, 0)); }
-  else if ($first==0 && $num>0) { $lines = array_slice($lines, max(count($lines)-$num, 0)); }
-
-  // handle lines in reverse order
-  for ($i = count($lines)-1; $i >= 0; $i--) {
-    $tmp = parseChangelogLine($lines[$i]);
-    if ($tmp!==false) {
-      $cache[$id][$tmp['date']] = $tmp;
-      $revs[] = $tmp['date'];
-    }
-  }
-
-  return $revs;
-}
-
 /**
  * Saves a wikitext by calling io_writeWikiPage
  *
-- 
GitLab