Integration of the tree in the spool view
authorx2003bruneau <x2003bruneau@9869982d-c50d-0410-be91-f2a2ec7c7c7b>
Tue, 23 Oct 2007 22:04:19 +0000 (22:04 +0000)
committerFlorent Bruneau <florent.bruneau@polytechnique.org>
Fri, 4 Jan 2008 23:35:51 +0000 (00:35 +0100)
Signed-off-by: Florent Bruneau <florent.bruneau@polytechnique.org>
git-svn-id: svn+ssh://murphy/home/svn/banana/trunk@281 9869982d-c50d-0410-be91-f2a2ec7c7c7b

banana/banana.inc.php.in
banana/message.inc.php
banana/spool.inc.php
banana/templates/banana-message.inc.tpl
banana/templates/banana-thread.inc.tpl
css/style.css

index 3ca5da6..2b43207 100644 (file)
@@ -33,8 +33,8 @@ class Banana
     static public $spool_root    = '/var/spool/banana';
     static public $spool_max     = 3000;
     static public $spool_tbefore = 5;
-    static public $spool_tafter  = 5;
-    static public $spool_tmax    = 50;
+    static public $spool_tcontext= 10;
+    static public $spool_tmax    = 10;
     static public $spool_boxlist = true;
 
 ### Message processing ###
index ff08fd3..51999cb 100644 (file)
@@ -119,7 +119,7 @@ final class BananaMessage extends BananaMimePart
     public function getSender()
     {
         $from = $this->headers['from'];
-        $name = trim(preg_replace('/<[^ ]*>/', '', $from));
+        $name = trim(strip_tags($from));
         if (empty($name)) {
             return $from;
         }
@@ -165,7 +165,7 @@ final class BananaMessage extends BananaMimePart
         }
         if (preg_match("/^([^ ]+@[^ ]+) \((.*)\)$/", $text, $regs)) {
             $result = $mailto . $regs[1] . $subject . '">' . banana_htmlentities($regs[2]) . '</a>';
-        }   
+        }
         if (preg_match("/^\"?([^<>\"]+)\"? +<(.+@.+)>$/", $text, $regs)) {
             $nom = preg_replace("/^'(.*)'$/", '\1', $regs[1]);
             $nom = stripslashes($nom);
@@ -180,7 +180,7 @@ final class BananaMessage extends BananaMimePart
         $name = null;
         if (preg_match("/^([^ ]+@[^ ]+) \((.*)\)$/", $text, $regs)) {
             $name = $regs[2];
-        }   
+        }
         if (preg_match("/^\"?([^<>\"]+)\"? +<(.+@.+)>$/", $text, $regs)) {
             $name = preg_replace("/^'(.*)'$/", '\1', $regs[1]);
             $name = stripslashes($name);
index 6ce1751..28e8a35 100644 (file)
@@ -9,7 +9,7 @@
 
 require_once dirname(__FILE__) . '/banana.inc.php';
 
-define('BANANA_SPOOL_VERSION', '0.5.1');
+define('BANANA_SPOOL_VERSION', '0.5.7');
 
 /** Class spoolhead
  *  class used in thread overviews
@@ -22,6 +22,7 @@ class BananaSpoolHead
     public $subject;
     /** author */
     public $from;
+    public $name;
     public $color;
     /** reference of parent */
     public $parent = null;
@@ -56,6 +57,20 @@ class BananaSpoolHead
         $this->desc       = 1;
         $this->isread     = true;
         $this->descunread = 0;
+        if (preg_match("/^([^ ]+@[^ ]+) \((.*)\)$/", $this->from, $regs)) {
+            $this->name = $regs[2];
+        }
+        if (preg_match("/^\"?([^<>\"]+)\"? +<(.+@.+)>$/", $this->from, $regs)) {
+            $this->name = preg_replace("/^'(.*)'$/", '\1', $regs[1]);
+            $this->name = stripslashes($this->name);
+        }
+        if ($this->name) {
+            $this->name =  preg_replace("/\\\(\(|\))/","\\1", $this->name);
+        } else if (preg_match("/([^< ]+)@([^> ]+)/", $this->from, $regs)) {
+            $this->name = $regs[1];
+        } else {
+            $this->name = 'Anonymous';
+        }
     }
 }
 
@@ -73,6 +88,9 @@ class BananaSpool
     public $ids;
     /** thread starts */
     public $roots;
+    /** thread trees (one tree per root node) */
+    public $trees = array();
+
     /** protocole specific data */
     public $storage = array();
 
@@ -219,6 +237,7 @@ class BananaSpool
         if (!is_array($this->overview)) {
             $this->overview = array();
         }
+        $updateTrees = array();
         foreach ($messages as $id=>&$message) {
             if (!isset($this->overview[$id])) {
                 $this->overview[$id] = new BananaSpoolHead($message);
@@ -234,17 +253,23 @@ class BananaSpool
                     $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;
                     } else {
                         $p = null;
                     }
+                    if (is_null($p)) {
+                        $updateTrees[$prev] = true;
+                    }
                 }
             }
         }
+        foreach ($updateTrees as $root=>$t) {
+            $this->trees[$root] = $this->buildTree($root, true);
+        }
         Banana::$protocole->updateSpool($messages);
         return true;
     }
@@ -385,6 +410,7 @@ class BananaSpool
             }
             unset($overview);
             unset($this->overview[$_id]);
+            unset($this->trees[$_id]);
             $msgid = array_search($_id, $this->ids);
             if ($msgid !== false) {
                 unset($this->ids[$msgid]);
@@ -400,7 +426,7 @@ class BananaSpool
         }
     }
 
-    private function formatDate($stamp)
+    public function formatDate($stamp)
     {
         $today  = intval(time() / (24*3600));
         $dday   = intval($stamp / (24*3600));
@@ -419,6 +445,47 @@ class BananaSpool
         return strftime($format, $stamp);
     }
 
+    public function formatSubject($id, $subject)
+    {
+        $subject = banana_html_entity_decode($subject);
+        $popup = $subject;
+        if (function_exists('hook_formatDisplayHeader')) {
+            list($subject, $link) = hook_formatDisplayHeader('subject', $subject, true);
+        } else {
+            $subject = banana_catchFormats(banana_entities(stripslashes($subject)));
+            $link = null;
+        }
+        if (empty($subject)) {
+            $subject = _b_('(pas de sujet)');
+        }
+        if ($id != Banana::$artid) {
+            $subject = Banana::$page->makeLink(Array('group' => $this->group, 'artid' => $id,
+                                                     'text'  => $subject, 'popup' => $popup));
+        }
+        return $subject . $link;
+    }
+
+    public function formatFrom($from)
+    {
+        $from = banana_html_entity_decode($from);
+        return BananaMessage::formatFrom($from);
+    }
+
+    public function start()
+    {
+        if (Banana::$first) {
+            return Banana::$first;
+        } else {
+            $first = array_search(Banana::$artid, $this->roots);
+            return max(0, $first - Banana::$spool_tbefore);
+        }
+    }
+
+    public function context()
+    {
+        return Banana::$first ? Banana::$spool_tmax : Banana::$spool_tcontext;
+    }
+
     /** displays children tree of a post
      * @param $_id INTEGER MSGNUM of post
      * @param $_index INTEGER linear number of post in the tree
@@ -558,10 +625,11 @@ class BananaSpool
         }
         $style = 'background-color:' . $head->color . '; text-decoration: none';
         $prof  = 1;
-        $text = '<span style="' . $style . '" title="' . banana_entities($head->from) . '">' .
+        $text = '<span style="' . $style . '" title="' . banana_entities($head->name . ', ' . $this->formatDate($head->date)) . '">' .
                 '<input type="radio" name="banana_tree" '. ($id == $current ? 'checked="checked" ' : ' ' ) .
                 (Banana::$msgshow_javascript ? 'onchange="window.location=\'' .
-                    Banana::$page->makeURL(array('group' => $this->group, 'artid' => $id)) . '\'"' : ' disabled="disabled"')
+                    banana_entities(Banana::$page->makeURL(array('group' => $this->group, 'artid' => $id))) . '\'"'
+                    : ' disabled="disabled"')
                 .' />' .
                 '</span>';
         $array = array($text);
@@ -584,6 +652,7 @@ class BananaSpool
                     $array[] = $t_e . ($msg->isread ? $r_l : $u_l) . $line;
                 }
             }
+            unset($tree);
             if ($tpr > $prof) {
                 $prof = $tpr + 1;
             }
@@ -593,15 +662,19 @@ class BananaSpool
 
     /** build the spool tree associated with the given message
      */
-    public function buildTree($id) {
+    public function buildTree($id, $force = false) {
         $pos      =  $id;
         $overview =& $this->overview[$id];
         while (!is_null($overview->parent)) {
             $pos = $overview->parent;
             $overview =& $this->overview[$pos];
         }
-        list($prof, $tree) = $this->_buildTree($pos, $overview, $id);
-        return implode("\n", $tree);
+        if (!$force && isset($this->trees[$pos])) {
+            return $this->trees[$pos];
+        } else {
+            list(, $tree) = $this->_buildTree($pos, $overview, $force ? -1 : $id);
+            return '<div style="height:18px">' . implode("</div>\n<div style=\"height:18px\">", $tree) . '</div>';
+        }
     }
 
     /** computes linear post index
index 94d7fa7..0712532 100644 (file)
@@ -1,22 +1,18 @@
-<pre class="thread_tree">
-{$spool->buildTree($artid)|smarty:nodefaults}
-</pre>
-
 <table class="bicol message">
   <tr>
     <th colspan="3" class="subject">
       {if !$noactions}
       <div class="menu">
-        {if $spool->nextUnread($artid)}
-        {imglink group=$group artid=$spool->nextUnread($artid) img=next_unread alt="Message non-lu suivant"|b accesskey=u}{/if}
-        {if $spool->prevPost($artid)}
-        {imglink group=$group artid=$spool->prevPost($artid) img=prev alt="Message précédent"|b accesskey=a}{/if}
-        {if $spool->nextPost($artid)}
-        {imglink group=$group artid=$spool->nextPost($artid) img=next alt="Message suivant"|b accesskey=z}{/if}
-        {if $spool->prevThread($artid)}
-        {imglink group=$group artid=$spool->prevThread($artid) img=prev_thread alt="Discussion précédente"|b accesskey=q}{/if}
-        {if $spool->nextThread($artid)}
-        {imglink group=$group artid=$spool->nextThread($artid) img=next_thread alt="Discussion suivante"|b accesskey=s}{/if}
+        {assign var=nextUnread value=$spool->nextUnread($artid)}
+        {assign var=prevPost value=$spool->prevPost($artid)}
+        {assign var=nextPost value=$spool->nextPost($artid)}
+        {assign var=prevThread value=$spool->prevThread($artid)}
+        {assign var=nextThread value=$spool->nextThread($artid)}
+        {if $nextUnread}{imglink group=$group artid=$nextUnread img=next_unread alt="Message non-lu suivant"|b accesskey=u}{/if}
+        {if $prevPost}{imglink group=$group artid=$prevPost img=prev alt="Message précédent"|b accesskey=a}{/if}
+        {if $nextPost}{imglink group=$group artid=$nextPost img=next alt="Message suivant"|b accesskey=z}{/if}
+        {if $prevThread}{imglink group=$group artid=$prevThread img=prev_thread alt="Discussion précédente"|b accesskey=q}{/if}
+        {if $nextThread}{imglink group=$group artid=$nextThread img=next_thread alt="Discussion suivante"|b accesskey=s}{/if}
       </div>
       <div class="action">
         {if $message->canSend()}
       {$body|banana_utf8entities|smarty:nodefaults}
     </td>
   </tr>
+  {if $spool && ($nextPost || $prevPost)}
+  <tr class="pair">
+    <th colspan="3">
+      <strong>{"Naviguer dans la discussion..."|b}</strong>
+    </th>
+  </tr>
+  <tr class="pair">
+    <td colspan="3" class="thread_tree">{$spool->buildTree($artid)|smarty:nodefaults}</td>
+  </tr>
+  {/if}
 </table>
 
 {* vim:set et sw=2 sts=2 ts=2 enc=utf-8: *}
index 7fce61b..3729385 100644 (file)
@@ -1,8 +1,8 @@
 {capture name=pages}
 {if $withtitle}
 <div class="pages">
-{if $spool->overview|@count gt $msgbypage}
-{section name=pages loop=$spool->overview step=$msgbypage}
+{if $spool->roots|@count gt $msgbypage}
+{section name=pages loop=$spool->roots step=$msgbypage}
   {if $first ge $smarty.section.pages.index && $first lt $smarty.section.pages.index_next}
     <strong>{$smarty.section.pages.iteration}</strong>
   {else}
   <tr>
     {if $withtitle}
     <th>
-      {if $spool->nextUnread()}
+      {assign var=nextUnread value=$spool->nextUnread()}
+      {if $nextUnread}
       <div class="menu">
-        {imglink group=$group artid=$spool->nextUnread() img=next_unread alt="Message non-lu suivant"|b accesskey=u}
+        {imglink group=$group artid=$nextUnread img=next_unread alt="Message non-lu suivant"|b accesskey=u}
       </div>
       {/if}
       {"Date"|b}
       {"Auteur"|b}
     </th>
     {else}
-    <th colspan="3">
-      {"Aperçu de "|b}{link group=$group text=$group}
-    </th>
+    <th colspan="3">{"En discussion sur "|b}{link group=$group text=$group}...</th>
     {/if}
   </tr>
-  {if $spool->overview|@count}
-  {if $artid}{$spool->toHtml($artid, true)|smarty:nodefaults}{else}{$spool->toHtml($first)|smarty:nodefaults}{/if}
+  {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]}
+  {cycle assign=class values="impair,pair"}
+  <tr class="{$class} {if $overview->descunread}new{/if}">
+    <td class="date">{$spool->formatDate($overview->date)}</td>
+    <td class="subj">{$spool->formatSubject($id, $overview->subject)|smarty:nodefaults}</td>
+    <td class="from">{$spool->formatFrom($overview->from)|smarty:nodefaults}</td>
+  </tr>
+  {if !$artid && $spool->nextPost($id)}
+  <tr class="{$class}">
+    <td colspan="3" class="thread_tree">{$spool->buildTree($id)|smarty:nodefaults}</td>
+  </tr>
+  {/if}
+  {/section}
   {else}
   <tr>
     <td colspan="3">
index 98f6b67..660eeb9 100644 (file)
@@ -72,8 +72,8 @@
     background-color: #fff;
 }
 
-.banana pre.thread_tree {
-  overflow: scroll;
+.banana td.thread_tree, .banana div.thread_tree {
+  overflow: auto;
 }
 
 .banana .thread_tree input {