Enables group filling from its MLs and aliases (Closes #1473).
authorStéphane Jacob <sj@m4x.org>
Thu, 28 Apr 2011 12:42:06 +0000 (14:42 +0200)
committerStéphane Jacob <sj@m4x.org>
Thu, 28 Apr 2011 12:42:06 +0000 (14:42 +0200)
Signed-off-by: Stéphane Jacob <sj@m4x.org>
ChangeLog
classes/user.php
modules/xnetgrp.php
templates/xnetgrp/annuaire.tpl
templates/xnetgrp/sync.tpl [new file with mode: 0644]

index adce71d..cb997d1 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -23,6 +23,9 @@ Bug/Wish:
         - #1469: Adds search on firstname/lastname/nickname                -JAC
         - #1470: Fixes autocomplete on countries                           -JAC
 
+    * XnetGrp:
+        - #1473: Enables group filling from its MLs and aliases            -JAC
+
     * XnetList:
         - #957: Allows xnet list sorting by description and members count  -JAC
 
index 801fe39..ab554bc 100644 (file)
@@ -300,6 +300,11 @@ class User extends PlUser
         return $this->profile()->directory_name;
     }
 
+    static public function compareDirectoryName($a, $b)
+    {
+        return strcasecmp(replace_accent($a->directoryName()), replace_accent($b->directoryName()));
+    }
+
     /** Return the main profile attached with this account if any.
      */
     public function profile($forceFetch = false, $fields = 0x0000, $visibility = null)
index 6b06bcd..b7d8f20 100644 (file)
@@ -35,6 +35,7 @@ class XnetGrpModule extends PLModule
             '%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/directory/sync'  => $this->make_hook('directory_sync',        AUTH_MDP, 'groupadmin'),
             '%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),
@@ -401,6 +402,113 @@ class XnetGrpModule extends PLModule
         $page->assign('users', $users);
     }
 
