From: x2003bruneau Date: Sun, 28 Oct 2007 15:08:54 +0000 (+0000) Subject: Rewritten banana spool structure for faster build and access X-Git-Tag: 1.8~27 X-Git-Url: http://git.polytechnique.org/?p=banana.git;a=commitdiff_plain;h=0580f9274b206e64682b017bdcccd1c0f4ee6b19 Rewritten banana spool structure for faster build and access Signed-off-by: Florent Bruneau git-svn-id: svn+ssh://murphy/home/svn/banana/trunk@284 9869982d-c50d-0410-be91-f2a2ec7c7c7b --- diff --git a/banana/message.inc.php b/banana/message.inc.php index 51999cb..efe8f7a 100644 --- a/banana/message.inc.php +++ b/banana/message.inc.php @@ -228,22 +228,14 @@ final class BananaMessage extends BananaMimePart return BananaMessage::formatReferences($this->headers); } - static public function formatReferences(array &$refs) + static public function &formatReferences(array &$refs) { - if (isset($refs['references'])) { - $text = preg_split('/\s/', str_replace('><', '> <', $refs['references'])); - $references = array(); - foreach ($text as $id=>&$value) { - if (isset(Banana::$spool->ids[$value])) { - $references[] = Banana::$spool->ids[$value]; - } - } - return $references; - } elseif (isset($refs['in-reply-to']) && isset(Banana::$spool->ids[$refs['in-reply-to']])) { - return array(Banana::$spool->ids[$refs['in-reply-to']]); - } else { - return array(); + $references = array(); + $msgs = Banana::$spool->getReferences($refs); + foreach ($msgs as &$msg) { + $references[] = $msg->id; } + return $references; } public function hasXFace() diff --git a/banana/page.inc.php b/banana/page.inc.php index b325330..6e126dd 100644 --- a/banana/page.inc.php +++ b/banana/page.inc.php @@ -24,7 +24,7 @@ class BananaPage extends Smarty public function __construct() { - $this->Smarty(); + parent::Smarty(); $this->compile_check = Banana::$debug_smarty; $this->template_dir = dirname(__FILE__) . '/templates/'; @@ -67,7 +67,7 @@ class BananaPage extends Smarty * @param action_code HTML code of the action * @param pages ARRAY pages where to show the action (null == every pages) * @return true if success - */ + */ public function registerAction($action_code, array $pages = null) { $this->actions[] = array('text' => $action_code, 'pages' => $pages); @@ -133,7 +133,7 @@ class BananaPage extends Smarty return 'banana-base.tpl'; } - + /** Generate XHTML code */ public function run() @@ -215,7 +215,7 @@ class BananaPage extends Smarty * @param params ARRAY location datas * @param smarty OBJECT Smarty instance associated (null if none) * @return URL of the page associated with the given parameters - * + * * Usual parameters are : * - group : the box name * - artid : the current message id (index of message-id) @@ -231,11 +231,11 @@ class BananaPage extends Smarty if (function_exists('hook_makeLink') && $res = hook_makeLink($params)) { return $res; - } + } $proto = empty($_SERVER['HTTPS']) ? 'http://' : 'https://'; $host = Banana::$baseurl ? Banana::$baseurl : $_SERVER['SERVER_NAME']; $file = $_SERVER['PHP_SELF']; - + if (count($params) != 0) { $get = '?'; foreach ($params as $key=>$value) { @@ -246,7 +246,7 @@ class BananaPage extends Smarty } } else { $get = ''; - } + } return $proto . $host . $file . $get; } @@ -334,7 +334,7 @@ class BananaPage extends Smarty return '' . _b_($alt) . ''; } - + /** Build a link to one of the banana built-in javascript * @param src STRING javascript name * @return Javascript tag @@ -356,7 +356,7 @@ class BananaPage extends Smarty return ''; } - + /** Build a link with an image as text * @param params ARRAY image and location data * @param smarty OBJECT Smarty instance associated (null if none) @@ -371,7 +371,7 @@ class BananaPage extends Smarty { if (!isset($params['popup'])) { $params['popup'] = @$params['alt']; - } + } $img = $this->makeImg($params, $smarty); if (isset($params['text'])) { $img .= ' ' . $params['text']; diff --git a/banana/spool.inc.php b/banana/spool.inc.php index e65d05a..745ecd7 100644 --- a/banana/spool.inc.php +++ b/banana/spool.inc.php @@ -9,13 +9,16 @@ require_once dirname(__FILE__) . '/banana.inc.php'; -define('BANANA_SPOOL_VERSION', '0.5.9'); +define('BANANA_SPOOL_VERSION', '0.5.12'); /** Class spoolhead * class used in thread overviews */ class BananaSpoolHead { + public $id; + public $msgid; + /** date (timestamp) */ public $date; /** subject */ @@ -26,8 +29,6 @@ class BananaSpoolHead public $color; /** reference of parent */ public $parent = null; - /** paren is direct */ - public $parent_direct; /** array of children */ public $children = Array(); /** true if post is read */ @@ -48,8 +49,10 @@ class BananaSpoolHead * @param $_read BOOLEAN true if read * @param $_descunread INTEGER descunread value (0 for a new post) */ - public function __construct(array &$message) + public function __construct($id, array &$message) { + $this->id = $id; + $this->msgid = $message['message-id']; $this->date = $message['date']; $this->subject = $message['subject']; $this->from = $message['from']; @@ -83,13 +86,13 @@ class BananaSpool /** group name */ public $group; /** spool */ - public $overview; + public $overview = array(); /** array msgid => msgnum */ - public $ids; + public $ids = array(); /** thread starts */ - public $roots; + public $roots = array(); /** thread trees (one tree per root node) */ - public $trees = array(); + public $trees = array(); /** protocole specific data */ public $storage = array(); @@ -124,6 +127,7 @@ class BananaSpool $spool->markAllAsRead(); } $spool->updateUnread($since); + //var_dump($spool); return $spool; } @@ -152,9 +156,9 @@ class BananaSpool return $spool; } - private function compare($a, $b) + private function compare(&$a, &$b) { - return ($this->overview[$b]->date >= $this->overview[$a]->date); + return ($b->date - $a->date); } private function saveToFile() @@ -162,9 +166,9 @@ class BananaSpool $file = BananaSpool::spoolFilename($this->group); $this->roots = Array(); - foreach($this->overview as $id=>&$msg) { + foreach($this->overview as &$msg) { if (is_null($msg->parent)) { - $this->roots[] = $id; + $this->roots[] =& $msg; } } usort($this->roots, array($this, 'compare')); @@ -202,7 +206,7 @@ class BananaSpool private function clean(&$first, &$last, $msgnum) { $do_save = false; - if (is_array($this->overview)) { + if (!empty($this->overview)) { $mids = array_keys($this->overview); foreach ($mids as $id) { if (($first <= $last && ($id < $first || $id > $last)) @@ -227,44 +231,38 @@ class BananaSpool $messages =& Banana::$protocole->getMessageHeaders($first, $last, array('Date', 'Subject', 'From', 'Message-ID', 'References', 'In-Reply-To')); - if (!is_array($this->ids)) { - $this->ids = array(); - } + // Build all the new Spool Heads foreach ($messages as $id=>&$message) { - $this->ids[$message['message-id']] = $id; + if (!isset($this->overview[$id])) { + $this->overview[$id] = new BananaSpoolHead($id, $message); + $head =& $this->overview[$id]; + $this->ids[$head->msgid] =& $head; + } } - if (!is_array($this->overview)) { - $this->overview = array(); - } + // Build tree $updateTrees = array(); + $null = null; foreach ($messages as $id=>&$message) { - if (!isset($this->overview[$id])) { - $this->overview[$id] = new BananaSpoolHead($message); - } - $msg =& $this->overview[$id]; - $msgrefs = BananaMessage::formatReferences($message); - $parents = preg_grep('/^\d+$/', $msgrefs); - $msg->parent = array_pop($parents); - $msg->parent_direct = preg_match('/^\d+$/', array_pop($msgrefs)); - - if (!is_null($p = $msg->parent)) { - if (empty($this->overview[$p])) { - $this->overview[$p] = new BananaSpoolHead($messages[$p]); - } - $this->overview[$p]->children[] = $id; - while (!is_null($p)) { - $this->overview[$p]->desc += $msg->desc; - $prev = $p; - if ($p != $this->overview[$p]->parent) { - $p = $this->overview[$p]->parent; + $msg =& $this->overview[$id]; + $parents =& $this->getReferences($message); + while (!empty($parents) && ($msg->parent === $msg || is_null($msg->parent))) { + $msg->parent =& array_pop($parents); + } + + if (!is_null($msg->parent)) { + $parent =& $msg->parent; + $parent->children[] =& $msg; + while (!is_null($parent)) { + $parent->desc += $msg->desc; + $prev =& $p; + if ($parent !== $parent->parent) { + $parent =& $parent->parent; } else { - $p = null; - } - if (is_null($p)) { - $updateTrees[$prev] = true; + $parent =& $null; } } + $updateTrees[$prev->id] = true; } } foreach ($updateTrees as $root=>$t) { @@ -286,21 +284,18 @@ class BananaSpool return; } - if (!is_array($this->ids)) { - $this->ids = array(); - } $newpostsids = array_intersect($newpostsids, array_keys($this->ids)); foreach ($newpostsids as $mid) { - $id = $this->ids[$mid]; - if ($this->overview[$id]->isread) { - $this->overview[$id]->isread = false; - $this->unreadnb++; - while (isset($id)) { - $this->overview[$id]->descunread++; - $id = $this->overview[$id]->parent; + $overview =& $this->ids[$mid]; + if ($overview->isread) { + $overview->isread = false; + while (!is_null($overview)) { + $overview->descunread++; + $overview =& $overview->parent; } } } + $this->unreadnb += count($newpostsids); } public function setMode($mode) @@ -312,16 +307,33 @@ class BananaSpool if ($this->overview[$num]->isread) { break; } - foreach ($this->roots as $k=>$i) { - if ($this->overview[$i]->descunread == 0) { - $this->killdesc($i); - unset($this->roots[$k]); + foreach ($this->roots as &$root) { + if ($root->descunread == 0) { + $this->killdesc($root->id); } } break; } } + /** Fetch list of references + */ + public function &getReferences(array &$refs) + { + $references = array(); + if (isset($refs['references'])) { + $text = preg_split('/\s/', str_replace('><', '> <', $refs['references'])); + foreach ($text as $id=>&$value) { + if (isset($this->ids[$value])) { + $references[] =& $this->ids[$value]; + } + } + } elseif (isset($refs['in-reply-to']) && isset($this->ids[$refs['in-reply-to']])) { + $references[] =& $this->ids[$refs['in-reply-to']]; + } + return $references; + } + /** Mark the given id as read * @param id MSGNUM of post */ @@ -344,20 +356,20 @@ class BananaSpool if (!$this->unreadnb) { return; } - if (is_null($array) && is_array($this->roots)) { + if (is_null($array) && !empty($this->roots)) { $array =& $this->roots; } elseif (is_null($array)) { return; } - foreach ($array as $id) { - if (!$this->overview[$id]->isread) { - $this->markAsRead($id); + foreach ($array as &$msg) { + if (!$msg->isread) { + $this->markAsRead($msg->id); if (!$this->unreadnb) { return; } } - if ($this->overview[$id]->descunread) { - $this->markAllAsRead($this->overview[$id]->children); + if ($msg->descunread) { + $this->markAllAsRead($msg->children); } } } @@ -367,15 +379,23 @@ class BananaSpool */ private function killdesc($_id) { - if (sizeof($this->overview[$_id]->children)) { - foreach ($this->overview[$_id]->children as $c) { - $this->killdesc($c); + $overview =& $this->overview[$_id]; + $children =& $overview->children; + if (sizeof($children)) { + foreach ($children as &$c) { + $this->killdesc($c->id); } } unset($this->overview[$_id]); - if (($msgid = array_search($_id, $this->ids)) !== false) { - unset($this->ids[$msgid]); + foreach ($this->roots as $k=>&$root) { + if ($root === $overview) { + unset($this->roots[$k]); + break; + } } + unset($this->ids[$overview->msgid]); + unset($this->trees[$_id]); + $overview = null; } /** delete a post from overview @@ -383,51 +403,58 @@ class BananaSpool */ public function delid($_id, $write = true) { - if (isset($this->overview[$_id])) { - $overview =& $this->overview[$_id]; - if (!$overview->isread) { - $this->markAsRead($_id); - } - if ($overview->parent) { - $p = $overview->parent; - $parent =& $this->overview[$p]; - $parent->children = array_diff($parent->children, array($_id)); - if (sizeof($overview->children)) { - $parent->children = array_merge($parent->children, $overview->children); - foreach ($overview->children as $c) { - $this->overview[$c]->parent = $p; - $this->overview[$c]->parent_direct = false; - } - } - while (isset($p)) { - $this->overview[$p]->desc--; - $p = $this->overview[$p]->parent; - } - } elseif ($overview->children) { - foreach ($overview->children as $c) { - $this->overview[$c]->parent = null; + if (!isset($this->overview[$_id])) { + return; + } + + $overview =& $this->overview[$_id]; + // Be sure it is not counted as unread + if (!$overview->isread) { + $this->markAsRead($_id); + } + + $parent =& $overview->parent; + + // Remove from the message tree + if (!is_null($parent)) { + foreach ($parent->children as $key=>&$child) { + if ($child === $overview) { + unset($parent->children[$key]); + break; } } - unset($overview); - unset($this->overview[$_id]); - unset($this->trees[$_id]); - $msgid = array_search($_id, $this->ids); - if ($msgid !== false) { - unset($this->ids[$msgid]); + if (sizeof($overview->children)) { + $parent->children = array_merge($parent->children, $overview->children); + foreach ($overview->children as &$child) { + $child->parent =& $parent; + } } - $msgid = array_search($_id, $this->roots); - if ($msgid !== false) { - unset($this->roots[$msgid]); + while (!is_null($parent)) { + $parent->desc--; + $parent =& $parent->parent; } + } - if ($write) { - $this->saveToFile(); + // Remove all refenrences and assign null to the object + unset($this->ids[$overview->msgid]); + unset($this->overview[$_id]); + unset($this->trees[$_id]); + foreach ($this->roots as $k=>&$root) { + if ($root === $overview) { + unset($this->roots[$k]); + break; } } + $overview = null; + + if ($write) { + $this->saveToFile(); + } } - public function formatDate($stamp) + public function formatDate(BananaSpoolHead &$head) { + $stamp = $head->date; $today = intval(time() / (24*3600)); $dday = intval($stamp / (24*3600)); @@ -445,9 +472,9 @@ class BananaSpool return strftime($format, $stamp); } - public function formatSubject($id, $subject) + public function formatSubject(BananaSpoolHead &$head) { - $subject = banana_html_entity_decode($subject); + $subject = $popup = $head->subject; $popup = $subject; if (function_exists('hook_formatDisplayHeader')) { list($subject, $link) = hook_formatDisplayHeader('subject', $subject, true); @@ -458,17 +485,16 @@ class BananaSpool if (empty($subject)) { $subject = _b_('(pas de sujet)'); } - if ($id != Banana::$artid) { - $subject = Banana::$page->makeLink(Array('group' => $this->group, 'artid' => $id, + if ($head->id != Banana::$artid) { + $subject = Banana::$page->makeLink(Array('group' => $this->group, 'artid' => $head->id, 'text' => $subject, 'popup' => $popup)); } return $subject . $link; } - public function formatFrom($from) + public function formatFrom(BananaSpoolHead &$head) { - $from = banana_html_entity_decode($from); - return BananaMessage::formatFrom($from); + return BananaMessage::formatFrom($head->from); } public function start() @@ -487,7 +513,7 @@ class BananaSpool } - private function &_buildTree($id, BananaSpoolHead &$head) { + private function &_buildTree(BananaSpoolHead &$head) { static $t_e, $u_h, $u_ht, $u_vt, $u_l, $u_f, $r_h, $r_ht, $r_vt, $r_l, $r_f; if (!isset($spfx_f)) { $t_e = Banana::$page->makeImg(Array('img' => 'e', 'alt' => ' ', 'height' => 18, 'width' => 14)); @@ -503,16 +529,15 @@ class BananaSpool $r_f = Banana::$page->makeImg(Array('img' => 'f2r', 'alt' => 't', 'height' => 18, 'width' => 14)); } $style = 'background-color:' . $head->color . '; text-decoration: none'; - $text = ''; $array = array($text); - foreach ($head->children as $key=>&$child) { - $msg =& $this->overview[$child]; - $tree =& $this->_buildTree($child, $msg); + foreach ($head->children as $key=>&$msg) { + $tree =& $this->_buildTree($msg); $last = $key == count($head->children) - 1; foreach ($tree as $kt=>&$line) { if ($kt === 0 && $key === 0 && !$last) { @@ -541,7 +566,7 @@ class BananaSpool if (!$force && isset($this->trees[$id])) { return $this->trees[$id]; } else { - $tree =& $this->_buildTree($id, $this->overview[$id]); + $tree =& $this->_buildTree($this->overview[$id]); $tree = '
' . implode("
\n
", $tree) . '
'; diff --git a/banana/templates/banana-thread.inc.tpl b/banana/templates/banana-thread.inc.tpl index 3729385..91a7098 100644 --- a/banana/templates/banana-thread.inc.tpl +++ b/banana/templates/banana-thread.inc.tpl @@ -43,13 +43,13 @@ {if $spool->roots|@count} {section name=threads loop=$spool->roots step=1 start=$spool->start() max=$spool->context()} - {assign var=id value=$spool->roots[$smarty.section.threads.index]} - {assign var=overview value=$spool->overview[$id]} + {assign var=overview value=$spool->roots[$smarty.section.threads.index]} + {assign var=id value=$overview->id} {cycle assign=class values="impair,pair"} - {$spool->formatDate($overview->date)} - {$spool->formatSubject($id, $overview->subject)|smarty:nodefaults} - {$spool->formatFrom($overview->from)|smarty:nodefaults} + {$spool->formatDate($overview)} + {$spool->formatSubject($overview)|smarty:nodefaults} + {$spool->formatFrom($overview)|smarty:nodefaults} {if !$artid && $spool->nextPost($id)}