Truncates subjects when they are too long (Closes #959).
[banana.git] / banana / spool.inc.php
index 745ecd7..2a9ec6d 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.12');
+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();
@@ -52,9 +55,9 @@ class BananaSpoolHead
     public function __construct($id, array &$message)
     {
         $this->id         = $id;
-        $this->msgid      = $message['message-id'];
+        $this->msgid      = @$message['message-id'];
         $this->date       = $message['date'];
-        $this->subject    = $message['subject'];
+        $this->subject    = @$message['subject'];
         $this->from       = $message['from'];
         $this->color      = sprintf('#%06x', abs(crc32($this->from) % 0xffffff));
         $this->desc       = 1;
@@ -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();
@@ -127,23 +128,30 @@ class BananaSpool
             $spool->markAllAsRead();
         }
         $spool->updateUnread($since);
-        //var_dump($spool);
         return $spool;
     }
 
-    private static function spoolFilename($group)
+    public static function getPath($file = null)
     {
-        $file = Banana::$spool_root . '/' . Banana::$protocole->name() . '/';
-        if (!is_dir($file)) {
-            mkdir($file);
+        $path = Banana::$spool_root . '/' . Banana::$protocole->name() . '/' . Banana::$protocole->filename();
+        if (!is_dir($path)) {
+            if (file_exists($path)) {
+                @unlink($path);
+            }
+            mkdir($path, 0777, true);
         }
-        return $file . Banana::$protocole->filename();
+        return $path . '/' . $file;
+    }
+
+    private static function spoolFilename()
+    {
+        return BananaSpool::getPath('spool');
     }
 
     private static function &readFromFile($group)
     {
         $spool = null;
-        $file = BananaSpool::spoolFilename($group);
+        $file = BananaSpool::spoolFilename();
         if (!file_exists($file)) {
             return $spool;
         }
@@ -156,14 +164,14 @@ class BananaSpool
         return $spool;
     }
 
-    private function compare(&$a, &$b)
+    private function compare($a, $b)
     {
         return ($b->date - $a->date);
     }
 
     private function saveToFile()
     {
-        $file = BananaSpool::spoolFilename($this->group);
+        $file = BananaSpool::spoolFilename();
 
         $this->roots = Array();
         foreach($this->overview as &$msg) {
@@ -232,22 +240,23 @@ 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];
             $parents     =& $this->getReferences($message);
             while (!empty($parents) && ($msg->parent === $msg || is_null($msg->parent))) {
-                $msg->parent =& array_pop($parents);
+                @$msg->parent =& array_pop($parents);
             }
 
             if (!is_null($msg->parent)) {
@@ -255,19 +264,16 @@ class BananaSpool
                 $parent->children[] =& $msg;
                 while (!is_null($parent)) {
                     $parent->desc += $msg->desc;
-                    $prev =& $p;
+                    $parent->time  = $time;
+                    $prev =& $parent;
                     if ($parent !== $parent->parent) {
                         $parent =& $parent->parent;
                     } else {
                         $parent =& $null;
                     }
                 }
-                $updateTrees[$prev->id] = true;
             }
         }
-        foreach ($updateTrees as $root=>$t) {
-            $this->trees[$root] =& $this->buildTree($root);
-        }
         Banana::$protocole->updateSpool($messages);
         return true;
     }
@@ -334,17 +340,25 @@ class BananaSpool
         return $references;
     }
 
+    /** Get the tree associated to a given id
+     */
+    public function &getTree($id)
+    {
+        return BananaTree::build($id)->show();
+    }
+
     /** Mark the given id as read
      * @param id MSGNUM of post
      */
     public function markAsRead($id)
     {
-        if (!$this->overview[$id]->isread) {
-            $this->overview[$id]->isread = true;
+        $overview =& $this->overview[$id];
+        if (!$overview->isread) {
+            $overview->isread = true;
             $this->unreadnb--;
-            while (isset($id)) {
-                $this->overview[$id]->descunread--;
-                $id = $this->overview[$id]->parent;
+            while (!is_null($overview)) {
+                $overview->descunread--;
+                $overview =& $overview->parent;
             }
         }
     }
@@ -394,7 +408,6 @@ class BananaSpool
             }
         }
         unset($this->ids[$overview->msgid]);
