New BananaTree class that can be serialized into its own file.
authorx2003bruneau <x2003bruneau@9869982d-c50d-0410-be91-f2a2ec7c7c7b>
Tue, 30 Oct 2007 21:07:02 +0000 (21:07 +0000)
committerFlorent Bruneau <florent.bruneau@polytechnique.org>
Fri, 4 Jan 2008 23:35:54 +0000 (00:35 +0100)
Some API consistency improvements
Signed-off-by: Florent Bruneau <florent.bruneau@polytechnique.org>
git-svn-id: svn+ssh://murphy/home/svn/banana/trunk@293 9869982d-c50d-0410-be91-f2a2ec7c7c7b

banana/feed.inc.php
banana/spool.inc.php
banana/templates/banana-message.inc.tpl
banana/templates/banana-thread.inc.tpl
banana/tree.inc.php [new file with mode: 0644]

index 451e229..9f177e7 100644 (file)
@@ -88,7 +88,7 @@ class BananaFeed
         }
         uasort($this->messages, Array('BananaFeed', 'compare'));
         $this->lastupdate = time();
-        $this->writeToFile();
+        $this->saveToFile();
     }
 
     /** Get the spool corresponding with the current settings of Banana
@@ -130,7 +130,7 @@ class BananaFeed
 
     /** Write a feed to a cache file
      */
-    private function writeToFile()
+    private function saveToFile()
     {
         $file = BananaFeed::filename();
         file_put_contents($file, serialize($this));
index 3d44785..b6355b8 100644 (file)
@@ -8,8 +8,9 @@
 ********************************************************************************/
 
 require_once dirname(__FILE__) . '/banana.inc.php';
+require_once dirname(__FILE__) . '/tree.inc.php';
 
-define('BANANA_SPOOL_VERSION', '0.5.13');
+define('BANANA_SPOOL_VERSION', '0.5.14');
 
 /** Class spoolhead
  *  class used in thread overviews
@@ -37,6 +38,8 @@ class BananaSpoolHead
     public $desc;
     /**  same as desc, but counts only unread posts */
     public $descunread;
+    /** last time the number of children has been updated */
+    public $time = 0;
 
     /** storage data */
     public $storage = array();
@@ -91,8 +94,6 @@ class BananaSpool
     public $ids      = array();
     /** thread starts */
     public $roots    = array();
-    /** thread trees (one tree per root node) */
-    public $trees    = array();
 
     /** protocole specific data */
     public $storage = array();
@@ -239,16 +240,17 @@ class BananaSpool
             array('Date', 'Subject', 'From', 'Message-ID', 'References', 'In-Reply-To'));
 
         // Build all the new Spool Heads
+        $time = time();
         foreach ($messages as $id=>&$message) {
             if (!isset($this->overview[$id])) {
                 $this->overview[$id] = new BananaSpoolHead($id, $message);
                 $head =& $this->overview[$id];
                 $this->ids[$head->msgid] =& $head;
+                $head->time = $time;
             }
         }
 
         // Build tree
-        $updateTrees = array();
         $null = null;
         foreach ($messages as $id=>&$message) {
             $msg         =& $this->overview[$id];
@@ -262,6 +264,7 @@ class BananaSpool
                 $parent->children[] =& $msg;
                 while (!is_null($parent)) {
                     $parent->desc += $msg->desc;
+                    $parent->time  = $time;
                     $prev =& $parent;
                     if ($parent !== $parent->parent) {
                         $parent =& $parent->parent;
@@ -269,12 +272,8 @@ class BananaSpool
                         $parent =& $null;
                     }
                 }
-                $updateTrees[$prev->id] = true;
             }
         }
-        foreach ($updateTrees as $root=>$t) {
-            $this->trees[$root] =& $this->buildTree($root);
-        }
         Banana::$protocole->updateSpool($messages);
         return true;
     }
@@ -341,6 +340,13 @@ class BananaSpool
         return $references;
     }
 
+    /** Get the tree associated to a given id
+     */
+    public function &getTree($id)
+    {
+        return BananaTree::build($id)->data;
+    }
+
     /** Mark the given id as read
      * @param id MSGNUM of post
      */
@@ -401,7 +407,6 @@ class BananaSpool
             }
         }
         unset($this->ids[$overview->msgid]);
-        unset($this->trees[$_id]);
         $overview = null;
     }
 
@@ -436,8 +441,10 @@ class BananaSpool
                     $child->parent =& $parent;
                 }
             }
+            $time = time();
             while (!is_null($parent)) {
                 $parent->desc--;
+                $parent->time = $time;
                 $parent =& $parent->parent;
             }
         }
@@ -445,7 +452,7 @@ class BananaSpool
         // Remove all refenrences and assign null to the object
         unset($this->ids[$overview->msgid]);
         unset($this->overview[$_id]);
-        unset($this->trees[$_id]);
+        BananaTree::kill($_id);
         foreach ($this->roots as $k=>&$root) {
             if ($root === $overview) {
                 unset($this->roots[$k]);
@@ -520,68 +527,6 @@ class BananaSpool
     }
 
 
-    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' => '&nbsp;', 'height' => 18,  'width' => 14));
-            $u_h   = Banana::$page->makeImg(Array('img' => 'h2', 'alt' => '-', 'height' => 18,  'width' => 14));
-            $u_ht  = Banana::$page->makeImg(Array('img' => 'T2', 'alt' => '+', 'height' => 18, 'width' => 14));
-            $u_vt  = Banana::$page->makeImg(Array('img' => 't2', 'alt' => '`', 'height' => 18, 'width' => 14));
-            $u_l   = Banana::$page->makeImg(Array('img' => 'l2', 'alt' => '|', 'height' => 18, 'width' => 14));
-            $u_f   = Banana::$page->makeImg(Array('img' => 'f2', 'alt' => 't', 'height' => 18, 'width' => 14));
-            $r_h   = Banana::$page->makeImg(Array('img' => 'h2r', 'alt' => '-', 'height' => 18,  'width' => 14));
-            $r_ht  = Banana::$page->makeImg(Array('img' => 'T2r', 'alt' => '+', 'height' => 18, 'width' => 14));
-            $r_vt  = Banana::$page->makeImg(Array('img' => 't2r', 'alt' => '`', 'height' => 18, 'width' => 14));
-            $r_l   = Banana::$page->makeImg(Array('img' => 'l2r', 'alt' => '|', 'height' => 18, 'width' => 14));
-            $r_f   = Banana::$page->makeImg(Array('img' => 'f2r', 'alt' => 't', 'height' => 18, 'width' => 14));
-        }
-        $style = 'background-color:' . $head->color . '; text-decoration: none';
-        $text = '<span style="' . $style . '" title="' . banana_entities($head->name . ', ' . $this->formatDate($head))
-              . '"><input type="radio" name="banana_tree" '
-              . (Banana::$msgshow_javascript ? 'onchange="window.location=\'' .
-                    banana_entities(Banana::$page->makeURL(array('group' => $this->group, 'artid' => $head->id))) . '\'"'
-                    : ' disabled="disabled"')
-              . ' /></span>';
-        $array = array($text);
-        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) {
-                    $array[0] .= ($msg->isread ? $r_ht : $u_ht) . $line;
-                } else if($kt === 0 && $key === 0) {
-                    $array[0] .= ($msg->isread ? $r_h : $u_h)  . $line;
-                } else if ($kt === 0 && $last) {
-                    $array[] = $t_e . ($msg->isread ? $r_vt : $u_vt) . $line;
-                } else if ($kt === 0) {
-                    $array[] = $t_e . ($msg->isread ? $r_f : $u_f) . $line;
-                } else if ($last) {
-                    $array[] = $t_e . $t_e . $line;
-                } else {
-                    $array[] = $t_e . ($msg->isread ? $r_l : $u_l) . $line;
-                }
-            }
-            unset($tree);
-        }
-        return $array;
-    }
-
-    /** build the spool tree associated with the given message
-     */
-    public function &buildTree($id, $force = false) {
-        $root =& $this->root($id);
-        $id   = $root->id;
-        if (!$force && isset($this->trees[$id])) {
-            return $this->trees[$id];
-        } else {
-            $tree =& $this->_buildTree($root);
-            $tree = '<div class="tree"><div style="height:18px">'
-                  . implode("</div>\n<div style=\"height:18px\">", $tree)
-                  . '</div></div>';
-            return $tree;
-        }
-    }
-
     /** computes linear post index
      * @param $_id INTEGER MSGNUM of post
      * @return INTEGER linear index of post
@@ -804,6 +749,5 @@ class BananaSpool
         return null;
     }
 }
-
 // vim:set et sw=4 sts=4 ts=4 enc=utf-8:
 ?>
index 0712532..329f6d2 100644 (file)
     </th>
   </tr>
   <tr class="pair">
-    <td colspan="3" class="thread_tree">{$spool->buildTree($artid)|smarty:nodefaults}</td>
+    <td colspan="3" class="thread_tree">{$spool->getTree($artid)|smarty:nodefaults}</td>
   </tr>
   {/if}
 </table>
index 91a7098..3879d55 100644 (file)
@@ -53,7 +53,7 @@
   </tr>
   {if !$artid && $spool->nextPost($id)}
   <tr class="{$class}">
-    <td colspan="3" class="thread_tree">{$spool->buildTree($id)|smarty:nodefaults}</td>
+    <td colspan="3" class="thread_tree">{$spool->getTree($id)|smarty:nodefaults}</td>
   </tr>
   {/if}
   {/section}
diff --git a/banana/tree.inc.php b/banana/tree.inc.php
new file mode 100644 (file)
index 0000000..f780bcd
--- /dev/null
@@ -0,0 +1,151 @@
+<?php
+/********************************************************************************
+* include/tree.inc.php : thread tree
+* -----------------------
+*
+* This file is part of the banana distribution
+* Copyright: See COPYING files that comes with this distribution
+********************************************************************************/
+
+
+define('BANANA_TREE_VERSION', '0.1');
+
+/**
+ * Class representing a thread tree
+ */
+class BananaTree
+{
+    /** Tree cache
+     */
+    static private $cache = array();
+
+    /** Tree format
+     */
+    public $version;
+
+    /** Last update timestamp
+     */
+    public $time = 0;
+
+    /** Data
+     */
+    public $data;
+
+    /** Construct a new tree from a given root
+     */
+    public function __construct(BananaSpoolHead &$root)
+    {
+        if (empty($root->children)) {
+            $this->data = null;
+        } else {
+            $tree =& $this->builder($root);
+            $this->data = '<div class="tree"><div style="height:18px">'
+                        . implode("</div>\n<div style=\"height:18px\">", $tree)
+                        . '</div></div>';
+        }
+        $this->time = time();
+        $this->version = BANANA_TREE_VERSION;
+        $this->saveToFile($root->id);
+    }
+
+    private function &builder(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' => '&nbsp;', 'height' => 18,  'width' => 14));
+            $u_h   = Banana::$page->makeImg(Array('img' => 'h2', 'alt' => '-', 'height' => 18,  'width' => 14));
+            $u_ht  = Banana::$page->makeImg(Array('img' => 'T2', 'alt' => '+', 'height' => 18, 'width' => 14));
+            $u_vt  = Banana::$page->makeImg(Array('img' => 't2', 'alt' => '`', 'height' => 18, 'width' => 14));
+            $u_l   = Banana::$page->makeImg(Array('img' => 'l2', 'alt' => '|', 'height' => 18, 'width' => 14));
+            $u_f   = Banana::$page->makeImg(Array('img' => 'f2', 'alt' => 't', 'height' => 18, 'width' => 14));
+            $r_h   = Banana::$page->makeImg(Array('img' => 'h2r', 'alt' => '-', 'height' => 18,  'width' => 14));
+            $r_ht  = Banana::$page->makeImg(Array('img' => 'T2r', 'alt' => '+', 'height' => 18, 'width' => 14));
+            $r_vt  = Banana::$page->makeImg(Array('img' => 't2r', 'alt' => '`', 'height' => 18, 'width' => 14));
+            $r_l   = Banana::$page->makeImg(Array('img' => 'l2r', 'alt' => '|', 'height' => 18, 'width' => 14));
+            $r_f   = Banana::$page->makeImg(Array('img' => 'f2r', 'alt' => 't', 'height' => 18, 'width' => 14));
+        }
+        $style = 'background-color:' . $head->color . '; text-decoration: none';
+        $text = '<span style="' . $style . '" title="' . banana_entities($head->name . ', ' . Banana::$spool->formatDate($head))
+              . '"><input type="radio" name="banana_tree" '
+              . (Banana::$msgshow_javascript ? 'onchange="window.location=\'' .
+                    banana_entities(Banana::$page->makeURL(array('group' => Banana::$spool->group, 'artid' => $head->id))) . '\'"'
+                    : ' disabled="disabled"')
+              . ' /></span>';
+        $array = array($text);
+        foreach ($head->children as $key=>&$msg) {
+            $tree =& $this->builder($msg);
+            $last = $key == count($head->children) - 1;
+            foreach ($tree as $kt=>&$line) {
+                if ($kt === 0 && $key === 0 && !$last) {
+                    $array[0] .= ($msg->isread ? $r_ht : $u_ht) . $line;
+                } else if($kt === 0 && $key === 0) {
+                    $array[0] .= ($msg->isread ? $r_h : $u_h)  . $line;
+                } else if ($kt === 0 && $last) {
+                    $array[] = $t_e . ($msg->isread ? $r_vt : $u_vt) . $line;
+                } else if ($kt === 0) {
+                    $array[] = $t_e . ($msg->isread ? $r_f : $u_f) . $line;
+                } else if ($last) {
+                    $array[] = $t_e . $t_e . $line;
+                } else {
+                    $array[] = $t_e . ($msg->isread ? $r_l : $u_l) . $line;
+                }
+            }
+            unset($tree);
+        }
+        return $array;
+    }
+
+    /** Save the content of the tree into a file
+     */
+    private function saveToFile($id)
+    {
+        file_put_contents(BananaTree::filename($id), serialize($this));
+    }
+
+    /** Get filename
+     */
+    static private function filename($id)
+    {
+        return BananaSpool::getPath('tree_' . $id);
+    }
+
+    /** Read a tree from a file
+     */
+    static private function &readFromFile($id)
+    {
+        $tree = null;
+        $file = BananaTree::filename($id);
+        if (!file_exists($file)) {
+            return $tree;
+        }
+        $tree = unserialize(file_get_contents($file));
+        if ($tree->version != BANANA_TREE_VERSION) {
+            $tree = null;
+        }
+        return $tree;
+    }
+
+    /** Build a tree for the given id
+     */
+    static public function &build($id)
+    {
+        $root =& Banana::$spool->root($id);
+        if (!isset(BananaTree::$cache[$root->id])) {
+            $tree =& BananaTree::readFromFile($root->id);
+            if (is_null($tree) || $tree->time < $root->time) {
+                $tree = new BananaTree($root);
+            }
+            BananaTree::$cache[$root->id] =& $tree;
+        }
+        return BananaTree::$cache[$root->id];
+    }
+
+    /** Kill the file associated to the given id
+     */
+    static public function kill($id)
+    {
+        @unlink(BananaTree::filename($id));
+    }
+}
+// vim:set et sw=4 sts=4 ts=4 enc=utf-8:
+?>