huge commit, bringing back text links, even though not completely functional if nextpage link comes _before_ the {entry} block; the commit contains the 'loose' search option for bplustree, which lets loosely search the tree for the nearest key to a given search key, which makes the thing possible; a few fixes to 404 error handling and related prettyurls stuff

This commit is contained in:
real_nowhereman 2008-11-12 16:54:40 +00:00
parent 4fe8540e2f
commit e052fa4e4a
4 changed files with 130 additions and 91 deletions

View File

@ -978,13 +978,19 @@ class BPlusTree_Node {
* @returns int|false corresponding integer or false if key is missing
*
*/
function getvalue($key) {
function getvalue(&$key, $loose=false) {
#d(implode(",",$this->keys));
$place = array_search($key, $this->keys);
if ($place!==false) {
#$place = array_search($key, $this->keys);
$place = BPT_bisect($this->keys, $key, 0);
if (@$this->keys[$place-1] == $key) {
return $this->indices[$place];
} else {
if ($loose) {
if ($place>1) $place--;
$key = $this->keys[$place];
return $this->indices[$place];
}
trigger_error("key '$key' not found", E_USER_WARNING);
return false;
}
@ -1522,12 +1528,17 @@ class BPlusTree {
/**
* returns an iterator for the tree
* @param string $keylower key lower limit of the iterator
* @param bool $includelower if true $keylower is included in the iterator
* @param bool|int $includelower if true $keylower is included in the iterator;
* if $includelower > 1 then 'loose' search is assumed:
* the tree will be walked starting from
* the key $k in the tree such as $k <= $keylower
* and such as there are NO other keys $k'
* such as $k < $k' <= $keylower
* @param string $keyupper key upper bound of the iterator
* @param bool $includeupper if true $keyupper is included in the iterator
*/
function walker(
$keylower =null,
&$keylower =null,
$includelower =null,
$keyupper =null,
$includeupper =null
@ -1694,14 +1705,16 @@ class BPlusTree {
}
/**
* @param string $key key to find
* @param string &$key key to find.
* @param bool $loose if true searches the tree for the "nearest" key to $key;
*
* @returns int associated value
*
*/
function getitem($key) {
function getitem(&$key, $loose=false) {
if (is_null($this->root))
trigger_error("not open!", E_USER_ERROR);
return $this->find($key, $this->root);
return $this->find($key, $this->root, $loose);
}
/**
@ -1712,7 +1725,7 @@ class BPlusTree {
* @returns int|bool value at the leaf node containing key or false if key is missing
*
*/
function find($key, &$node) {
function find(&$key, &$node, $loose=false) {
while (($node->flag & BPT_FLAG_INTERIOR) == BPT_FLAG_INTERIOR) {
@ -1736,7 +1749,7 @@ class BPlusTree {
$node =& $node->getnode($nodekey);
}
return $node->getvalue($key);
return $node->getvalue($key, $loose);
}
/**
@ -1744,7 +1757,7 @@ class BPlusTree {
* @returns bool false if key does not exists, true otherwise
*/
function has_key($key) {
if ($this->getitem($key)!==false) {
if (@$this->getitem($key)!==false) {
return true;
} else {
return false;
@ -2331,7 +2344,7 @@ class BPlusWalker {
function BPlusWalker(
&$tree,
$keylower=null,
&$keylower=null,
$includelower=null,
$keyupper=null,
$includeupper=null){
@ -2371,6 +2384,7 @@ class BPlusWalker {
$this->node_index = null;
$this->valid = 0;
$this->first();
$keylower = $this->keylower;
}
function first() {
@ -2395,7 +2409,11 @@ class BPlusWalker {
if (!$this->valid) {
$place = BPT_bisect($keys, $keylower, 0, $validkeys);
if ($place < $validkeys) {
$index = $this->node_index = $place;
if ($place > 0)
$index = $place - 1;
else $index = $place;
$this->node_index = $index;
$testk = $keys[$index];
/*
if ($testk>$keylower ||
@ -2406,7 +2424,11 @@ class BPlusWalker {
}
*/
$this->valid = BPT_keycmp($testk,$keylower)<0||#$testk>$keylower ||
($this->includelower && $testk==$keylower);
($this->includelower && ($this->includelower>1 || $testk==$keylower) );
$this->keylower = $testk;
} else {
$next =& $node->nextneighbour();
if (!is_null($next)) {
@ -2482,10 +2504,10 @@ class caching_BPT extends BPlusTree {
var $cache = array();
function getitem($key) {
function getitem(&$key, $loose=false) {
if (isset($cache[$key]))
return $cache[$key];
else return ($cache[$key] = parent::getitem($key));
else return ($cache[$key] = parent::getitem($key, $loose));
}
function resetcache() {
@ -2529,9 +2551,9 @@ class SBPlusTree extends BPlusTree {
return $seek;
}
function getitem($key) {
$seek = parent::getitem($key);
return $this->getstring($seek);
function getitem(&$key, $loose=false) {
$seek = parent::getitem($key, $loose);
return $seek!==false? $this->getstring($seek) : false;
}
function setitem($key, $val) {
@ -2541,7 +2563,7 @@ class SBPlusTree extends BPlusTree {
}
function walker(
$keylower =null,
&$keylower =null,
$includelower =null,
$keyupper =null,
$includeupper =null
@ -2564,10 +2586,10 @@ class caching_SBPT extends SBPlusTree {
var $cache = array();
function getitem($key) {
function getitem(&$key, $loose=false) {
if (isset($cache[$key]))
return $cache[$key];
else return ($cache[$key] = parent::getitem($key));
else return ($cache[$key] = parent::getitem($key, $loose));
}
function resetcache() {

View File

@ -386,6 +386,19 @@
return date('ymdHis', $time);
}
function entry_keytotime($key) {
$arr[ 'y' ] = substr($key, 0, 2);
$arr[ 'm' ] = substr($key, 2, 2);
$arr[ 'd' ] = substr($key, 4, 2);
$arr[ 'H' ] = substr($key, 6, 2);
$arr[ 'M' ] = substr($key, 8, 2);
$arr[ 'S' ] = substr($key, 10, 2);
return mktime($arr['H'], $arr['M'], $arr['S'],
$arr['m'], $arr['d'], $arr['y']);
}
function entry_idtotime($id) {
$date = date_from_id($id);
return $date['time'];
@ -408,7 +421,7 @@
function entry_exists($id) {
$f = entry_dir($id).EXT;
return $f;file_exists($f)? $f : false;
return file_exists($f)? $f : false;
}
function entry_dir($id) {

View File

@ -45,7 +45,10 @@
if (entry_exists($params['id'])) {
$this->id = $params['id'];
} else {
// let it fail
$this->count = 0;
return;
}
}
@ -78,7 +81,7 @@
}
if (isset($params['random'])) {
if (isset($params['random']) && !$this->id) {
$this->random = intval($params['random']);
$this->count = $this->random;
}
@ -148,7 +151,7 @@
$this->params =& new FPDB_QueryParams($params);
$this->ID = $ID;
if ($this->params->id) {
if ($this->params->id || $this->params->random) {
$this->single = true;
}
@ -174,13 +177,13 @@
return;
}
if ($this->single) {
if ($this->single || $this->params->random) {
if ($this->params->random>0) {
$this->_get_random_id($entry_index);
}
$this->_prepare_single($entry_index);
} else {
$this->_prepare_list($entry_index);
if ($this->params->random>0) {
$this->_randomize_list();
}
}
@ -197,34 +200,41 @@
$qp =& $this->params;
$time = entry_idtotime($qp->id);
// let's get a preceding key in the order relation.
// please notice this is hardcoded to $time+1, since
// order of the indices is not configurable by the user
$prevkey = entry_timetokey($time+1);
$key = entry_idtokey($qp->id);
#print_r($key);
#$key = entry_idtokey($qp->id);
if (!($entry_index->has_key($key))){
trigger_error("FPDB: no entry found for {$qp->id}", E_USER_WARNING);
#trigger_error("FPDB: no entry found for {$qp->id}", E_USER_WARNING);
$qp->count = 0;
return;
}
$this->walker =& $entry_index->walker($key, true);
/*
if ($this->counter < 0) {
$idlist = array_keys($entry_index);
$fliplist = array_flip($idlist);
$this->local_index =& $entry_index;
$this->local_list =& $idlist;
$qp->start = $fliplist[$qp->id];
$qp->count = 1;
// if $includelower = 2 (second parameter) then assumes 'loose' inclusion
// i.e. includes the first key $newkey such as $newkey <= $prevkey
// also, if $prevkey != $newkey then $prevkey := $newkey
}
$this->pointer = $qp->start;
*/
$this->walker =& $entry_index->walker($prevkey, 2, null, null);
// since we're searching for $prevkey, i.e. a key preceding the target $id
// in the sequence, if $prevkey becomes equal to $key then it means
// $key is the first post (the last in time)
if ($prevkey == $key)
$qp->start = 0;
else
$qp->start = 1;
$qp->start = 0;
$qp->count = 1;
$this->pointer = 0;
}
@ -291,34 +301,26 @@
*/
}
function _randomize_list() {
// not so great implementation... doesn't work well
function _get_random_id(&$entry_index) {
$qp =& $this->params;
$i = $qp->random - 1;
$nums = array_keys($this->local_list);
if ($qp->random == 1) {
$i = mt_rand(0, end($nums));
$this->single = true;
$qp->id = $this->local_list[ $i ];
$this->_prepare_single($this->local_index);
return;
}
shuffle($nums);
$newlocal = array();
do {
$newlocal[ $i ] = $this->local_list[ $nums[$i] ];
} while($i--);
$this->local_list = $newlocal;
if ($qp->count > $qp->random) {
$qp->count = $qp->random;
}
$now = time();
$first = '999999999999';
$last = '000000000000';
$entry_index->getitem($first, true);
$entry_index->getitem($last, true);
$t1 = entry_keytotime($first);
$t2 = entry_keytotime($last);
$t = mt_rand($t2, $t1);
$random_key = entry_timetokey($t);
$entry_index->getitem($random_key, true);
$qp->id = entry_keytoid($random_key);
}
/* reading functions */
@ -361,14 +363,19 @@
$this->previd = $this->currentid;
$id = $this->currentid = entry_keytoid($this->walker->current_key());
if ($this->single) $this->preventry = array('subject' => $this->walker->current_value());
$this->walker->next();
$this->pointer++;
}
// pointer == start
$this->previd = $this->currentid;
$prevcurr = $this->currentid;
$id = $this->currentid = entry_keytoid($this->walker->current_key());
if ($id != $prevcurr) $this->previd = $prevcurr;
if ($qp->fullparse && $this->counter <= 0) {
@ -465,14 +472,16 @@
function getNextPage() {
if ($this->single){
return false;
$id = $this->_getOffsetId(1, $this->params->start);
#return false;
#$id = $this->_getOffsetId(1, $this->params->start);
$id = $this->walker->valid ? entry_keytoid($this->walker->current_key()) : false;
if ($id)
$label = $this->local_index[$id]['subject'];
else
if ($id) {
$label = $this->walker->current_value();
} else {
return false;
}
return array($label, $id);
}
@ -490,14 +499,9 @@
function getPrevPage() {
if ($this->single) {
return false;
$id = $this->_getOffsetId(-1, $this->params->start);
if ($id)
$label = $this->local_index[$id]['subject'];
else
return false;
$id = $this->previd;
$label = $this->preventry['subject'];
return array($label, $id);

View File

@ -205,7 +205,7 @@ class Plugin_PrettyURLs {
} else {
// a bit hackish: we make up a fake url when there is no match,
// so that at the higher level the system will 404...
$this->fp_params['entry'] = 'entry000000-000000';
$this->fp_params['entry'] = 'a';
}
} else {
$this->fp_params['entry'] = $matches[1];