Moving to GitHub.
[platal.git] / modules / carnet.php
index d60d34d..588be5d 100644 (file)
@@ -1,6 +1,6 @@
 <?php
 /***************************************************************************
- *  Copyright (C) 2003-2011 Polytechnique.org                              *
+ *  Copyright (C) 2003-2014 Polytechnique.org                              *
  *  http://opensource.polytechnique.org/                                   *
  *                                                                         *
  *  This program is free software; you can redistribute it and/or modify   *
@@ -34,6 +34,7 @@ class CarnetModule extends PLModule
             'carnet/contacts/ical'         => $this->make_token_hook('ical',         AUTH_COOKIE, 'directory_private'),
             'carnet/contacts/csv'          => $this->make_token_hook('csv',          AUTH_COOKIE, 'directory_private'),
             'carnet/contacts/csv/birthday' => $this->make_token_hook('csv_birthday', AUTH_COOKIE, 'directory_private'),
+            'carnet/batch'                 => $this->make_hook('batch',              AUTH_COOKIE, 'directory_private'),
 
             'carnet/rss'                   => $this->make_token_hook('rss',          AUTH_COOKIE, 'directory_private'),
         );
@@ -152,12 +153,62 @@ class CarnetModule extends PLModule
         Platal::session()->updateNbNotifs();
     }
 
+    private function getGroup(PlPage $page, $group)
+    {
+        $groupid = XDB::fetchOneCell("SELECT  id
+                                        FROM  groups
+                                       WHERE  (nom = {?} OR diminutif = {?}) AND NOT FIND_IN_SET('private', pub)",
+                                     $group, $group);
+        if (is_null($groupid)) {
+            $search = XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $group);
+            $res = XDB::query('SELECT  id
+                                 FROM  groups
+                                WHERE  (nom ' . $search . ' OR diminutif ' . $search . ") AND NOT FIND_IN_SET('private', pub)",
+                              $search, $search);
+            if ($res->numRows() == 1) {
+                $groupid = $res->fetchOneCell();
+            }
+        }
+        return $groupid;
+    }
+
+    private function addGroup(PlPage $page, $group)
+    {
+        $groupid = $this->getGroup($page, $group);
+        if (is_null($groupid)) {
+            return;
+        }
+        XDB::execute('INSERT IGNORE INTO  watch_group (uid, groupid)
+                                  VALUES  ({?}, {?})',
+                     S::i('uid'), $groupid);
+        S::user()->invalidWatchCache();
+        Platal::session()->updateNbNotifs();
+    }
+
+    private function delGroup(PlPage $page, $group)
+    {
+        $groupid = $this->getGroup($page, $group);
+        if (is_null($groupid)) {
+            return;
+        }
+        XDB::execute('DELETE FROM  watch_group
+                            WHERE  uid = {?} AND groupid = {?}',
+                     S::i('uid'), $groupid);
+        S::user()->invalidWatchCache();
+        Platal::session()->updateNbNotifs();
+    }
+
     public function addNonRegistered(PlPage $page, PlUser $user)
     {
         XDB::execute('INSERT IGNORE INTO  watch_nonins (uid, ni_id)
                                   VALUES  ({?}, {?})', S::i('uid'), $user->id());
-        S::user()->invalidWatchCache();
-        Platal::session()->updateNbNotifs();
+        if (XDB::affectedRows() > 0) {
+            S::user()->invalidWatchCache();
+            Platal::session()->updateNbNotifs();
+            $page->trigSuccess('Contact ajouté&nbsp;: ' . $user->fullName(true));
+        } else {
+            $page->trigWarning('Contact déjà dans la liste&nbsp;: ' . $user->fullName(true));
+        }
     }
 
     public function delNonRegistered(PlPage $page, PlUser $user)
@@ -169,6 +220,33 @@ class CarnetModule extends PLModule
         Platal::session()->updateNbNotifs();
     }
 
+    public function addRegistered(PlPage $page, Profile $profile)
+    {
+        XDB::execute('INSERT IGNORE INTO  contacts (uid, contact)
+                                  VALUES  ({?}, {?})',
+                     S::i('uid'), $profile->id());
+        if (XDB::affectedRows() > 0) {
+            S::user()->invalidWatchCache();
+            Platal::session()->updateNbNotifs();
+            $page->trigSuccess('Contact ajouté&nbsp;: ' . $profile->fullName(true));
+        } else {
+            $page->trigWarning('Contact déjà dans la liste&nbsp;: ' . $profile->fullName(true));
+        }
+    }
+
+    public function delRegistered(PlPage $page, Profile $profile)
+    {
+        XDB::execute('DELETE FROM  contacts
+                            WHERE  uid = {?} AND contact = {?}',
+                     S::i('uid'), $profile->id());
+        if (XDB::affectedRows() > 0) {
+            S::user()->invalidWatchCache();
+            Platal::session()->updateNbNotifs();
+            $page->trigSuccess("Contact retiré&nbsp;!");
+        }
+
+    }
+
     public function handler_notifs($page, $action = null, $arg = null)
     {
         $page->changeTpl('carnet/notifs.tpl');
@@ -184,6 +262,14 @@ class CarnetModule extends PLModule
                 $this->delPromo($page, $arg);
                 break;
 
+              case 'add_group':
+                $this->addGroup($page, $arg);
+                break;
+
+              case 'del_group':
+                $this->delGroup($page, $arg);
+                break;
+
               case 'del_nonins':
                 $user = User::get($arg);
                 if ($user) {
@@ -256,6 +342,14 @@ class CarnetModule extends PLModule
         $page->assign('promo_ranges', $ranges);
         $page->assign('nonins', $nonins->getUsers());
 
+        $groups = XDB::fetchColumn('SELECT  g.nom
+                                      FROM  watch_group AS w
+                                INNER JOIN  groups      AS g ON (g.id = w.groupid)
+                                     WHERE  w.uid = {?}
+                                  ORDER BY  g.nom',
+                                   S::i('uid'));
+        $page->assign('groups', $groups);
+        $page->assign('groups_count', count($groups));
         list($flags, $actions) = XDB::fetchOneRow('SELECT  flags, actions
                                                      FROM  watch
                                                     WHERE  uid = {?}', S::i('uid'));
@@ -270,9 +364,6 @@ class CarnetModule extends PLModule
         $page->setTitle('Mes contacts');
         $this->_add_rss_link($page);
 
-        $uid  = S::i('uid');
-        $user = S::user();
-
         // For XSRF protection, checks both the normal xsrf token, and the special RSS token.
         // It allows direct linking to contact adding in the RSS feed.
         if (Env::v('action') && Env::v('token') !== S::user()->token) {
@@ -281,31 +372,19 @@ class CarnetModule extends PLModule
         switch (Env::v('action')) {
             case 'retirer':
                 if (($contact = Profile::get(Env::v('user')))) {
-                    if (XDB::execute("DELETE FROM  contacts
-                                            WHERE  uid = {?} AND contact = {?}",
-                                     $uid, $contact->id())) {
-                        Platal::session()->updateNbNotifs();
-                        $page->trigSuccess("Contact retiré&nbsp;!");
-                    }
+                    $this->delRegistered($page, $contact);
                 }
                 break;
 
             case 'ajouter':
                 if (($contact = Profile::get(Env::v('user')))) {
-                    XDB::execute('INSERT IGNORE INTO  contacts (uid, contact)
-                                              VALUES  ({?}, {?})',
-                                 $uid, $contact->id());
-                    if (XDB::affectedRows() > 0) {
-                        Platal::session()->updateNbNotifs();
-                        $page->trigSuccess('Contact ajouté&nbsp;!');
-                    } else {
-                        $page->trigWarning('Contact déjà dans la liste&nbsp;!');
-                    }
+                    $this->addRegistered($page, $contact);
                 }
                 break;
         }
 
         $search = false;
+        $user = S::user();
 
         require_once 'userset.inc.php';
 
@@ -427,7 +506,86 @@ class CarnetModule extends PLModule
         require_once 'carnet/outlook.inc.php';
         Outlook::output_profiles($pf->getProfiles(), 'fr');
     }
+
+    function handler_batch($page)
+    {
+        $page->changeTpl('carnet/batch.tpl');
+        $errors = false;
+        $incomplete = array();
+
+        if (Post::has('add')) {
+            S::assert_xsrf_token();
+            require_once 'userset.inc.php';
+            require_once 'emails.inc.php';
+            require_once 'marketing.inc.php';
+
+            $list = explode("\n", Post::v('list'));
+            $origin = Post::v('origin');
+
+            foreach ($list as $item) {
+                if ($item = trim($item)) {
+                    $elements = preg_split("/\s/", $item);
+                    $email = array_pop($elements);
+                    if (!isvalid_email($email)) {
+                        $page->trigError('Email invalide&nbsp;: ' . $email);
+                        $incomplete[] = $item;
+                        $errors = true;
+                        continue;
+                    }
+
+                    $user = User::getSilent($email);
+                    if (is_null($user)) {
+                        $details = implode(' ', $elements);
+                        $promo = trim(array_pop($elements));
+                        $cond = new PFC_And();
+                        if (preg_match('/^[MDX]\d{4}$/', $promo)) {
+                            $cond->addChild(new UFC_Promo('=', UserFilter::DISPLAY, $promo));
+                        } else {
+                            $cond->addChild(new UFC_NameTokens($promo));
+                        }
+                        foreach ($elements as $element) {
+                            $cond->addChild(new UFC_NameTokens($element));
+                        }
+                        $uf = new UserFilter($cond);
+                        $count = $uf->getTotalCount();
+                        if ($count == 0) {
+                            $page->trigError('Les informations : « ' . $item . ' » ne correspondent à aucun camarade.');
+                            $incomplete[] = $item;
+                            $errors = true;
+                            continue;
+                        } elseif ($count > 1) {
+                            $page->trigError('Les informations : « ' . $item . ' » sont ambigues et correspondent à plusieurs camarades.');
+                            $incomplete[] = $item;
+                            $errors = true;
+                            continue;
+                        } else {
+                            $user = $uf->getUser();
+                        }
+                    }
+
+                    if ($user->state == 'active') {
+                        $this->addRegistered($page, $user->profile());
+                    } else {
+                        if (!User::isForeignEmailAddress($email)) {
+                            $page->trigError('Email pas encore attribué&nbsp;: ' . $email);
+                            $incomplete[] = $item;
+                            $errors = true;
+                        } else {
+                            $this->addNonRegistered($page, $user);
+                            if (!Marketing::get($user->id(), $email, true)) {
+                                check_email($email, "Une adresse surveillée est proposée au marketing par " . S::user()->login());
+                                $market = new Marketing($user->id(), $email, 'default', null, $origin, S::v('uid'), null);
+                                $market->add();
+                            }
+                        }
+                    }
+                }
+            }
+        }
+        $page->assign('errors', $errors);
+        $page->assign('incomplete', $incomplete);
+    }
 }
 
-// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker fenc=utf-8:
 ?>