-        unset($this->trees[$_id]);
         $overview = null;
     }
 
@@ -417,6 +430,7 @@ class BananaSpool
 
         // Remove from the message tree
         if (!is_null($parent)) {
+            $time = time();
             foreach ($parent->children as $key=>&$child) {
                 if ($child === $overview) {
                     unset($parent->children[$key]);
@@ -424,13 +438,15 @@ class BananaSpool
                 }
             }
             if (sizeof($overview->children)) {
-                $parent->children = array_merge($parent->children, $overview->children);
                 foreach ($overview->children as &$child) {
+                    $parent->children[] =& $child;
+                    $child->time   = $time;
                     $child->parent =& $parent;
                 }
             }
             while (!is_null($parent)) {
                 $parent->desc--;
+                $parent->time = $time;
                 $parent =& $parent->parent;
             }
         }
@@ -438,7 +454,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]);
@@ -452,7 +468,7 @@ class BananaSpool
         }
     }
 
-    public function formatDate(BananaSpoolHead &$head)
+    public function formatDate(BananaSpoolHead $head)
     {
         $stamp  = $head->date;
         $today  = intval(time() / (24*3600));
@@ -472,7 +488,7 @@ class BananaSpool
         return strftime($format, $stamp);
     }
 
-    public function formatSubject(BananaSpoolHead &$head)
+    public function formatSubject(BananaSpoolHead $head)
     {
         $subject = $popup = $head->subject;
         $popup = $subject;
@@ -485,14 +501,17 @@ class BananaSpool
         if (empty($subject)) {
             $subject = _b_('(pas de sujet)');
         }
-        if ($head->id != Banana::$artid) {
+        if (strlen($subject) > 100) {
+            $subject = substr($subject, 0, 99) . '…';
+        }
+        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(BananaSpoolHead &$head)
+    public function formatFrom(BananaSpoolHead $head)
     {
         return BananaMessage::formatFrom($head->from);
     }
@@ -512,109 +531,16 @@ class BananaSpool
         return Banana::$first ? Banana::$spool_tmax : Banana::$spool_tcontext;
     }
 
-
-    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));
-            $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' => $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) {
-        $id = $this->root($id);
-        if (!$force && isset($this->trees[$id])) {
-            return $this->trees[$id];
-        } else {
-            $tree =& $this->_buildTree($this->overview[$id]);
-            $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
-     */
-    public function getNdX($_id)
-    {
-        $ndx    = 1;
-        $id_cur = $_id;
-        while (true) {
-            $id_parent = $this->overview[$id_cur]->parent;
-            if (is_null($id_parent)) break;
-            $pos = array_search($id_cur, $this->overview[$id_parent]->children);
-
-            for ($i = 0; $i < $pos ; $i++) {
-                $ndx += $this->overview[$this->overview[$id_parent]->children[$i]]->desc;
-            }
-            $ndx++; //noeud père
-
-            $id_cur = $id_parent;
-        }
-
-        foreach ($this->roots as $i) {
-            if ($i==$id_cur) {
-                break;
-            }
-            $ndx += $this->overview[$i]->desc;
-        }
-        return $ndx;
-    }
-
     /** Return root message of the given thread
      * @param id INTEGER id of a message
      */
-    public function root($id)
+    public function &root($id)
     {
-        while (true) {
-            $id_parent = $this->overview[$id]->parent;
-            if (is_null($id_parent)) break;
-            $id = $id_parent;
+        $parent =& $this->overview[$id];
+        while (!is_null($parent->parent)) {
+            $parent =& $parent->parent;
         }
-        return $id;
+        return $parent;
     }
 
     /** Return the last post id with the given subject
@@ -648,13 +574,13 @@ class BananaSpool
      */
     public function prevThread($id)
     {
-        $root = $this->root($id);
+        $root =& $this->root($id);
         $last = null;
-        foreach ($this->roots as $i) {
-            if ($i == $root) {
+        foreach ($this->roots as &$i) {
+            if ($i === $root) {
                 return $last;
             }
-            $last = $i;
+            $last = $i->id;
         }
         return $last;
     }
@@ -664,13 +590,13 @@ class BananaSpool
      */
     public function nextThread($id)
     {
-        $root = $this->root($id);
+        $root =& $this->root($id);
         $ok   = false;
-        foreach ($this->roots as $i) {
+        foreach ($this->roots as &$i) {
             if ($ok) {
-                return $i;
+                return $i->id;
             }
-            if ($i == $root) {
+            if ($i === $root) {
                 $ok = true;
             }
         }
@@ -682,16 +608,16 @@ class BananaSpool
      */
     public function prevPost($id)
     {
-        $parent = $this->overview[$id]->parent;
+        $parent =& $this->overview[$id]->parent;
         if (is_null($parent)) {
             return null;
         }
-        $last = $parent;
-        foreach ($this->overview[$parent]->children as $child) {
-            if ($child == $id) {
+        $last = $parent->id;
+        foreach ($parent->children as &$child) {
+            if ($child->id == $id) {
                 return $last;
             }
-            $last = $child;
+            $last = $child->id;
         }
         return null;
     }
@@ -701,26 +627,27 @@ class BananaSpool
      */
     public function nextPost($id)
     {
-        if (count($this->overview[$id]->children) != 0) {
-            return $this->overview[$id]->children[0];
+        $cur =& $this->overview[$id];
+        if (count($cur->children) != 0) {
+            return $cur->children[0]->id;
         }
 
-        $cur    = $id;
+        $parent =& $cur;
         while (true) {
-            $parent = $this->overview[$cur]->parent;
+            $parent =& $cur->parent;
             if (is_null($parent)) {
                 return null;
             }
             $ok = false;
-            foreach ($this->overview[$parent]->children as $child) {
+            foreach ($parent->children as &$child) {
                 if ($ok) {
-                    return $child;
+                    return $child->id;
                 }
-                if ($child == $cur) {
+                if ($child === $cur) {
                     $ok = true;
                 }
             }
-            $cur = $parent;
+            $cur =& $parent;
         }
         return null;
     }
@@ -728,12 +655,12 @@ class BananaSpool
     /** Look for an unread message in the thread rooted by the message
      * @param id INTEGER message number
      */
-    private function _nextUnread($id)
+    private function _nextUnread(BananaSpoolHead $cur)
     {
-        if (!$this->overview[$id]->isread) {
-            return $id;
+        if (!$cur->isread) {
+            return $cur->id;
         }
-        foreach ($this->overview[$id]->children as $child) {
+        foreach ($cur->children as &$child) {
             $unread = $this->_nextUnread($child);
             if (!is_null($unread)) {
                 return $unread;
@@ -753,7 +680,7 @@ class BananaSpool
 
         if (!is_null($id)) {
             // Look in message children
-            foreach ($this->overview[$id]->children as $child) {
+            foreach ($this->overview[$id]->children as &$child) {
                 $next = $this->_nextUnread($child);
                 if (!is_null($next)) {
                     return $next;
@@ -762,31 +689,39 @@ class BananaSpool
         }
 
         // Look in current thread
-        $cur = $id;
+        if (is_null($id)) {
+            $cur = null;
+        } else {
+            $cur =& $this->overview[$id];
+        }
         do {
-            $parent = is_null($cur) ? null : $this->overview[$cur]->parent;
-            $ok     = is_null($cur) ? true : false;
+            if (is_null($cur)) {
+                $parent =& $cur;
+                $ok     = true;
+            } else {
+                $parent =& $cur->parent;
+                $ok     =  false;
+            }
             if (!is_null($parent)) {
-                $array = &$this->overview[$parent]->children;
+                $array =& $parent->children;
             } else {
-                $array = &$this->roots;
+                $array =$this->roots;
             }
-            foreach ($array as $child) {
+            foreach ($array as &$child) {
                 if ($ok) {
                     $next = $this->_nextUnread($child);
                     if (!is_null($next)) {
                         return $next;
                     }
                 }
-                if ($child == $cur) {
+                if ($child === $cur) {
                     $ok = true;
                 }
             }
-            $cur = $parent;
+            $cur =& $parent;
         } while(!is_null($cur));
         return null;
     }
 }
-
 // vim:set et sw=4 sts=4 ts=4 enc=utf-8:
 ?>