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:
parent
4fe8540e2f
commit
e052fa4e4a
@ -978,13 +978,19 @@ class BPlusTree_Node {
|
|||||||
* @returns int|false corresponding integer or false if key is missing
|
* @returns int|false corresponding integer or false if key is missing
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function getvalue($key) {
|
function getvalue(&$key, $loose=false) {
|
||||||
|
|
||||||
#d(implode(",",$this->keys));
|
#d(implode(",",$this->keys));
|
||||||
$place = array_search($key, $this->keys);
|
#$place = array_search($key, $this->keys);
|
||||||
if ($place!==false) {
|
$place = BPT_bisect($this->keys, $key, 0);
|
||||||
|
if (@$this->keys[$place-1] == $key) {
|
||||||
return $this->indices[$place];
|
return $this->indices[$place];
|
||||||
} else {
|
} else {
|
||||||
|
if ($loose) {
|
||||||
|
if ($place>1) $place--;
|
||||||
|
$key = $this->keys[$place];
|
||||||
|
return $this->indices[$place];
|
||||||
|
}
|
||||||
trigger_error("key '$key' not found", E_USER_WARNING);
|
trigger_error("key '$key' not found", E_USER_WARNING);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -1522,12 +1528,17 @@ class BPlusTree {
|
|||||||
/**
|
/**
|
||||||
* returns an iterator for the tree
|
* returns an iterator for the tree
|
||||||
* @param string $keylower key lower limit of the iterator
|
* @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 string $keyupper key upper bound of the iterator
|
||||||
* @param bool $includeupper if true $keyupper is included in the iterator
|
* @param bool $includeupper if true $keyupper is included in the iterator
|
||||||
*/
|
*/
|
||||||
function walker(
|
function walker(
|
||||||
$keylower =null,
|
&$keylower =null,
|
||||||
$includelower =null,
|
$includelower =null,
|
||||||
$keyupper =null,
|
$keyupper =null,
|
||||||
$includeupper =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
|
* @returns int associated value
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
function getitem($key) {
|
function getitem(&$key, $loose=false) {
|
||||||
if (is_null($this->root))
|
if (is_null($this->root))
|
||||||
trigger_error("not open!", E_USER_ERROR);
|
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
|
* @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) {
|
while (($node->flag & BPT_FLAG_INTERIOR) == BPT_FLAG_INTERIOR) {
|
||||||
|
|
||||||
@ -1736,7 +1749,7 @@ class BPlusTree {
|
|||||||
$node =& $node->getnode($nodekey);
|
$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
|
* @returns bool false if key does not exists, true otherwise
|
||||||
*/
|
*/
|
||||||
function has_key($key) {
|
function has_key($key) {
|
||||||
if ($this->getitem($key)!==false) {
|
if (@$this->getitem($key)!==false) {
|
||||||
return true;
|
return true;
|
||||||
} else {
|
} else {
|
||||||
return false;
|
return false;
|
||||||
@ -2331,7 +2344,7 @@ class BPlusWalker {
|
|||||||
|
|
||||||
function BPlusWalker(
|
function BPlusWalker(
|
||||||
&$tree,
|
&$tree,
|
||||||
$keylower=null,
|
&$keylower=null,
|
||||||
$includelower=null,
|
$includelower=null,
|
||||||
$keyupper=null,
|
$keyupper=null,
|
||||||
$includeupper=null){
|
$includeupper=null){
|
||||||
@ -2371,6 +2384,7 @@ class BPlusWalker {
|
|||||||
$this->node_index = null;
|
$this->node_index = null;
|
||||||
$this->valid = 0;
|
$this->valid = 0;
|
||||||
$this->first();
|
$this->first();
|
||||||
|
$keylower = $this->keylower;
|
||||||
}
|
}
|
||||||
|
|
||||||
function first() {
|
function first() {
|
||||||
@ -2395,7 +2409,11 @@ class BPlusWalker {
|
|||||||
if (!$this->valid) {
|
if (!$this->valid) {
|
||||||
$place = BPT_bisect($keys, $keylower, 0, $validkeys);
|
$place = BPT_bisect($keys, $keylower, 0, $validkeys);
|
||||||
if ($place < $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];
|
$testk = $keys[$index];
|
||||||
/*
|
/*
|
||||||
if ($testk>$keylower ||
|
if ($testk>$keylower ||
|
||||||
@ -2406,7 +2424,11 @@ class BPlusWalker {
|
|||||||
}
|
}
|
||||||
*/
|
*/
|
||||||
$this->valid = BPT_keycmp($testk,$keylower)<0||#$testk>$keylower ||
|
$this->valid = BPT_keycmp($testk,$keylower)<0||#$testk>$keylower ||
|
||||||
($this->includelower && $testk==$keylower);
|
($this->includelower && ($this->includelower>1 || $testk==$keylower) );
|
||||||
|
|
||||||
|
|
||||||
|
$this->keylower = $testk;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
$next =& $node->nextneighbour();
|
$next =& $node->nextneighbour();
|
||||||
if (!is_null($next)) {
|
if (!is_null($next)) {
|
||||||
@ -2482,10 +2504,10 @@ class caching_BPT extends BPlusTree {
|
|||||||
|
|
||||||
var $cache = array();
|
var $cache = array();
|
||||||
|
|
||||||
function getitem($key) {
|
function getitem(&$key, $loose=false) {
|
||||||
if (isset($cache[$key]))
|
if (isset($cache[$key]))
|
||||||
return $cache[$key];
|
return $cache[$key];
|
||||||
else return ($cache[$key] = parent::getitem($key));
|
else return ($cache[$key] = parent::getitem($key, $loose));
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetcache() {
|
function resetcache() {
|
||||||
@ -2529,9 +2551,9 @@ class SBPlusTree extends BPlusTree {
|
|||||||
return $seek;
|
return $seek;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getitem($key) {
|
function getitem(&$key, $loose=false) {
|
||||||
$seek = parent::getitem($key);
|
$seek = parent::getitem($key, $loose);
|
||||||
return $this->getstring($seek);
|
return $seek!==false? $this->getstring($seek) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function setitem($key, $val) {
|
function setitem($key, $val) {
|
||||||
@ -2541,7 +2563,7 @@ class SBPlusTree extends BPlusTree {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function walker(
|
function walker(
|
||||||
$keylower =null,
|
&$keylower =null,
|
||||||
$includelower =null,
|
$includelower =null,
|
||||||
$keyupper =null,
|
$keyupper =null,
|
||||||
$includeupper =null
|
$includeupper =null
|
||||||
@ -2564,10 +2586,10 @@ class caching_SBPT extends SBPlusTree {
|
|||||||
|
|
||||||
var $cache = array();
|
var $cache = array();
|
||||||
|
|
||||||
function getitem($key) {
|
function getitem(&$key, $loose=false) {
|
||||||
if (isset($cache[$key]))
|
if (isset($cache[$key]))
|
||||||
return $cache[$key];
|
return $cache[$key];
|
||||||
else return ($cache[$key] = parent::getitem($key));
|
else return ($cache[$key] = parent::getitem($key, $loose));
|
||||||
}
|
}
|
||||||
|
|
||||||
function resetcache() {
|
function resetcache() {
|
||||||
|
@ -386,6 +386,19 @@
|
|||||||
return date('ymdHis', $time);
|
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) {
|
function entry_idtotime($id) {
|
||||||
$date = date_from_id($id);
|
$date = date_from_id($id);
|
||||||
return $date['time'];
|
return $date['time'];
|
||||||
@ -408,7 +421,7 @@
|
|||||||
|
|
||||||
function entry_exists($id) {
|
function entry_exists($id) {
|
||||||
$f = entry_dir($id).EXT;
|
$f = entry_dir($id).EXT;
|
||||||
return $f;file_exists($f)? $f : false;
|
return file_exists($f)? $f : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function entry_dir($id) {
|
function entry_dir($id) {
|
||||||
|
@ -45,7 +45,10 @@
|
|||||||
|
|
||||||
if (entry_exists($params['id'])) {
|
if (entry_exists($params['id'])) {
|
||||||
$this->id = $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->random = intval($params['random']);
|
||||||
$this->count = $this->random;
|
$this->count = $this->random;
|
||||||
}
|
}
|
||||||
@ -148,7 +151,7 @@
|
|||||||
$this->params =& new FPDB_QueryParams($params);
|
$this->params =& new FPDB_QueryParams($params);
|
||||||
$this->ID = $ID;
|
$this->ID = $ID;
|
||||||
|
|
||||||
if ($this->params->id) {
|
if ($this->params->id || $this->params->random) {
|
||||||
$this->single = true;
|
$this->single = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,13 +177,13 @@
|
|||||||
return;
|
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);
|
$this->_prepare_single($entry_index);
|
||||||
} else {
|
} else {
|
||||||
$this->_prepare_list($entry_index);
|
$this->_prepare_list($entry_index);
|
||||||
if ($this->params->random>0) {
|
|
||||||
$this->_randomize_list();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -197,34 +200,41 @@
|
|||||||
|
|
||||||
$qp =& $this->params;
|
$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);
|
$key = entry_idtokey($qp->id);
|
||||||
|
#print_r($key);
|
||||||
|
|
||||||
|
#$key = entry_idtokey($qp->id);
|
||||||
if (!($entry_index->has_key($key))){
|
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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->walker =& $entry_index->walker($key, true);
|
// 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
|
||||||
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;
|
|
||||||
|
|
||||||
|
|
||||||
}
|
$this->walker =& $entry_index->walker($prevkey, 2, null, null);
|
||||||
|
|
||||||
$this->pointer = $qp->start;
|
// 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;
|
$qp->start = 0;
|
||||||
|
else
|
||||||
|
$qp->start = 1;
|
||||||
|
|
||||||
$qp->count = 1;
|
$qp->count = 1;
|
||||||
|
|
||||||
$this->pointer = 0;
|
$this->pointer = 0;
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -292,33 +302,25 @@
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function _randomize_list() {
|
// not so great implementation... doesn't work well
|
||||||
|
function _get_random_id(&$entry_index) {
|
||||||
$qp =& $this->params;
|
$qp =& $this->params;
|
||||||
|
$now = time();
|
||||||
|
|
||||||
$i = $qp->random - 1;
|
$first = '999999999999';
|
||||||
$nums = array_keys($this->local_list);
|
$last = '000000000000';
|
||||||
|
$entry_index->getitem($first, true);
|
||||||
|
$entry_index->getitem($last, true);
|
||||||
|
|
||||||
|
$t1 = entry_keytotime($first);
|
||||||
|
$t2 = entry_keytotime($last);
|
||||||
|
|
||||||
if ($qp->random == 1) {
|
$t = mt_rand($t2, $t1);
|
||||||
$i = mt_rand(0, end($nums));
|
|
||||||
$this->single = true;
|
|
||||||
$qp->id = $this->local_list[ $i ];
|
|
||||||
$this->_prepare_single($this->local_index);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
shuffle($nums);
|
$random_key = entry_timetokey($t);
|
||||||
|
$entry_index->getitem($random_key, true);
|
||||||
|
|
||||||
$newlocal = array();
|
$qp->id = entry_keytoid($random_key);
|
||||||
do {
|
|
||||||
$newlocal[ $i ] = $this->local_list[ $nums[$i] ];
|
|
||||||
} while($i--);
|
|
||||||
|
|
||||||
$this->local_list = $newlocal;
|
|
||||||
|
|
||||||
if ($qp->count > $qp->random) {
|
|
||||||
$qp->count = $qp->random;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* reading functions */
|
/* reading functions */
|
||||||
@ -361,14 +363,19 @@
|
|||||||
$this->previd = $this->currentid;
|
$this->previd = $this->currentid;
|
||||||
$id = $this->currentid = entry_keytoid($this->walker->current_key());
|
$id = $this->currentid = entry_keytoid($this->walker->current_key());
|
||||||
|
|
||||||
|
if ($this->single) $this->preventry = array('subject' => $this->walker->current_value());
|
||||||
|
|
||||||
|
|
||||||
$this->walker->next();
|
$this->walker->next();
|
||||||
$this->pointer++;
|
$this->pointer++;
|
||||||
}
|
}
|
||||||
|
|
||||||
// pointer == start
|
// pointer == start
|
||||||
|
|
||||||
$this->previd = $this->currentid;
|
$prevcurr = $this->currentid;
|
||||||
$id = $this->currentid = entry_keytoid($this->walker->current_key());
|
$id = $this->currentid = entry_keytoid($this->walker->current_key());
|
||||||
|
if ($id != $prevcurr) $this->previd = $prevcurr;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
if ($qp->fullparse && $this->counter <= 0) {
|
if ($qp->fullparse && $this->counter <= 0) {
|
||||||
@ -465,13 +472,15 @@
|
|||||||
function getNextPage() {
|
function getNextPage() {
|
||||||
|
|
||||||
if ($this->single){
|
if ($this->single){
|
||||||
return false;
|
#return false;
|
||||||
$id = $this->_getOffsetId(1, $this->params->start);
|
#$id = $this->_getOffsetId(1, $this->params->start);
|
||||||
|
$id = $this->walker->valid ? entry_keytoid($this->walker->current_key()) : false;
|
||||||
|
|
||||||
if ($id)
|
if ($id) {
|
||||||
$label = $this->local_index[$id]['subject'];
|
$label = $this->walker->current_value();
|
||||||
else
|
} else {
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return array($label, $id);
|
return array($label, $id);
|
||||||
|
|
||||||
@ -490,14 +499,9 @@
|
|||||||
function getPrevPage() {
|
function getPrevPage() {
|
||||||
|
|
||||||
if ($this->single) {
|
if ($this->single) {
|
||||||
return false;
|
|
||||||
|
|
||||||
$id = $this->_getOffsetId(-1, $this->params->start);
|
$id = $this->previd;
|
||||||
|
$label = $this->preventry['subject'];
|
||||||
if ($id)
|
|
||||||
$label = $this->local_index[$id]['subject'];
|
|
||||||
else
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return array($label, $id);
|
return array($label, $id);
|
||||||
|
|
||||||
|
@ -205,7 +205,7 @@ class Plugin_PrettyURLs {
|
|||||||
} else {
|
} else {
|
||||||
// a bit hackish: we make up a fake url when there is no match,
|
// a bit hackish: we make up a fake url when there is no match,
|
||||||
// so that at the higher level the system will 404...
|
// so that at the higher level the system will 404...
|
||||||
$this->fp_params['entry'] = 'entry000000-000000';
|
$this->fp_params['entry'] = 'a';
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$this->fp_params['entry'] = $matches[1];
|
$this->fp_params['entry'] = $matches[1];
|
||||||
|
Loading…
x
Reference in New Issue
Block a user