+    function handler_directory_sync($page)
+    {
+        global $globals;
+        require_once 'emails.inc.php';
+
+        $page->changeTpl('xnetgrp/sync.tpl');
+        Platal::load('lists', 'lists.inc.php');
+
+        if (Env::has('add_users')) {
+            S::assert_xsrf_token();
+
+            $users = array_keys(Env::v('add_users'));
+            $data = array();
+            foreach ($users as $uid) {
+                $data[] = XDB::format('({?}, {?})', $globals->asso('id'), $uid);
+            }
+            XDB::rawExecute('INSERT INTO  group_members (asso_id, uid)
+                                  VALUES  ' . implode(',', $data));
+        }
+
+        if (Env::has('add_nonusers')) {
+            S::assert_xsrf_token();
+
+            $nonusers = array_keys(Env::v('add_nonusers'));
+            foreach ($nonusers as $email) {
+                if ($user = User::getSilent($email) || !isvalid_email($email)) {
+                    continue;
+                }
+
+                list($local_part, $domain) = explode('@', strtolower($email));
+                $hruid = User::makeHrid($local_part, $domain, 'ext');
+                if ($user = User::getSilent($hruid)) {
+                    continue;
+                }
+
+                $parts = explode('.', $local_part);
+                if (count($parts) == 1) {
+                    $lastname = $display_name = $full_name = $directory_name = ucfirst($local_part);
+                    $firstname = '';
+                } else {
+                    $firstname = ucfirst($parts[0]);
+                    $lastname = ucwords(implode(' ', array_slice($parts, 1)));
+                    $display_name = $firstname;
+                    $full_name = $firstname . ' ' . $lastname;
+                    $directory_name = strtoupper($lastname) . ' ' . $firstname;
+                }
+                XDB::execute('INSERT INTO  accounts (hruid, display_name, full_name, directory_name, firstname, lastname, email, type, state)
+                                   VALUES  ({?}, {?}, {?}, {?}, {?}, {?}, {?}, \'xnet\', \'disabled\')',
+                             $hruid, $display_name, $full_name, $directory_name, $firstname, $lastname, $email);
+                $uid = XDB::insertId();
+                XDB::execute('INSERT INTO  group_members (asso_id, uid)
+                                   VALUES  ({?}, {?})',
+                             $globals->asso('id'), $uid);
+            }
+        }
+
+        if (Env::has('add_users') || Env::has('add_nonusers')) {
+            $page->trigSuccess('Ajouts réalisés avec succès.');
+        }
+
+        $user = S::user();
+        $client = new MMList($user, $globals->asso('mail_domain'));
+        $lists = $client->get_lists();
+        $members = array();
+        foreach ($lists as $list) {
+            $details = $client->get_members($list['list']);
+            $members = array_merge($members, list_extract_members($details[1]));
+        }
+        $members = array_unique($members);
+        $uids = array();
+        $users = array();
+        $nonusers = array();
+        foreach ($members as $email) {
+            if ($user = User::getSilent($email)) {
+                $uids[] = $user->id();
+            } else {
+                $nonusers[] = $email;
+            }
+        }
+
+        $aliases = iterate_list_alias($globals->asso('mail_domain'));
+        foreach ($aliases as $alias) {
+            list($local_part, $domain) = explode('@', $alias);
+            $aliases_members = list_alias_members($local_part, $domain);
+            $users = array_merge($users, $aliases_members['users']);
+            $nonusers = array_merge($nonusers, $aliases_members['nonusers']);
+        }
+        foreach ($users as $user) {
+            $uids[] = $user->id();
+        }
+        $nonusers = array_unique($nonusers);
+        $uids = array_unique($uids);
+        $uids = XDB::fetchColumn('SELECT  a.uid
+                                    FROM  accounts AS a
+                                   WHERE  a.uid IN {?} AND NOT EXISTS (SELECT  *
+                                                                         FROM  group_members AS g
+                                                                        WHERE  a.uid = g.uid AND g.asso_id = {?})',
+                                 $uids, $globals->asso('id'));
+
+        $users = User::getBulkUsersWithUIDs($uids);
+        usort($users, 'User::compareDirectoryName');
+        sort($nonusers);
+
+        $page->assign('users', $users);
+        $page->assign('nonusers', $nonusers);
+    }
+
     private function removeSubscriptionRequest($uid)
     {
         global $globals;
index 54bcd53..d18bffd 100644 (file)
@@ -34,6 +34,12 @@ Le groupe {$asso->nom} compte {$nb_tot} membres&nbsp;:
       Ajouter un membre
     </a>
   </li>
+  <li>
+    <a href="{$platal->ns}directory/sync">
+      {icon name=arrow_refresh title="Synchroniser avec les listes"}
+      Synchroniser avec les listes
+    </a>
+  </li>
   {if $asso->has_ml}
   <li>
     <a href="{$platal->ns}admin/annuaire">
diff --git a/templates/xnetgrp/sync.tpl b/templates/xnetgrp/sync.tpl
new file mode 100644 (file)
index 0000000..be2c689
--- /dev/null
@@ -0,0 +1,102 @@
+{**************************************************************************}
+{*                                                                        *}
+{*  Copyright (C) 2003-2011 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 !($users|@count || $nonusers|@count)}
+<p>Tous les inscrits aux listes de diffusions et alias du groupe sont déjà inscrits au groupe.</p>
+{else}
+<form action="{$platal->ns}directory/sync" method="post">
+  {xsrf_token_field}
+  <table cellspacing="2" cellpadding="0" class="tiny">
+    {if $users|@count}
+    <tr>
+      <th>Nom</th>
+      <th>
+        <a href="javascript:toggleAll('users')">{icon name="arrow_refresh" title="Tout (dé)cocher"}</a>
+      </th>
+    </tr>
+    {foreach from=$users item=user}
+    <tr>
+      <td class="checkboxToggle">{profile user=$user promo=true}</td>
+      <td class="checkboxToggle"><input type="checkbox" class="users moderate_email" name="add_users[{$user->id()}]" /></td>
+    </tr>
+    {/foreach}
+    {/if}
+    {if $nonusers|@count}
+    <tr>
+      <th>Email</th>
+      <th>
+        <a href="javascript:toggleAll('nonusers')">{icon name="arrow_refresh" title="Tout (dé)cocher"}</a>
+      </th>
+    </tr>
+    {foreach from=$nonusers item=nonuser}
+    <tr>
+      <td class="checkboxToggle">{$nonuser}</td>
+      <td class="checkboxToggle"><input type="checkbox" class="nonusers moderate_email" name="add_nonusers[{$nonuser}]" /></td>
+    </tr>
+    {/foreach}
+    {/if}
+    <tr>
+      <td colspan="2" class="center">
+        <input type="submit" value="Inscrire au groupe" />
+      </td>
+    </tr>
+  </table>
+
+  <script type="text/javascript">//<![CDATA[
+  {literal}
+  var toggleStateUsers = false;
+  var toggleStateNonUsers = false;
+  function toggleAll(type) {
+    if (type == 'users') {
+      toggleStateUsers = !toggleStateUsers;
+      var toggleState = toggleStateUsers;
+    } else if (type == 'nonusers') {
+      toggleStateNonUsers = !toggleStateNonUsers;
+      var toggleState = toggleStateNonUsers;
+    } else {
+      return;
+    }
+    var boxes = $(':checkbox.moderate_email.' + type);
+    if (toggleState) {
+      boxes.attr('checked', 'checked');
+    } else {
+      boxes.removeAttr('checked');
+    }
+  }
+
+  $('.checkboxToggle').click(function (event) {
+    // Don't uncheck the checkbox when clicking it
+    if (event.target.tagName === 'INPUT') {
+      return;
+    }
+
+    var checkbox = $(this).parent().find(':checkbox');
+    checkbox = checkbox.attr('checked', !checkbox.attr('checked'));
+    event.stopPropagation();
+  });
+  {/literal}
+  //]]></script>
+
+</form>
+{/if}
+
+{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}