Merge commit 'origin/master' into fusionax
authorStéphane Jacob <jacou@melix.net>
Thu, 30 Apr 2009 14:55:23 +0000 (16:55 +0200)
committerStéphane Jacob <jacou@melix.net>
Thu, 30 Apr 2009 14:55:23 +0000 (16:55 +0200)
19 files changed:
bin/cron/cron_ml_moderate.php
bin/cron/cron_validations.php
classes/platalglobals.php.in
htdocs/images/medals/eufor.jpg [new file with mode: 0644]
include/vcard.inc.php
modules/lists.php
modules/lists/mail_templates/accept.txt [new file with mode: 0644]
modules/xnet.php
modules/xnetgrp.php
modules/xnetlists.php
templates/admin/deces_promo.tpl
templates/events/index.tpl
templates/marketing/private.tpl
templates/payment/retour_paypal.tpl
templates/xnetevents/edit.tpl
templates/xnetgrp/annuaire.tpl
templates/xnetgrp/membres-add.tpl
templates/xnetgrp/membres-edit.tpl
upgrade/0.10.1/01_groupex.sql [new file with mode: 0644]

index 044635a..e91d6e0 100755 (executable)
@@ -100,7 +100,7 @@ while ($sent_mails < $globals->lists->max_mail_per_min
     // send feedback to the mailing list owners
     if ($client->handle_request($list, $mid, $action, utf8_decode($reason))) {
         $sent_mails += $count;
-        $texte = "le message suivant :\n\n"
+        $texte = "Le message suivant :\n\n"
                . "    Auteur: {$mail['sender']}\n"
                . "    Sujet : « {$mail['subj']} »\n"
                . "    Date  : ".strftime("le %d %b %Y à %H:%M:%S", (int)$mail['stamp'])."\n\n"
index d08d381..bdf7330 100755 (executable)
@@ -37,17 +37,17 @@ list($nb, $age, $nbold, $nbveryold) = $res->fetchOneRow();
 $age = (time() - intval($age)) / 86400;
 $head = "";
 if ($age > 15) {
-    $head = "[autodestruction du serveur] ";
+    $head = "[Autodestruction du serveur] ";
 } elseif ($age > 7) {
-    $head = "[armageddon imminent] ";
+    $head = "[Armageddon imminent] ";
 } elseif ($age > 5) {
-    $head = "[guerre nucléaire] ";
+    $head = "[Guerre nucléaire] ";
 } elseif ($age > 3) {
     $head = "[ET Téléphone maison] ";
 } elseif ($age > 1) {
-    $head = "[réveil !] ";
+    $head = "[Réveil !] ";
 } elseif (!empty($nbveryold)) {
-    $head = "[urgent] ";
+    $head = "[Urgent] ";
 }
 
 
@@ -60,10 +60,10 @@ $plural = $nb == 1 ? "" : "s";
 $mymail = new PlMailer();
 $mymail->setFrom('validation@' . $globals->mail->domain);
 $mymail->addTo("validation@" . $globals->mail->domain);
-$mymail->setSubject($head . "il y a $nb validation$plural non effectuée$plural");
+$mymail->setSubject($head . "Il y a $nb validation$plural non effectuée$plural");
 
 $message =
-       "il y a $nb validation$plural à effectuer \n"
+       "Il y a $nb validation$plural à effectuer\n"
        .(empty($nbold)?"":"dont $nbold depuis le dernier mail !!!\n")
        .(empty($nbveryold)?"":"et dont *$nbveryold* ".($nbveryold == 1 ? "est" : "sont")." en retard de plus de 6h !!!")
        ."\n"
@@ -74,7 +74,7 @@ $res = XDB::iterRow("SELECT  type, count(*)
                    GROUP BY  type
                    ORDER BY  type");
 while (list($type, $nb) = $res->next()) {
-    $message .= "- $type: $nb\n";
+    $message .= "- $type : $nb\n";
 }
 
 $message = wordwrap($message,78);
index cc95b1b..94803e8 100644 (file)
@@ -60,12 +60,14 @@ class PlatalGlobals extends PlGlobals
             }
 
             if ($gp) {
-                $res = XDB::query('SELECT  a.*, d.nom AS domnom,
-                                           FIND_IN_SET(\'wiki_desc\', a.flags) AS wiki_desc,
-                                           FIND_IN_SET(\'notif_unsub\', a.flags) AS notif_unsub
+                $res = XDB::query("SELECT  a.*, d.nom AS domnom,
+                                           FIND_IN_SET('wiki_desc', a.flags) AS wiki_desc,
+                                           FIND_IN_SET('notif_unsub', a.flags) AS notif_unsub,
+                                           FIND_IN_SET('has_ml', a.flags) AS has_ml
                                      FROM  groupex.asso AS a
                                 LEFT JOIN  groupex.dom  AS d ON d.id = a.dom
-                                    WHERE  diminutif = {?}', $gp);
+                                    WHERE  diminutif = {?}",
+                                  $gp);
                 if (!($aid = $res->fetchOneAssoc())) {
                     $aid = array();
                 }
diff --git a/htdocs/images/medals/eufor.jpg b/htdocs/images/medals/eufor.jpg
new file mode 100644 (file)
index 0000000..5956b25
Binary files /dev/null and b/htdocs/images/medals/eufor.jpg differ
index dfdadaa..59eb6f5 100644 (file)
@@ -113,7 +113,7 @@ class VCard extends PlVCard
         // Pro
         if (!empty($user['adr_pro'])) {
             foreach ($user['adr_pro'] as $pro) {
-                $street = array($adr['adr1']);
+                $street = array($pro['adr1']);
                 if (!empty($pro['adr2'])) {
                     $street[] = $pro['adr2'];
                 }
index 4c5b223..b7e35d6 100644 (file)
@@ -546,6 +546,21 @@ class ListsModule extends PLModule
                 $msg = str_replace("%(listname)s",  $liste, $msg);
                 $page->assign('msg', $msg);
                 return;
+            } elseif (Get::has('mid') && Env::has('mok')) {
+                $page->changeTpl('lists/moderate_mail.tpl');
+                require_once('banana/moderate.inc.php');
+                $params = array('listname' => $liste, 'domain' => $domain,
+                                'artid' => Get::i('mid'), 'part' => Get::v('part'), 'action' => Get::v('action'));
+                $params['client'] = $this->client;
+                run_banana($page, 'ModerationBanana', $params);
+
+                $msg = file_get_contents('/etc/mailman/fr/accept.txt');
+                $msg = str_replace("%(adminaddr)s", "$liste-owner@{$domain}", $msg);
+                $msg = str_replace("%(request)s",   "<< SUJET DU MAIL >>",    $msg);
+                $msg = str_replace("%(reason)s",    "<< TON EXPLICATION >>",  $msg);
+                $msg = str_replace("%(listname)s",  $liste, $msg);
+                $page->assign('msg', $msg);
+                return;
             }
 
             $mail = $this->moderate_mail($domain, $liste, Env::i('mid'));
diff --git a/modules/lists/mail_templates/accept.txt b/modules/lists/mail_templates/accept.txt
new file mode 100644 (file)
index 0000000..f80227b
--- /dev/null
@@ -0,0 +1,13 @@
+Vous avez envoyé un message à la liste de diffusion {{{LIST}}} :
+
+    %(request)s 
+
+Le modérateur a souhaité diffuser votre message vers les abonnés à
+la liste.
+
+    "%(reason)s" 
+
+Toute question ou commentaire doit être adressé aux modérateurs de la
+liste à cette adresse :
+
+    {{{ALIST}}}
index 195d4bb..c76bf3a 100644 (file)
@@ -24,15 +24,15 @@ class XnetModule extends PLModule
     function handlers()
     {
         return array(
-            'index'     => $this->make_hook('index',     AUTH_PUBLIC),
-            'exit'      => $this->make_hook('exit',      AUTH_PUBLIC),
-
-            'admin'     => $this->make_hook('admin',     AUTH_MDP, 'admin'),
-            'groups'    => $this->make_hook('groups',    AUTH_PUBLIC),
-            'groupes.php' => $this->make_hook('groups2', AUTH_PUBLIC),
-            'plan'      => $this->make_hook('plan',      AUTH_PUBLIC),
-            'photo'     => $this->make_hook('photo',     AUTH_MDP),
-            'autologin' => $this->make_hook('autologin', AUTH_MDP),
+            'index'       => $this->make_hook('index',     AUTH_PUBLIC),
+            'exit'        => $this->make_hook('exit',      AUTH_PUBLIC),
+
+            'admin'       => $this->make_hook('admin',     AUTH_MDP, 'admin'),
+            'groups'      => $this->make_hook('groups',    AUTH_PUBLIC),
+            'groupes.php' => $this->make_hook('groups2',   AUTH_PUBLIC),
+            'plan'        => $this->make_hook('plan',      AUTH_PUBLIC),
+            'photo'       => $this->make_hook('photo',     AUTH_MDP),
+            'autologin'   => $this->make_hook('autologin', AUTH_MDP),
         );
     }
 
index e5a737b..eed2975 100644 (file)
@@ -73,41 +73,34 @@ class XnetGrpModule extends PLModule
     function handlers()
     {
         return array(
-            '%grp'                => $this->make_hook('index',     AUTH_PUBLIC),
-            '%grp/asso.php'       => $this->make_hook('index',     AUTH_PUBLIC),
-            '%grp/logo'           => $this->make_hook('logo',      AUTH_PUBLIC),
-            '%grp/site'           => $this->make_hook('site',      AUTH_PUBLIC),
-            '%grp/edit'           => $this->make_hook('edit',      AUTH_MDP, 'groupadmin'),
-            '%grp/mail'           => $this->make_hook('mail',      AUTH_MDP, 'groupadmin'),
-            '%grp/forum'          => $this->make_hook('forum',     AUTH_MDP, 'groupmember'),
-            '%grp/annuaire'       => $this->make_hook('annuaire',  AUTH_MDP, 'groupannu'),
-            '%grp/annuaire/vcard' => $this->make_hook('vcard',     AUTH_MDP, 'groupmember:groupannu'),
-            '%grp/annuaire/csv'   => $this->make_hook('csv',       AUTH_MDP, 'groupmember:groupannu'),
-            '%grp/trombi'         => $this->make_hook('trombi',    AUTH_MDP, 'groupannu'),
-            '%grp/geoloc'         => $this->make_hook('geoloc',    AUTH_MDP, 'groupannu'),
-            '%grp/subscribe'      => $this->make_hook('subscribe', AUTH_MDP),
-            '%grp/subscribe/valid' => $this->make_hook('subscribe_valid', AUTH_MDP, 'groupadmin'),
-            '%grp/unsubscribe'    => $this->make_hook('unsubscribe', AUTH_MDP, 'groupmember'),
-
-            '%grp/change_rights'  => $this->make_hook('change_rights', AUTH_MDP),
-
-            '%grp/admin/annuaire'
-                 => $this->make_hook('admin_annuaire', AUTH_MDP, 'groupadmin'),
-
-            '%grp/member'
-                 => $this->make_hook('admin_member', AUTH_MDP, 'groupadmin'),
-            '%grp/member/new'
-                 => $this->make_hook('admin_member_new', AUTH_MDP, 'groupadmin'),
-            '%grp/member/new/ajax'
-                 => $this->make_hook('admin_member_new_ajax', AUTH_MDP, 'user', NO_AUTH),
-            '%grp/member/del'
-                 => $this->make_hook('admin_member_del', AUTH_MDP, 'groupadmin'),
-
-            '%grp/rss'             => $this->make_hook('rss', AUTH_PUBLIC, 'user', NO_HTTPS),
-            '%grp/announce/new'    => $this->make_hook('edit_announce', AUTH_MDP,  'groupadmin'),
-            '%grp/announce/edit'   => $this->make_hook('edit_announce', AUTH_MDP,  'groupadmin'),
-            '%grp/announce/photo'  => $this->make_hook('photo_announce', AUTH_PUBLIC),
-            '%grp/admin/announces' => $this->make_hook('admin_announce', AUTH_MDP, 'groupadmin'),
+            '%grp'                 => $this->make_hook('index',                 AUTH_PUBLIC),
+            '%grp/asso.php'        => $this->make_hook('index',                 AUTH_PUBLIC),
+            '%grp/logo'            => $this->make_hook('logo',                  AUTH_PUBLIC),
+            '%grp/site'            => $this->make_hook('site',                  AUTH_PUBLIC),
+            '%grp/edit'            => $this->make_hook('edit',                  AUTH_MDP, 'groupadmin'),
+            '%grp/mail'            => $this->make_hook('mail',                  AUTH_MDP, 'groupadmin'),
+            '%grp/forum'           => $this->make_hook('forum',                 AUTH_MDP, 'groupmember'),
+            '%grp/annuaire'        => $this->make_hook('annuaire',              AUTH_MDP, 'groupannu'),
+            '%grp/annuaire/vcard'  => $this->make_hook('vcard',                 AUTH_MDP, 'groupmember:groupannu'),
+            '%grp/annuaire/csv'    => $this->make_hook('csv',                   AUTH_MDP, 'groupmember:groupannu'),
+            '%grp/trombi'          => $this->make_hook('trombi',                AUTH_MDP, 'groupannu'),
+            '%grp/geoloc'          => $this->make_hook('geoloc',                AUTH_MDP, 'groupannu'),
+            '%grp/subscribe'       => $this->make_hook('subscribe',             AUTH_MDP),
+            '%grp/subscribe/valid' => $this->make_hook('subscribe_valid',       AUTH_MDP, 'groupadmin'),
+            '%grp/unsubscribe'     => $this->make_hook('unsubscribe',           AUTH_MDP, 'groupmember'),
+
+            '%grp/change_rights'   => $this->make_hook('change_rights',         AUTH_MDP),
+            '%grp/admin/annuaire'  => $this->make_hook('admin_annuaire',        AUTH_MDP, 'groupadmin'),
+            '%grp/member'          => $this->make_hook('admin_member',          AUTH_MDP, 'groupadmin'),
+            '%grp/member/new'      => $this->make_hook('admin_member_new',      AUTH_MDP, 'groupadmin'),
+            '%grp/member/new/ajax' => $this->make_hook('admin_member_new_ajax', AUTH_MDP, 'user', NO_AUTH),
+            '%grp/member/del'      => $this->make_hook('admin_member_del',      AUTH_MDP, 'groupadmin'),
+
+            '%grp/rss'             => $this->make_hook('rss',                   AUTH_PUBLIC, 'user', NO_HTTPS),
+            '%grp/announce/new'    => $this->make_hook('edit_announce',         AUTH_MDP,  'groupadmin'),
+            '%grp/announce/edit'   => $this->make_hook('edit_announce',         AUTH_MDP,  'groupadmin'),
+            '%grp/announce/photo'  => $this->make_hook('photo_announce',        AUTH_PUBLIC),
+            '%grp/admin/announces' => $this->make_hook('admin_announce',        AUTH_MDP, 'groupadmin'),
         );
     }
 
@@ -604,7 +597,7 @@ class XnetGrpModule extends PLModule
                 $mailer->setSubject('['.$globals->asso('nom').'] Demande d\'inscription annulée');
                 $mailer->setTxtBody(Env::v('motif'));
                 $mailer->send();
-                $page->kill("La demande de {$user->fullName()} a bien été refusée.");
+                $page->killSuccess("La demande de {$user->fullName()} a bien été refusée.");
             } else {
                 $page->assign('show_form', true);
                 $page->assign('reason', $reason);
index 6738601..036452e 100644 (file)
@@ -28,29 +28,29 @@ class XnetListsModule extends ListsModule
     function handlers()
     {
         return array(
-            '%grp/lists'           => $this->make_hook('lists',     AUTH_MDP, 'groupmember'),
-            '%grp/lists/create'    => $this->make_hook('create',    AUTH_MDP, 'groupmember'),
+            '%grp/lists'              => $this->make_hook('lists',    AUTH_MDP, 'groupmember'),
+            '%grp/lists/create'       => $this->make_hook('create',   AUTH_MDP, 'groupmember'),
 
-            '%grp/lists/members'   => $this->make_hook('members',   AUTH_COOKIE),
-            '%grp/lists/csv'       => $this->make_hook('csv',       AUTH_COOKIE),
-            '%grp/lists/annu'      => $this->make_hook('annu',      AUTH_COOKIE),
-            '%grp/lists/archives'  => $this->make_hook('archives',  AUTH_COOKIE),
-            '%grp/lists/archives/rss' => $this->make_hook('rss',    AUTH_PUBLIC),
+            '%grp/lists/members'      => $this->make_hook('members',  AUTH_COOKIE),
+            '%grp/lists/csv'          => $this->make_hook('csv',      AUTH_COOKIE),
+            '%grp/lists/annu'         => $this->make_hook('annu',     AUTH_COOKIE),
+            '%grp/lists/archives'     => $this->make_hook('archives', AUTH_COOKIE),
+            '%grp/lists/archives/rss' => $this->make_hook('rss',      AUTH_PUBLIC),
 
-            '%grp/lists/moderate'  => $this->make_hook('moderate',  AUTH_MDP),
-            '%grp/lists/admin'     => $this->make_hook('admin',     AUTH_MDP),
-            '%grp/lists/options'   => $this->make_hook('options',   AUTH_MDP),
-            '%grp/lists/delete'    => $this->make_hook('delete',    AUTH_MDP),
+            '%grp/lists/moderate'     => $this->make_hook('moderate', AUTH_MDP),
+            '%grp/lists/admin'        => $this->make_hook('admin',    AUTH_MDP),
+            '%grp/lists/options'      => $this->make_hook('options',  AUTH_MDP),
+            '%grp/lists/delete'       => $this->make_hook('delete',   AUTH_MDP),
 
-            '%grp/lists/soptions'  => $this->make_hook('soptions',  AUTH_MDP),
-            '%grp/lists/check'     => $this->make_hook('check',     AUTH_MDP),
-            '%grp/lists/sync'      => $this->make_hook('sync',      AUTH_MDP),
+            '%grp/lists/soptions'     => $this->make_hook('soptions', AUTH_MDP),
+            '%grp/lists/check'        => $this->make_hook('check',    AUTH_MDP),
+            '%grp/lists/sync'         => $this->make_hook('sync',     AUTH_MDP),
 
-            '%grp/alias/admin'     => $this->make_hook('aadmin',    AUTH_MDP, 'groupadmin'),
-            '%grp/alias/create'    => $this->make_hook('acreate',   AUTH_MDP, 'groupadmin'),
+            '%grp/alias/admin'        => $this->make_hook('aadmin',   AUTH_MDP, 'groupadmin'),
+            '%grp/alias/create'       => $this->make_hook('acreate',  AUTH_MDP, 'groupadmin'),
 
             /* hack: lists uses that */
-            'profile' => $this->make_hook('profile', AUTH_PUBLIC),
+            'profile'                 => $this->make_hook('profile',  AUTH_PUBLIC),
         );
     }
 
@@ -104,7 +104,7 @@ class XnetListsModule extends ListsModule
         }
 
         $listes = $this->client->get_lists();
-        $page->assign('listes',$listes);
+        $page->assign('listes', $listes);
 
         $alias  = XDB::iterator(
                 'SELECT  alias,type
@@ -115,6 +115,13 @@ class XnetListsModule extends ListsModule
         $page->assign('alias', $alias);
 
         $page->assign('may_update', may_update());
+
+        if (count($listes) > 0 && !$globals->asso('has_ml')) {
+            XDB::execute("UPDATE  groupex.asso
+                             SET  flags = CONCAT_WS(',', IF(flags = '', NULL, flags), 'has_ml')
+                           WHERE  id = {?}",
+                         $globals->asso('id'));
+        }
     }
 
     function handler_create(&$page)
@@ -181,6 +188,12 @@ class XnetListsModule extends ListsModule
                                     VALUES ({?}, {?})', XDB::insertId(),
                                    $red . $mdir . '@listes.polytechnique.org');
         }
+
+        XDB::execute("UPDATE  groupex.asso
+                         SET  flags = CONCAT_WS(',', IF(flags = '', NULL, flags), 'has_ml')
+                       WHERE  id = {?}",
+                     $globals->asso('id'));
+
         pl_redirect('lists/admin/'.$liste);
     }
 
index 8601bda..1bef29b 100644 (file)
@@ -23,7 +23,7 @@
 
 
 <form action="admin/deaths" method="post">
-  <table class="tinybicol">
+  <table class="bicol">
     <tr>
       <td>
         <input type="submit" value="GO" style="visibility: hidden" />
index 94fd518..fcdf582 100644 (file)
@@ -55,7 +55,7 @@ Bienvenue {$smarty.session.yourself_name}{if $birthday}
 
 {if $smarty.session.mx_failures|@count}
 <div class="warnings">
-  {icon name=error} Des problèmes sont actuellement recontrés sur tes redirections suivantes :
+  {icon name=error} Des problèmes sont actuellement recontrés sur tes redirections suivantes&nbsp;:
   <ul>
     {foreach from=$smarty.session.mx_failures item=mail}
     <li>
index 1c9f5dd..477b6af 100644 (file)
@@ -39,13 +39,13 @@ Cet utilisateur a une inscription en cours depuis le {$pending|date_format}.
 </p>
 <p>
 {if $relance eq '0000-00-00'}
-il n'a jamais été relancé.
+Il n'a jamais été relancé.
 {else}
-sa dernière relance date du {$relance|date_format}
+Sa dernière relance date du {$relance|date_format}.
 {/if}
 </p>
 
-<p>[<a href='{$path}/insrel?token={xsrf_token}'>le relancer</a>]</p>
+<p>[<a href='{$path}/insrel?token={xsrf_token}'>Le relancer</a>]</p>
 
 {/if}
 
index 6f593b6..b424d98 100644 (file)
@@ -32,5 +32,5 @@ réception de ton paiement.</p>
 
 <p>{$texte|nl2br}</p>
 {/if}
-<p>[<a href='payment'>retour aux Télépaiements</a>]</p>
+<p>[<a href="https://www.polytechnique.org/payment">retour aux Télépaiements</a>]</p>
 {* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
index 31ab564..f282b58 100644 (file)
@@ -184,7 +184,8 @@ Ton inscription à [METS LE NOM DE L'EVENEMENT ICI] a bien été enregistrée et
 
 -- 
 {$smarty.session.prenom} {$smarty.session.nom}{/if}</textarea><br />
-        Page internet de l'événement&nbsp;: <input size="40" name="site" value="{$paiement_site|default:$asso.site|default:$globals->baseurl|cat:'/'|cat:$platal->ns}" /><br />
+        {assign var='asso_url' value=$globals->baseurl|cat:'/'|cat:$platal->ns}
+        Page internet de l'événement&nbsp;: <input size="40" name="site" value="{$paiement_site|default:$asso.site|default:$asso_url}" /><br />
         Le nouveau paiement sera activé automatiquement après validation par le trésorier de Polytechnique.org,
         ce qui sera fait sous peu.
         <script type="text/javascript">//<![CDATA[
index 4d73f52..0e46aaa 100644 (file)
@@ -34,6 +34,7 @@ Le groupe {$asso.nom} compte {$nb_tot} membres&nbsp;:
       Ajouter un membre
     </a>
   </li>
+  {if $asso.has_ml}
   <li>
     <a href="{$platal->ns}admin/annuaire">
       {icon name=wand title="Synchroniser"} 
@@ -41,6 +42,7 @@ Le groupe {$asso.nom} compte {$nb_tot} membres&nbsp;:
     </a>
   </li>
   {/if}
+  {/if}
   <li>
     <a href="{$platal->ns}annuaire/csv/{$asso.diminutif}.csv">
       {icon name=page_excel title="Fichier Excel"} 
index cff436b..b01018d 100644 (file)
@@ -103,4 +103,10 @@ function searchX()
   </table>
 </form>
 
+{literal}
+<script type="text/javascript">
+  $("#email").focus();
+</script>
+{/literal}
+
 {* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
index b601010..e1769dd 100644 (file)
@@ -49,7 +49,7 @@
 <h2>
   Édition du profil de {if "`$user.prenom` `$user.nom`"|trim}{$user.prenom} {$user.nom}{else}{$user.email}{/if}
   {if $user.origine eq 'X'}
-  (X{$user.promo})
+  &nbsp;(X{$user.promo})
   <a href="https://www.polytechnique.org/profile/{$user.alias}">{icon name=user_suit title="fiche"}</a>
   {/if}
   <a href="{$platal->ns}member/del/{$user.email}">{icon name=delete title="Suppression du compte"}</a>
diff --git a/upgrade/0.10.1/01_groupex.sql b/upgrade/0.10.1/01_groupex.sql
new file mode 100644 (file)
index 0000000..e52291e
--- /dev/null
@@ -0,0 +1,3 @@
+ALTER TABLE groupex.asso CHANGE COLUMN flags flags SET('wiki_desc', 'notif_unsub', 'has_ml') NOT NULL;
+
+-- vim:set syntax=mysql: