AXLetter module.
authorx2003bruneau <x2003bruneau@839d8a87-29fc-0310-9880-83ba4fa771e5>
Fri, 19 Jan 2007 16:13:30 +0000 (16:13 +0000)
committerx2003bruneau <x2003bruneau@839d8a87-29fc-0310-9880-83ba4fa771e5>
Fri, 19 Jan 2007 16:13:30 +0000 (16:13 +0000)
The module is not finished, but I commit in order to allow cooperative work.

git-svn-id: svn+ssh://murphy/home/svn/platal/trunk@1357 839d8a87-29fc-0310-9880-83ba4fa771e5

configs/mails.conf
htdocs/css/ax.css [new file with mode: 0644]
htdocs/xorg.php
include/massmailer.inc.php
modules/axletter.php [new file with mode: 0644]
modules/axletter/axletter.inc.php [new file with mode: 0644]
templates/axletter/edit.tpl [new file with mode: 0644]
templates/axletter/index.tpl [new file with mode: 0644]
templates/axletter/letter.tpl [new file with mode: 0644]
templates/axletter/show.tpl [new file with mode: 0644]
upgrade/0.9.13/04_axletter.sql [new file with mode: 0644]

index 16ec787..fb38f72 100644 (file)
@@ -23,6 +23,6 @@ from=support@polytechnique.org
 from="Lettre Mensuelle Polytechnique.org" <info_newsletter@polytechnique.org>
 replyto=info+nlp@polytechnique.org
 
-[emails_broken]
-from="Polytechnique.org" <support@polytechnique.org>
-subject="Une de tes adresse de redirection Polytechnique.org ne marche plus !!"
+[mails_ax]
+from="Association des Anciens élèves de l'X" <info@amicale.polytechnique.org>
+replyto=info@amicale.polytechnique.org
diff --git a/htdocs/css/ax.css b/htdocs/css/ax.css
new file mode 100644 (file)
index 0000000..e35cd5d
--- /dev/null
@@ -0,0 +1,108 @@
+/***************************************************************************
+ *  Copyright (C) 2003-2007 Polytechnique.org                              *
+ *  http://opensource.polytechnique.org/                                   *
+ *                                                                         *
+ *  This program is free software; you can redistribute it and/or modify   *
+ *  it under the terms of the GNU General Public License as published by   *
+ *  the Free Software Foundation; either version 2 of the License, or      *
+ *  (at your option) any later version.                                    *
+ *                                                                         *
+ *  This program is distributed in the hope that it will be useful,        *
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ *  GNU General Public License for more details.                           *
+ *                                                                         *
+ *  You should have received a copy of the GNU General Public License      *
+ *  along with this program; if not, write to the Free Software            *
+ *  Foundation, Inc.,                                                      *
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
+ ***************************************************************************/
+
+
+div.ax_mail {
+    margin : auto;
+    width : 72ex;
+    font-family : "Georgia", "Times New Roman", serif;
+    font-size : 11pt;
+    text-align : justify;
+    background-color : #fff;
+    color : #000;
+}
+
+div.ax_mail a[href] {
+    text-decoration : none;
+    background-color : #fff;
+    color : #36c;
+}
+
+div.ax_mail a[href]:hover {
+    background-color : #fff;
+    color : #6c0;
+}
+
+div.ax_mail div.title {
+    margin : 0 0 3ex;
+    padding : 5ex 1ex 1ex 15ex;
+    font-size : 130%;
+    font-weight : bold;
+    text-align : right;
+    background-color : #e40;
+    color : #ed0;
+    background-repeat : no-repeat;
+    background-position : 0ex 0.5ex;
+}
+
+div.ax_mail div.intro {
+    margin : 4ex 3ex;
+}
+
+div.ax_mail div.body {
+    margin : 2ex 3ex;
+}
+
+div.ax_mail div.body h1 {
+    margin : 3ex 0 1ex;
+    padding : 1.5ex 2ex 0.5ex 0ex;
+    font-size : 120%;
+    font-weight : bold;
+    color : #400;
+}   
+    
+div.ax_mail div.body h2 {
+    margin : 0ex 0 0;
+    padding : 0.4ex 2ex;
+    font-size : 100%;
+    font-weight : bold;
+    font-style : italic;
+    background-color : #fff;
+    color : #440;
+}
+
+div.ax_mail div.signature {
+    margin : 2ex 2ex 0 0ex;
+    font-size : 80%;
+    font-style: italic;
+    text-align : right;
+
+}
+
+div.ax_mail div.foot1 {
+    margin : 2ex 0 0;
+    padding : 0.5ex 2ex;
+    font-size : 90%;
+    background-color : #fff;
+    color : #999;
+    border-width : thin 0;
+    border-style : solid;
+    border-color : #ddd;
+    text-align : center;
+}
+
+div.ax_mail div.foot2 {
+    padding : 1ex 0;
+    font-size : 90%;
+    background-color : #fff;
+    color : #999;
+    text-align : center;
+}
+
index 8042b5e..9a40d01 100644 (file)
@@ -28,7 +28,7 @@ if (!($path = Env::v('n')) || ($path{0} < 'A' || $path{0} > 'Z')) {
     $platal = new Platal('auth', 'banana', 'carnet', 'email', 'events',
                          'geoloc', 'lists', 'marketing', 'payment', 'platal',
                          'profile', 'register', 'search', 'stats', 'admin',
-                         'newsletter');
+                         'newsletter', 'axletter');
     $platal->run();
 
     exit;
index e326a31..d9ad35e 100644 (file)
@@ -62,12 +62,7 @@ abstract class MassMailer
             $head = str_replace('<cher>',   $sexe ? 'Chère' : 'Cher', $head);
             $head = str_replace('<prenom>', $prenom, $head);
             $head = str_replace('<nom>',    $nom,    $head);
-            if ($type == 'text') {
-                $head = enriched_to_text($head, false, true, 2, 64);
-            } else {
-                $head = enriched_to_text($head, true);
-            }
-            return $head;
+            return format_text($head, $type, 2, 64);
         }
     }
 
@@ -206,6 +201,14 @@ function justify($text,$n)
     return trim($res);
 }
 
+function format_text($input, $format, $indent = 0, $width = 68)
+{
+    if ($format == 'text') {
+        return enriched_to_text($input, false, true, $indent, $width);
+    }
+    return enriched_to_text($input, true);
+}
+
 function enriched_to_text($input,$html=false,$just=false,$indent=0,$width=68)
 {
     $text = trim($input);
@@ -217,6 +220,11 @@ function enriched_to_text($input,$html=false,$just=false,$indent=0,$width=68)
         $text = str_replace('[/i]','</em>', $text);
         $text = str_replace('[u]','<span style="text-decoration: underline">', $text);
         $text = str_replace('[/u]','</span>', $text);
+        $text = preg_replace("!(\\s*\n)*\[title\]!",'<h1>',$text);
+        $text = preg_replace("!\[\/title\](\\s*\n)*!", '</h1>',$text);
+        $text = preg_replace("!(\\s*\n)*\[subtitle\]!",'<h2>',$text);
+        $text = preg_replace("!\[\/subtitle\](\\s*\n)*!",'</h2>',$text);
+
         require_once('url_catcher.inc.php');
         $text = url_catcher($text);
         return nl2br($text);
@@ -224,6 +232,8 @@ function enriched_to_text($input,$html=false,$just=false,$indent=0,$width=68)
         $text = preg_replace('!\[\/?b\]!','*',$text);
         $text = preg_replace('!\[\/?u\]!','_',$text);
         $text = preg_replace('!\[\/?i\]!','/',$text);
+        $text = preg_replace('!\[\/?title\]!','***', $text);
+        $text = preg_replace('!\[\/?subtitle\]!','**', $text);
         $text = preg_replace('!(((https?|ftp)://|www\.)[^\r\n\t ]*)!','[\1]', $text);
         $text = preg_replace('!(([a-zA-Z0-9\-_+.]*@[a-zA-Z0-9\-_+.]*)(?:\?[^\r\n\t ]*)?)!','[mailto:\1]', $text);
         $text = $just ? justify($text,$width-$indent) : wordwrap($text,$width-$indent);
diff --git a/modules/axletter.php b/modules/axletter.php
new file mode 100644 (file)
index 0000000..4926ddb
--- /dev/null
@@ -0,0 +1,273 @@
+<?php
+/***************************************************************************
+ *  Copyright (C) 2003-2007 Polytechnique.org                              *
+ *  http://opensource.polytechnique.org/                                   *
+ *                                                                         *
+ *  This program is free software; you can redistribute it and/or modify   *
+ *  it under the terms of the GNU General Public License as published by   *
+ *  the Free Software Foundation; either version 2 of the License, or      *
+ *  (at your option) any later version.                                    *
+ *                                                                         *
+ *  This program is distributed in the hope that it will be useful,        *
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ *  GNU General Public License for more details.                           *
+ *                                                                         *
+ *  You should have received a copy of the GNU General Public License      *
+ *  along with this program; if not, write to the Free Software            *
+ *  Foundation, Inc.,                                                      *
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
+ ***************************************************************************/
+
+class AXLetterModule extends PLModule
+{
+    function handlers()
+    {
+        return array(
+            'ax'             => $this->make_hook('index',        AUTH_COOKIE),
+            'ax/show'        => $this->make_hook('show',   AUTH_COOKIE),
+            'ax/edit'        => $this->make_hook('submit', AUTH_MDP),
+            'ax/edit/cancel' => $this->make_hook('cancel', AUTH_MDP),
+            'ax/edit/valid'  => $this->make_hook('valid',  AUTH_MDP),
+            'admin/axletter/rights'        => $this->make_hook('admin_rights', AUTH_MDP, 'admin'),
+        );
+    }
+
+    function handler_index(&$page, $action = null, $hash = null)
+    {
+        require_once dirname(__FILE__) . '/axletter/axletter.inc.php';
+
+        $page->changeTpl('axletter/index.tpl');
+        $page->assign('xorg_title','Polytechnique.org - Envois de l\'AX');
+
+        switch ($action) {
+          case 'out': AXLetter::unsubscribe($hash); break;
+          case 'in':  AXLetter::subscribe(); break;
+          default: ;
+        }
+
+        $perm = AXLetter::hasPerms();
+        if ($perm) {
+            $waiting = AXLetter::awaiting();
+            if ($waiting) {
+                $new = new AXLetter($waiting);
+                $page->assign('new', $new);
+            }
+        }
+        $page->assign('axs', AXLetter::subscriptionState());
+        $page->assign('ax_list', AXLetter::listSent());
+        $page->assign('ax_rights', $perm);
+    }
+
+    function handler_submit(&$page, $action = null)
+    {
+        require_once dirname(__FILE__) . '/axletter/axletter.inc.php';
+        if (!AXLetter::hasPerms()) {
+            return PL_FORBIDDEN;
+        }
+
+        $page->changeTpl('axletter/edit.tpl');
+
+        $saved     = Post::i('saved');
+        $new       = false;
+        $id        = Post::i('id');
+        $shortname = trim(Post::v('shortname'));
+        $subject   = trim(Post::v('subject'));
+        $title     = trim(Post::v('title'));
+        $body      = rtrim(Post::v('body'));
+        $signature = trim(Post::v('signature'));
+        $promo_min = Post::i('promo_min');
+        $promo_max = Post::i('promo_max');
+        $echeance  = Post::has('echeance_date') ? Post::v('echeance_date') . ' ' . Post::v('echeance_time')
+                                                : Post::v('echeance');
+        $echeance_date = Post::v('echeance_date');
+        $echeance_time = Post::v('echeance_time');
+
+        if (!$id) {
+            $res = XDB::query("SELECT * FROM axletter WHERE FIND_IN_SET('new', bits)");
+            if ($res->numRows()) {
+                extract($res->fetchOneAssoc(), EXTR_OVERWRITE);
+                $saved = true;
+            } else  {
+                XDB::execute("INSERT INTO axletter SET id = NULL");
+                $id  = XDB::insertId();
+            }
+            if (!$echeance || $echeance == '0000-00-00 00:00:00') {
+                $saved = false;
+                $new   = true;
+            }
+        } elseif (Post::has('valid')) {
+            if (!$subject && $title) {
+                $subject = $title;
+            }
+            if (!$title && $subject) {
+                $title = $subject;
+            }
+            if (!$subject || !$title || !$body) {
+                $page->trig("L'article doit avoir un sujet et un contenu");
+                Post::kill('valid');
+            }
+            if (($promo_min > $promo_max && $promo_max != 0)||
+                ($promo_min != 0 && ($promo_min <= 1900 || $promo_min >= 2020)) ||
+                ($promo_max != 0 && ($promo_max <= 1900 || $promo_max >= 2020)))
+            {
+                $page->trig("L'intervalle de promotions n'est pas valide");
+                Post::kill('valid');
+            }
+            if (empty($shortname)) {
+                $page->trig("L'annonce doit avoir un nom raccourci pour simplifier la navigation dans les archives");
+                Post::kill('valid');
+            } elseif (!preg_match('/^[a-z][-a-z0-9]*[a-z0-9]$/', $shortname)) {
+                $page->trig("Le nom raccourci n'est pas valide, il doit comporter au moins 2 caractères et n'être composé "
+                          . "que de chiffres, lettres et tirets");
+                Post::kill('valid');
+            } elseif ($shortname != Post::v('old_shortname')) {
+                $res = XDB::query("SELECT id FROM axletter WHERE  shortname = {?}", $shortname);
+                if ($res->numRows() && $res->fetchOneCell() != $id) {
+                    $page->trig("Le nom $shortname est déjà utilisé, merci d'en choisir un autre");
+                    $shortname = Post::v('old_shortname');
+                    if (empty($shortname)) {
+                        Post::kill('valid');
+                    }
+                }
+            }
+
+            switch (@Post::v('valid')) {
+              case 'Aperçu':
+                require_once dirname(__FILE__) . '/axletter/axletter.inc.php';
+                $al = new AXLetter(array($id, $shortname, $subject, $title, $body, $signature,
+                                         $promo_min, $promo_max, $echeance, 0, 'new'));
+                $al->toHtml($page, S::v('prenom'), S::v('nom'), S::v('femme'));
+                break;
+
+              case 'Confirmer':
+                XDB::execute("REPLACE INTO  axletter
+                                       SET  id = {?}, shortname = {?}, subject = {?}, title = {?}, body = {?},
+                                            signature = {?}, promo_min = {?}, promo_max = {?}, echeance = {?}",
+                             $id, $shortname, $subject, $title, $body, $signature, $promo_min, $promo_max, $echeance);
+                $saved = true;
+                $echeance_date = null;
+                $echeance_time = null;
+                pl_redirect('ax');
+                break;
+            }
+        }
+        $page->assign('id', $id);
+        $page->assign('shortname', $shortname);
+        $page->assign('subject', $subject);
+        $page->assign('title', $title);
+        $page->assign('body', $body);
+        $page->assign('signature', $signature);
+        $page->assign('promo_min', $promo_min);
+        $page->assign('promo_max', $promo_max);
+        $page->assign('echeance', $echeance);
+        $page->assign('echeance_date', $echeance_date);
+        $page->assign('echeance_time', $echeance_time);
+        $page->assign('saved', $saved);
+        $page->assign('new', $new);
+        $page->assign('is_xorg', S::has_perms());
+
+        if (!$saved) {
+            $select = '';
+            $time   = time() + 3600 * 24 * 2;
+            for ($i = 0 ; $i < 15 ; $i++) {
+                $time    += 3600 * 24;
+                $p_stamp = date('Ymd', $time);
+                $year    = date('Y',   $time);
+                $month   = date('m',   $time);
+                $day     = date('d',   $time);
+                
+                if ($p_stamp == $echeance_date) {
+                    $sel = ' selected="selected"';
+                } else {
+                    $sel = '';
+                }
+                $select .= "<option value=\"$p_stamp\"$sel> $day / $month / $year</option>\n";
+            }
+            $page->assign('echeance_date', $select);
+            $select = '';
+            for ($i = 0 ; $i < 24 ; $i++) {
+                $stamp = sprintf('%02d:00:00', $i);
+                if ($stamp == $echeance_time) {
+                    $sel = ' selected="selected"';
+                } else {
+                    $sel = '';
+                }
+                $select .= "<option value=\"$stamp\"$sel>{$i}h</option>\n";
+            }
+            $page->assign('echeance_time', $select);
+        }    
+    }
+
+    function handler_cancel(&$page, $force = null)
+    {
+        require_once dirname(__FILE__) . '/axletter/axletter.inc.php';
+        if (!AXLetter::hasPerms()) {
+            return PL_FORBIDDEN;
+        }
+
+        $url = parse_url($_SERVER['HTTP_REFERER']);
+        if ($force != 'force' && trim($url['path'], '/') != 'ax/edit') {
+            return PL_FORBIDDEN;
+        }
+
+        $waiting = AXLetter::awaiting();
+        if (!$waiting) {
+            $page->kill("Aucune lettre en attente");
+            return;
+        }
+        $al = new AXLetter($waiting);
+        if (!$al->invalid()) {
+            $page->kill("Une erreur est survenue lors de l'annulation de l'envoi");
+            return;
+        }
+
+        $page->kill("L'envoi de l'annonce {$al->title()} est annulé");
+    }
+
+    function handler_valid(&$page, $force = null)
+    {
+        require_once dirname(__FILE__) . '/axletter/axletter.inc.php';
+        if (!AXLetter::hasPerms()) {
+            return PL_FORBIDDEN;
+        }
+
+        $url = parse_url($_SERVER['HTTP_REFERER']);
+        if ($force != 'force' && trim($url['path'], '/') != 'ax/edit') {
+            return PL_FORBIDDEN;
+        }
+
+        $waiting = AXLetter::awaiting();
+        if (!$waiting) {
+            $page->kill("Aucune lettre en attente");
+            return;
+        }
+        $al = new AXLetter($waiting);
+        if (!$al->valid()) {
+            $page->kill("Une erreur est survenue lors de la validation de l'envoi");
+            return;
+        }
+
+        $page->kill("L'envoi de l'annonce aura lieu dans l'heure qui vient.");
+    }
+
+    function handler_show(&$page, $nid = 'last')
+    {
+        require_once dirname(__FILE__) . '/axletter/axletter.inc.php';
+        $page->changeTpl('axletter/show.tpl');
+
+        $nl  = new AXLetter($nid);
+        if (Get::has('text')) {
+            $nl->toText($page, S::v('prenom'), S::v('nom'), S::v('femme'));
+        } else {
+            $nl->toHtml($page, S::v('prenom'), S::v('nom'), S::v('femme'));
+        }
+        if (Post::has('send')) {
+            $nl->sendTo(S::v('prenom'), S::v('nom'),
+                        S::v('bestalias'), S::v('femme'),
+                        S::v('mail_fmt') != 'texte');
+        }
+    }
+}
+
+?>
diff --git a/modules/axletter/axletter.inc.php b/modules/axletter/axletter.inc.php
new file mode 100644 (file)
index 0000000..178a0d3
--- /dev/null
@@ -0,0 +1,200 @@
+<?php
+/***************************************************************************
+ *  Copyright (C) 2003-2007 Polytechnique.org                              *
+ *  http://opensource.polytechnique.org/                                   *
+ *                                                                         *
+ *  This program is free software; you can redistribute it and/or modify   *
+ *  it under the terms of the GNU General Public License as published by   *
+ *  the Free Software Foundation; either version 2 of the License, or      *
+ *  (at your option) any later version.                                    *
+ *                                                                         *
+ *  This program is distributed in the hope that it will be useful,        *
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of         *
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          *
+ *  GNU General Public License for more details.                           *
+ *                                                                         *
+ *  You should have received a copy of the GNU General Public License      *
+ *  along with this program; if not, write to the Free Software            *
+ *  Foundation, Inc.,                                                      *
+ *  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA                *
+ ***************************************************************************/
+
+require_once("massmailer.inc.php");
+
+class AXLetter extends MassMailer
+{
+    public $_body;
+    public $_signature;
+    public $_promo_min;
+    public $_promo_max;
+    public $_echeance;
+    public $_date;
+    public $_bits;
+
+    function __construct($id)
+    {
+        parent::__construct('axletter/letter.tpl', 'ax.css', 'ax/show');
+        $this->_head = '<cher> <prenom>,';
+
+        if (!is_array($id)) {
+            if ($id == 'last') {
+                $res = XDB::query("SELECT  *
+                                     FROM  axletter
+                                    WHERE  FIND_IN_SET('sent', bits)
+                                 ORDER BY  id DESC");
+            } else {
+                $res = XDB::query("SELECT  *
+                                     FROM  axletter
+                                    WHERE  id = {?} OR shortname = {?}", $id, $id);
+            }
+            if (!$res->numRows()) {
+                $this->_id = null;
+                return;
+            }
+            $id = $res->fetchOneRow();
+        }
+        list($this->_id, $this->_shortname, $this->_title_mail, $this->_title,
+             $this->_body, $this->_signature, $this->_promo_min, $this->_promo_max,
+             $this->_echeance, $this->_date, $this->_bits) = $id;
+    }
+
+    protected function assignData(&$smarty)
+    {
+        $smarty->assign_by_ref('am', $this);
+    }
+
+    public function body($format)
+    {
+        return format_text($this->_body, $format);
+    }
+
+    public function signature($format)
+    {
+        return format_text($this->_signature, $format, 10);
+    }
+
+    static public function create($subject, $title, $body, $signature, $promo_min, $promo_max, $date, $shortname = null)
+    {
+        $id = AXLetter::awaiting();
+        if ($id) {
+            return new AXLetter($id);
+        }
+        XDB::execute("INSERT INTO  axletter (shortname, echeance,  promo_min, promo_max,
+                                     subject, title, body, signature,
+                                     subject_ini, title_ini, body_ini, signature_ini)
+                           VALUES  ({?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?})",
+                     $shortname, $date, $promo_min, $promo_max,
+                     $subject, $title, $body, $signature, $subject, $title, $body, $signature);
+        return new AXLetter(XDB::insertId());
+    }
+
+    public function update($subject, $title, $body, $signature, $promo_min, $promo_max, $date, $shortname = null)
+    {
+        $this->_shortname  = $shortname;
+        $this->_title      = $title;
+        $this->_title_mail = $subject;
+        $this->_body       = $body;
+        $this->_signature  = $signature;
+        $this->_promo_min  = $promo_min;
+        $this->_promo_max  = $promo_max;
+        $this->_date       = $date;
+        return XDB::execute("UPDATE  axletter (shortname, subject, title, body, signature, promo_min, promo_max, echeance)
+                                SET  shorname={?}, subject={?}, title={?}, body={?}, signature={?},
+                                     promo_min={?}, promo_max={?}, echeance={?}
+                              WHERE  id = {?}",
+                            $shortname, $subject, $title, $body, $signature, $promo_min, $promo_max, $date, $this->_id);
+    }
+
+    public function valid()
+    {
+        return XDB::execute("UPDATE  axletter
+                                SET  echeance = NOW()
+                              WHERE  id = {?}", $this->_id);
+    }
+
+    public function invalid()
+    {
+        return XDB::execute("UPDATE  axletter
+                                SET  bits = 'invalid', date = CURDATE()
+                              WHERE  id = {?}", $this->_id);
+    }
+
+    protected function setSent()
+    {
+        XDB::execute("UPDATE  axletter
+                         SET  bits='sent', date=CURDATE()
+                       WHERE  id={?}", $this->_id);
+    }
+
+    static public function subscriptionState($uid = null)
+    {
+        $user = is_null($uid) ? S::v('uid') : $uid;
+        $res = XDB::query("SELECT  1
+                             FROM  axletter_ins
+                            WHERE  user_id={?}", $user);
+        return $res->fetchOneCell();
+    }   
+    
+    static public function unsubscribe($uid = null)
+    {
+        $user = is_null($uid) ? S::v('uid') : $uid;
+        XDB::execute("DELETE FROM  axletter_ins
+                            WHERE  user_id={?} OR hash = {?}", $user, $user);
+    }
+
+    static public function subscribe($uid = null)
+    {
+        $user = is_null($uid) ? S::v('uid') : $uid;
+        XDB::execute("REPLACE INTO  axletter_ins (user_id,last)
+                            VALUES  ({?}, 0)", $user);
+    }
+
+    static public function hasPerms()
+    {
+        if (S::has_perms()) {
+            return true;
+        }
+        $res = XDB::query("SELECT  1
+                             FROM  axletter_rights
+                            WHERE  user_id = {?}", S::i('uid'));
+        return $res->fetchOneCell();
+    }
+
+    protected function subscriptionTable()
+    {
+        return 'axletter_ins';
+    }
+
+    protected function subscriptionWhere()
+    {
+        return 'ni.last';
+    }
+
+    static public function awaiting()
+    {
+        $res = XDB::query("SELECT  id
+                             FROM  axletter
+                            WHERE  FIND_IN_SET('new', bits)");
+        return $res->fetchOneCell();
+    }
+
+    static public function listSent()
+    {   
+        $res = XDB::query("SELECT  IF(shortname IS NULL, id, shortname) as id, date, subject AS titre
+                             FROM  axletter
+                            WHERE  NOT (FIND_IN_SET('new', bits))
+                         ORDER BY  date DESC");
+        return $res->fetchAllAssoc();
+    }
+    
+    static public function listAll()
+    {   
+        $res = XDB::query("SELECT  IF(shortname IS NULL, id, shortname) as id, date, subject AS titre
+                             FROM  axletter
+                         ORDER BY  date DESC");
+        return $res->fetchAllAssoc();
+    }
+}
+
+// vim:set et sw=4 sts=4 sws=4:
+?>
diff --git a/templates/axletter/edit.tpl b/templates/axletter/edit.tpl
new file mode 100644 (file)
index 0000000..126852a
--- /dev/null
@@ -0,0 +1,114 @@
+{**************************************************************************}
+{*                                                                        *}
+{*  Copyright (C) 2003-2006 Polytechnique.org                             *}
+{*  http://opensource.polytechnique.org/                                  *}
+{*                                                                        *}
+{*  This program is free software; you can redistribute it and/or modify  *}
+{*  it under the terms of the GNU General Public License as published by  *}
+{*  the Free Software Foundation; either version 2 of the License, or     *}
+{*  (at your option) any later version.                                   *}
+{*                                                                        *}
+{*  This program is distributed in the hope that it will be useful,       *}
+{*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *}
+{*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *}
+{*  GNU General Public License for more details.                          *}
+{*                                                                        *}
+{*  You should have received a copy of the GNU General Public License     *}
+{*  along with this program; if not, write to the Free Software           *}
+{*  Foundation, Inc.,                                                     *}
+{*  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA               *}
+{*                                                                        *}
+{**************************************************************************}
+
+<h1>Edition de message</h1>
+
+<form action="{$platal->pl_self()}" method="post">
+  {if $am}
+  {include file="axletter/letter.tpl"}
+
+  <p class="center">
+    <input type="hidden" name="id" value="{$id}" />
+    <input type="hidden" name="old_shortname" value="{$shortname}" />
+    <input type="hidden" name="saved" value="{$saved}" />
+    {if $echeance}
+    <input type="hidden" name="echeance" value="{$echeance}" />
+    {/if}
+    {if !$new}
+    <input type="submit" name="valid" value="Confirmer" />
+    {/if}
+  </p>
+  {/if}
+
+  <fieldset>
+    <legend>Sujet du mail : <input type="text" name="subject" value="{$subject}" size="60"/></legend>
+    <p class="center">
+      <strong>Titre : </strong><input type="text" name="title" value="{$title}" size="60" /><br />
+      <textarea name="body" rows="30" cols="78">{$body}</textarea><br />
+      <strong>Signature : </strong><input type="text" name="signature" value="{$signature}" size="60" />
+    </p>
+  </fieldset>
+
+  <table class="tinybicol">
+    <tr>
+      <th colspan="2">Options du message</th>
+    </tr>
+    <tr>
+      <td class="titre">Nom raccourci</td>
+      <td>
+        <input type="text" name="shortname" value="{$shortname}" size="16" maxlength="16" />
+        <span class="smaller">(uniquement lettres, chiffres ou -)</span>
+      </td>
+    </tr>
+    <tr>
+      <td class="titre">Promo min</td>
+      <td>
+        <input type="text" name="promo_min" value="{$promo_min|default:0}" size="4" maxlength="4" />
+        <span class="smaller">(0 pour pas de minimum... ex: 1947)</span>
+      </td>
+    </tr>
+    <tr>
+      <td class="titre">Promo max</td>
+      <td>
+        <input type="text" name="promo_max" value="{$promo_max|default:0}" size="4" maxlength="4" />
+        <span class="smaller">(0 pour pas de maximum... ex: 2001)</span>
+      </td>
+    </tr>
+    {if !$saved}
+    <tr>
+      <td class="titre">Echéance d'envoi</td>
+      <td>
+        le <select name="echeance_date">{$echeance_date|smarty:nodefaults}</select>
+        vers <select name="echeance_time">{$echeance_time|smarty:nodefaults}</select>
+      </td>
+    </tr>
+    {else}
+    <tr>
+      <td colspan="2" class="center">
+        Envoi au plus tard le {$echeance|date_format:"%x vers %Hh"}<br />
+        {if $is_xorg}
+        [<a href="ax/edit/valid" onclick="return confirm('Es-tu sûr de voiloir valider l\'envoi de ce message ?');">{*
+          *}{icon name=thumb_up} Valider l'envoi</a>]
+        {else}
+        [<a href="ax/edit/cancel" onclick="return confirm('Es-tu sûr de vouloir annuler l\'envoi de ce message ?');">{*
+          *}{icon name=thumb_down} Annuler l'envoi</a>]
+        {/if}
+      </td>
+    </tr>
+    {/if}
+  </table>
+
+  <p class="center">
+    <input type="hidden" name="id" value="{$id}" />
+    <input type="hidden" name="old_shortname" value="{$shortname}" />
+    <input type="hidden" name="saved" value="{$saved}" />
+    {if $echeance}
+    <input type="hidden" name="echeance" value="{$echeance}" />
+    {/if}
+    <input type="submit" name="valid" value="Aperçu" />
+    {if !$new}
+    <input type="submit" name="valid" value="Confirmer" />
+    {/if}
+  </p>
+</form>
+
+{* vim:set et sw=2 sts=2 sws=2: *}
diff --git a/templates/axletter/index.tpl b/templates/axletter/index.tpl
new file mode 100644 (file)
index 0000000..b6ed9fc
--- /dev/null
@@ -0,0 +1,80 @@
+{**************************************************************************}
+{*                                                                        *}
+{*  Copyright (C) 2003-2006 Polytechnique.org                             *}
+{*  http://opensource.polytechnique.org/                                  *}
+{*                                                                        *}
+{*  This program is free software; you can redistribute it and/or modify  *}
+{*  it under the terms of the GNU General Public License as published by  *}
+{*  the Free Software Foundation; either version 2 of the License, or     *}
+{*  (at your option) any later version.                                   *}
+{*                                                                        *}
+{*  This program is distributed in the hope that it will be useful,       *}
+{*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *}
+{*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *}
+{*  GNU General Public License for more details.                          *}
+{*                                                                        *}
+{*  You should have received a copy of the GNU General Public License     *}
+{*  along with this program; if not, write to the Free Software           *}
+{*  Foundation, Inc.,                                                     *}
+{*  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA               *}
+{*                                                                        *}
+{**************************************************************************}
+
+
+<h1>
+  Envoi exceptionnel de l'AX
+</h1>
+
+<h2>Ton statut</h2>
+
+{if $axs}
+<p>
+Tu es actuellement inscrit aux envois exceptionnels de l'AX (pour choisir le format HTML ou texte, rends toi sur la page <a href='prefs'>des préférences</a>)
+</p>
+<div class='center'>
+  [<a href='ax/out'>{icon name=delete} me désinscrire des envois exceptionnels</a>]
+</div>
+{else}
+<p>
+Tu n'es actuellement pas inscrit à la lettre mensuelle de Polytechnique.org.
+</p>
+<div class='center'>
+  [<a href='ax/in'>{icon name=add} m'inscrire</a>]
+</div>
+{/if}
+
+<h2>Les archives</h2>
+
+<table class="bicol" cellpadding="3" cellspacing="0" summary="liste des NL">
+  <tr>
+    <th>date</th>
+    <th>titre</th>
+  </tr>
+  {if $ax_rights && !$new}
+  <tr class="pair">
+    <td colspan="2" class="center">
+      <a href="ax/edit">{icon name=page_edit} Proposer un nouveau mail</a>
+    </td>
+  </tr>
+  {elseif $ax_rights && $new}
+  <tr class="pair">
+    <td><a href="ax/edit">{icon name=page_edit} Editer la demande</a></td>
+    <td>
+      {if $new->title()}
+      <a href="ax/show/{$new->id()}"><strong>{$new->title(true)}</strong></a>
+      {/if}
+    </td>
+  </tr>
+  {/if}
+  {foreach item=al from=$ax_list}
+  <tr class="{cycle values="impair,pair"}">
+    <td>{$al.date|date_format}</td>
+    <td>
+      <a href="ax/show/{$al.id}">{$al.titre}</a>
+    </td>
+  </tr>
+  {/foreach}
+</table>
+
+
+{* vim:set et sw=2 sts=2 sws=2: *}
diff --git a/templates/axletter/letter.tpl b/templates/axletter/letter.tpl
new file mode 100644 (file)
index 0000000..8bf2c74
--- /dev/null
@@ -0,0 +1,90 @@
+{**************************************************************************}
+{*                                                                        *}
+{*  Copyright (C) 2003-2006 Polytechnique.org                             *}
+{*  http://opensource.polytechnique.org/                                  *}
+{*                                                                        *}
+{*  This program is free software; you can redistribute it and/or modify  *}
+{*  it under the terms of the GNU General Public License as published by  *}
+{*  the Free Software Foundation; either version 2 of the License, or     *}
+{*  (at your option) any later version.                                   *}
+{*                                                                        *}
+{*  This program is distributed in the hope that it will be useful,       *}
+{*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *}
+{*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *}
+{*  GNU General Public License for more details.                          *}
+{*                                                                        *}
+{*  You should have received a copy of the GNU General Public License     *}
+{*  along with this program; if not, write to the Free Software           *}
+{*  Foundation, Inc.,                                                     *}
+{*  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA               *}
+{*                                                                        *}
+{**************************************************************************}
+
+{if !$html_version}
+{if $is_mail}
+{config_load file="mails.conf" section="mails_ax"}
+{from full=#from#}
+{subject text=$am->title(true)}
+{if isset(#replyto#)}{add_header name='Reply-To' value=#replyto#}{/if}
+{if isset(#retpath#)}{add_header name='Return-Path' value=#retpath#}{/if}
+{else}
+<pre style="width : 72ex; margin: auto">
+{/if}
+====================================================================
+{$am->title()}
+====================================================================
+
+{$am->head($prenom, $nom, $sexe, 'text')}
+
+{$am->body('text')}
+
+{$am->signature('text')}
+
+--------------------------------------------------------------------
+Cette lettre est envoyée à tous les Polytechniciens sur Internet par
+l'intermédiaire de Polytechnique.org.
+
+archives         : [https://www.polytechnique.org/ax]
+ne plus recevoir : [https://www.polytechnique.org/ax/out]
+
+{if !$is_mail}
+</pre>
+{/if}
+{else}
+{if $is_mail}
+<?xml version="1.0" encoding="iso-8859-15"?>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml"> 
+  <head>  
+    <title></title>
+    <style type="text/css">
+    <!--
+      {literal}
+      body      { background-color: #ddd; color: #000; }
+      {/literal}
+      {$am->css()}
+    -->
+    </style>
+  </head>
+  <body>
+{/if}
+    <div class='ax_mail'>
+      <div class="title">{$am->title()}</div>
+      <div class="intro">{$am->head($prenom, $nom, $sexe, 'html')|smarty:nodefaults}</div>
+      <div class="body">{$am->body('html')|smarty:nodefaults}</div>
+      <div class="signature">{$am->signature('html')|smarty:nodefaults}</div>
+      <div class="foot1">
+        Cette lettre est envoyée par l'AX grâce aux outils de Polytechnique.org.
+      </div>
+      <div class="foot2">
+        [<a href="https://www.polytechnique.org/ax">archives</a>&nbsp;|
+        <a href="https://www.polytechnique.org/ax/out">ne plus recevoir</a>]
+      </div>
+    </div>
+{if $is_mail}
+  </body>
+</html>
+{/if}
+{/if}
+
+{* vim:set et sw=2 sts=2 sws=2: *}
diff --git a/templates/axletter/show.tpl b/templates/axletter/show.tpl
new file mode 100644 (file)
index 0000000..ca26d87
--- /dev/null
@@ -0,0 +1,54 @@
+{**************************************************************************}
+{*                                                                        *}
+{*  Copyright (C) 2003-2006 Polytechnique.org                             *}
+{*  http://opensource.polytechnique.org/                                  *}
+{*                                                                        *}
+{*  This program is free software; you can redistribute it and/or modify  *}
+{*  it under the terms of the GNU General Public License as published by  *}
+{*  the Free Software Foundation; either version 2 of the License, or     *}
+{*  (at your option) any later version.                                   *}
+{*                                                                        *}
+{*  This program is distributed in the hope that it will be useful,       *}
+{*  but WITHOUT ANY WARRANTY; without even the implied warranty of        *}
+{*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *}
+{*  GNU General Public License for more details.                          *}
+{*                                                                        *}
+{*  You should have received a copy of the GNU General Public License     *}
+{*  along with this program; if not, write to the Free Software           *}
+{*  Foundation, Inc.,                                                     *}
+{*  59 Temple Place, Suite 330, Boston, MA  02111-1307  USA               *}
+{*                                                                        *}
+{**************************************************************************}
+
+<h1>
+  {if $ax->_date}
+  Lettre de l'AX du {$ax->_date|date_format}
+  {else}
+  Lettre de l'AX en préparation
+  {/if}
+</h1>
+
+<p>
+[<a href='ax'>liste des lettres</a>]
+{if $smarty.get.text}
+[<a href='{$platal->pl_self()}'>version HTML</a>]
+{else}
+[<a href='{$platal->pl_self()}?text=1'>version Texte</a>]
+{/if}
+{if !$ax->_date}
+[<a href='ax/edit'>éditer</a>]
+{/if}
+</p>
+
+<form method="post" action="{$platal->path}">
+  <div class='center'>
+    <input type='submit' value="me l'envoyer" name='send' />
+  </div>
+</form>
+
+<fieldset>
+<legend>{$am->title(true)}</legend>
+  {include file="axletter/letter.tpl"}
+</fieldset>
+
+{* vim:set et sw=2 sts=2 sws=2: *}
diff --git a/upgrade/0.9.13/04_axletter.sql b/upgrade/0.9.13/04_axletter.sql
new file mode 100644 (file)
index 0000000..4c14495
--- /dev/null
@@ -0,0 +1,33 @@
+CREATE TABLE axletter (
+    id int(11) unsigned NOT NULL auto_increment,
+    shortname varchar(16) default NULL default '',
+    subject varchar(255) NOT NULL default '',
+    title varchar(255) NOT NULL default '',
+    body mediumtext NOT NULL default '',
+    signature mediumtext NOT NULL default '',
+    promo_min smallint(4) NOT NULL default 0,
+    promo_max smallint(4) NOT NULL default 0,
+    echeance datetime NOT NULL default 0,
+    date date NOT NULL default 0,
+    bits set('new', 'sent', 'invalid') NOT NULL default 'new',
+
+    PRIMARY KEY(id),
+    UNIQUE KEY(shortname)
+);
+CREATE TABLE axletter_ins (
+    user_id smallint(4) NOT NULL default 0,
+    email varchar(255) default NULL,
+    flag set('femme') default '',
+    prenom varchar(32) default NULL,
+    nom varchar(255) default NULL,
+    last int(11) NOT NULL default 0,
+    hash varchar(32) default NULL,
+
+    PRIMARY KEY(user_id, email),
+    KEY(last)
+);
+CREATE TABLE axletter_rights (
+    user_id smallint(4) NOT NULL default 0,
+    PRIMARY KEY(user_id)
+);
+# vim:set syntax=mysql: