Merge branch 'xorg/master' into xorg/f/geocoding
authorStéphane Jacob <sj@m4x.org>
Fri, 13 May 2011 12:31:20 +0000 (14:31 +0200)
committerStéphane Jacob <sj@m4x.org>
Fri, 13 May 2011 12:31:20 +0000 (14:31 +0200)
53 files changed:
ChangeLog
classes/profile.php
classes/user.php
classes/userfilter.php
classes/userfilter/conditions.inc.php
classes/xnetpage.php
classes/xorg.php
configs/mails.conf
configs/platal.ini
core
htdocs/css/nl.default.css [new file with mode: 0644]
include/emails.combobox.inc.php
include/newsletter.inc.php
include/ufbuilder.inc.php
include/userset.inc.php
modules/axletter.php
modules/deltaten.php [new file with mode: 0644]
modules/epletter.php
modules/googleapps.php
modules/lists.php
modules/newsletter.php
modules/payment/money/bplccyberplus.inc.php
modules/profile.php
modules/profile/deltaten.inc.php [new file with mode: 0644]
modules/profile/page.inc.php
modules/register.php
modules/xnetgrp.php
modules/xnetnl.php
plugins/modifier.get_profile.php [new file with mode: 0644]
plugins/modifier.get_user.php [new file with mode: 0644]
templates/deltaten/index.tpl [new file with mode: 0644]
templates/include/minifiche.tpl
templates/include/plview.groupmember.entry.tpl [new file with mode: 0644]
templates/include/plview.groupmember.tpl [new file with mode: 0644]
templates/include/plview.listmember.tpl [new file with mode: 0644]
templates/include/plview.minifiche.tpl
templates/include/plview.trombi.tpl
templates/lists/annu.tpl
templates/newsletter/admin.tpl
templates/newsletter/edit.tpl
templates/newsletter/enable.mail.tpl [new file with mode: 0644]
templates/newsletter/enable.tpl [new file with mode: 0644]
templates/newsletter/index.tpl
templates/newsletter/nl.default.mail.tpl [new file with mode: 0644]
templates/profile/deltaten.tpl [new file with mode: 0644]
templates/profile/profile.tpl
templates/skin/common.menu.tpl
templates/xnetgrp/annuaire.tpl
templates/xnetgrp/non_active.tpl
upgrade/1.1.1/15_deltaten.sql [new file with mode: 0644]
upgrade/1.1.1/group_logos.php [new file with mode: 0755]
upgrade/1.1.1/update.sh
upgrade/1.1.2/connect.db.inc.php [new symlink]

index 6153d19..8cadc0e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 ================================================================================
-VERSION 1.1.1                                                         XX XX XXXX
+VERSION 1.1.2                                                         XX XX XXXX
+
+================================================================================
+VERSION 1.1.1                                                         09 05 2011
 
 New:
 
@@ -12,6 +15,9 @@ Bug/Wish:
         - #1474: Provides accounts data for accounts without profile       -JAC
         - #1476: Logs last use of Auth-Groupe-X keys                       -JAC
 
+    * Carnet:
+        - #1486: Allows deletion of deceased contact/watched user          -JAC
+
     * Core:
         - #1484: Fix reference to is_IE that does not exist anymore        -FRU
 
@@ -27,6 +33,9 @@ Bug/Wish:
     * Newsletter:
         - #1394: Links nl unsubscribtions to the issues that caused them   -JAC
 
+    * Paiement:
+        - #1485: Properly formats name and comment field in paiements      -JAC
+
     * Profile:
         - #1445: Add job entry year                                        -JAC
         - #1478: Uses user's visibility limitations to display vcards      -JAC
@@ -38,6 +47,9 @@ Bug/Wish:
         - #1470: Fixes autocomplete on countries                           -JAC
 
     * XnetGrp:
+        - Enables NLs filling from group members                           -JAC
+        - #1179: Adds alphabetic choices for group directories             -XEL
+        - #1460: Enables NLs creation for groups                           -XEL
         - #1473: Enables group filling from its MLs and aliases            -JAC
 
     * XnetList:
index cf6bcd0..9c7cc3e 100644 (file)
@@ -109,10 +109,11 @@ class Profile implements PlExportable
     const FETCH_PHONES         = 0x000100;
     const FETCH_JOB_TERMS      = 0x000200;
     const FETCH_MENTOR_TERMS   = 0x000400;
+    const FETCH_DELTATEN       = 0x000800;
 
     const FETCH_MINIFICHES   = 0x00012D; // FETCH_ADDRESSES | FETCH_EDU | FETCH_JOBS | FETCH_NETWORKING | FETCH_PHONES
 
-    const FETCH_ALL          = 0x0007FF; // OR of FETCH_*
+    const FETCH_ALL          = 0x000FFF; // OR of FETCH_*
 
     static public $descriptions = array(
         'search_names'    => 'Noms',
@@ -144,7 +145,8 @@ class Profile implements PlExportable
         'langues'         => 'Langues',
         'expertise'       => 'Expertises (mentoring)',
         'terms'           => 'Compétences (mentoring)',
-        'countries'       => 'Pays (mentoring)'
+        'countries'       => 'Pays (mentoring)',
+        'deltaten'        => 'Opération N N-10',
     );
 
     private $fetched_fields  = 0x000000;
@@ -440,8 +442,8 @@ class Profile implements PlExportable
 
     /**
      * Clears a profile.
-     *  *always deletes in: profile_addresses, profile_binets, profile_job,
-     *      profile_langskills, profile_mentor, profile_networking,
+     *  *always deletes in: profile_addresses, profile_binets, profile_deltaten,
+     *      profile_job, profile_langskills, profile_mentor, profile_networking,
      *      profile_phones, profile_skills, watch_profile
      *  *always keeps in: profile_corps, profile_display, profile_education,
      *      profile_medals, profile_name, profile_photos, search_name
@@ -452,7 +454,8 @@ class Profile implements PlExportable
         $tables = array(
             'profile_job', 'profile_langskills', 'profile_mentor',
             'profile_networking', 'profile_skills', 'watch_profile',
-            'profile_phones', 'profile_addresses', 'profile_binets');
+            'profile_phones', 'profile_addresses', 'profile_binets',
+            'profile_deltaten');
 
         foreach ($tables as $t) {
             XDB::execute('DELETE FROM  ' . $t . '
@@ -823,6 +826,44 @@ class Profile implements PlExportable
         }
     }
 
+    /** DeltaTen
+     */
+
+    /** Find out whether this profile may take part to the "DeltaTen" operation.
+     * @param $role Which role to select ('young' or 'old')
+     * @return Boolean: whether it is enabled.
+     */
+    const DELTATEN_YOUNG = 'young';
+    const DELTATEN_OLD = 'old';
+    public function isDeltaTenEnabled($role)
+    {
+        global $globals;
+        switch ($role) {
+        case self::DELTATEN_YOUNG:
+            return ($this->mainGrade() == UserFilter::GRADE_ING && $this->yearpromo() >= $globals->deltaten->first_promo_young);
+        case self::DELTATEN_OLD:
+            // Roughly compute the current promo in second year on the campus:
+            // Promo 2010 is in second year between 09/2011 and 08/2012 => use 2012.
+            // DeltaTen program begins around January of the second year.
+            $promo_on_platal = ((int) date('Y')) - 2;
+            return ($this->mainGrade() == UserFilter::GRADE_ING && $this->yearpromo() >= $globals->deltaten->first_promo_young - 10 && $this->yearpromo() <= $promo_on_platal - 10);
+        default:
+            Platal::assert(false, "Invalid DeltaTen role $role");
+        }
+    }
+
+    /** Retrieve the "Deltaten" message of the user.
+     * Returns "null" if the message is empty or the user is not taking part to the
+     * DeltaTen operation.
+     */
+    public function getDeltatenMessage()
+    {
+        if ($this->isDeltaTenEnabled(self::DELTATEN_OLD)) {
+            return $this->deltaten_message;
+        } else {
+            return null;
+        }
+    }
 
     /* Binets
      */
@@ -926,16 +967,17 @@ class Profile implements PlExportable
                                      pe.entry_year, pe.grad_year, pe.promo_year, pe.program, pe.fieldid,
                                      IF ({?}, pse.text, NULL) AS section,
                                      pn_f.name AS firstname, pn_l.name AS lastname,
-                                     IF{?}, pn_n.name, NULL) AS nickname,
-                                     IF(pn_uf.name IS NULL, pn_f.name, pn_uf.name) AS firstname_ordinary,
-                                     IF(pn_ul.name IS NULL, pn_l.name, pn_ul.name) AS lastname_ordinary,
+                                     IF ({?}, pn_n.name, NULL) AS nickname,
+                                     IF (pn_uf.name IS NULL, pn_f.name, pn_uf.name) AS firstname_ordinary,
+                                     IF (pn_ul.name IS NULL, pn_l.name, pn_ul.name) AS lastname_ordinary,
                                      pd.yourself, pd.promo, pd.short_name, pd.public_name AS full_name,
                                      pd.directory_name, pd.public_name, pd.private_name,
-                                     IF(pp.pub IN {?}, pp.display_tel, NULL) AS mobile,
+                                     IF (pp.pub IN {?}, pp.display_tel, NULL) AS mobile,
                                      (ph.pub IN {?} AND ph.attach IS NOT NULL) AS has_photo,
                                      ph.x AS photo_width, ph.y AS photo_height,
                                      p.last_change < DATE_SUB(NOW(), INTERVAL 365 DAY) AS is_old,
                                      pm.expertise AS mentor_expertise,
+                                     IF ({?}, pdt.message, NULL) AS deltaten_message,
                                      ap.uid AS owner_id
                                FROM  profiles AS p
                          INNER JOIN  profile_display AS pd ON (pd.pid = p.pid)
@@ -954,6 +996,7 @@ class Profile implements PlExportable
                           LEFT JOIN  profile_phones AS pp ON (pp.pid = p.pid AND pp.link_type = \'user\' AND tel_type = \'mobile\')
                           LEFT JOIN  profile_photos AS ph ON (ph.pid = p.pid)
                           LEFT JOIN  profile_mentor AS pm ON (pm.pid = p.pid)
+                          LEFT JOIN  profile_deltaten AS pdt ON (pdt.pid = p.pid)
                           LEFT JOIN  account_profiles AS ap ON (ap.pid = p.pid AND FIND_IN_SET(\'owner\', ap.perms))
                               WHERE  p.pid IN {?}
                            GROUP BY  p.pid
@@ -964,6 +1007,7 @@ class Profile implements PlExportable
                            $visibility->isVisible(ProfileVisibility::VIS_PRIVATE), // nickname
                            $visibility->levels(), // mobile
                            $visibility->levels(), // photo
+                           $visibility->isVisible(ProfileVisibility::VIS_PRIVATE), // deltaten_message
                            $pids
                        );
         return new ProfileIterator($it, $pids, $fields, $visibility);
index ab554bc..7ede56b 100644 (file)
@@ -292,6 +292,14 @@ class User extends PlUser
         return $this->profile()->fullName($with_promo);
     }
 
+    public function shortName($with_promo = false)
+    {
+        if (!$this->hasProfile()) {
+            return $this->full_name;
+        }
+        return $this->profile()->shortName($with_promo);
+    }
+
     public function directoryName()
     {
         if (!$this->hasProfile()) {
@@ -769,7 +777,7 @@ class User extends PlUser
                              $this->forlifeEmail(), $newuser->id());
 
                 // Reftech new user so its forlifeEmail will be correct.
-                $newuser = getSilentWithUID($newuser->id());
+                $newuser = self::getSilentWithUID($newuser->id());
             }
 
             // Change email used in mailing lists.
index b4bf316..963f208 100644 (file)
@@ -971,11 +971,11 @@ class UserFilter extends PlFilter
         foreach ($this->sa as $sub => $emails) {
             if (is_null($emails)) {
                 $joins['sa' . $sub] = PlSqlJoin::left('email_source_account', '$ME.uid = $UID');
-            } else if ($key == self::ALIAS_BEST) {
+            } else if ($sub == self::ALIAS_BEST) {
                 $joins['sa' . $sub] = PlSqlJoin::left('email_source_account', '$ME.uid = $UID AND FIND_IN_SET(\'bestalias\', $ME.flags)');
-            } else if ($key == self::ALIAS_FORLIFE) {
+            } else if ($sub == self::ALIAS_FORLIFE) {
                 $joins['sa' . $sub] = PlSqlJoin::left('email_source_account', '$ME.uid = $UID AND $ME.type = \'forlife\'');
-            } else if ($key == self::ALIAS_AUXILIARY) {
+            } else if ($sub == self::ALIAS_AUXILIARY) {
                 $joins['sa' . $sub] = PlSqlJoin::left('email_source_account', '$ME.uid = $UID AND $ME.type = \'alias_aux\'');
             } else {
                 if (!is_array($emails)) {
@@ -1185,6 +1185,37 @@ class UserFilter extends PlFilter
         return $joins;
     }
 
+    /** DELTATEN
+     */
+    private $dts = array();
+    const DELTATEN = 1;
+    const DELTATEN_MESSAGE = 2;
+    // TODO: terms
+
+    public function addDeltaTenFilter($type)
+    {
+        $this->requireProfiles();
+        switch ($type) {
+        case self::DELTATEN:
+            $this->dts['pdt'] = 'profile_deltaten';
+            return 'pdt';
+        case self::DELTATEN_MESSAGE:
+            $this->dts['pdtm'] = 'profile_deltaten';
+            return 'pdtm';
+        default:
+            Platal::page()->killError("Undefined DeltaTen filter.");
+        }
+    }
+
+    protected function deltatenJoins()
+    {
+        $joins = array();
+        foreach ($this->dts as $sub => $tab) {
+            $joins[$sub] = PlSqlJoin::left($tab, '$ME.pid = $PID');
+        }
+        return $joins;
+    }
+
     /** MENTORING
      */
 
@@ -1197,7 +1228,7 @@ class UserFilter extends PlFilter
 
     public function addMentorFilter($type)
     {
-        $this->requireAccounts();
+        $this->requireProfiles();
         switch($type) {
         case self::MENTOR:
             $this->pms['pm'] = 'profile_mentor';
index 6c9a1be..c798f9d 100644 (file)
@@ -993,7 +993,7 @@ class UFC_Email extends UserFilterCondition
 
         if (count($foreign) > 0) {
             $sub = $uf->addEmailRedirectFilter($foreign);
-            $cond[] = XDB::format('ra' . $sub . '.redirect IS NOT NULL OR ra' . $sub . '.redirect IN {?}', $foreign);
+            $cond[] = XDB::format('ra' . $sub . '.redirect IS NOT NULL OR ra' . $sub . '.redirect IN {?} OR a.email IN {?}', $foreign, $foreign);
         }
         if (count($local) > 0) {
             $sub = $uf->addAliasFilter($local);
@@ -1513,6 +1513,36 @@ abstract class UFC_UserRelated extends UserFilterCondition
     }
 }
 // }}}
+// {{{ class UFC_DeltaTen
+class UFC_DeltaTen extends UserFilterCondition
+{
+    public function buildCondition(PlFilter $uf)
+    {
+        $sub = $uf->addDeltaTenFilter(UserFilter::DELTATEN);
+        return $sub . '.message IS NOT NULL';
+    }
+}
+// }}}
+// {{{ class UFC_DeltaTen_Message
+/** Filters users by deltaten message
+ * @param $message Message for the DeltaTen program
+ */
+class UFC_DeltaTen_Message extends UserFilterCondition
+{
+    private $message;
+
+    public function __construct($message)
+    {
+        $this->message = $message;
+    }
+
+    public function buildCondition(PlFilter $uf)
+    {
+        $sub = $uf->addDeltaTenFilter(UserFilter::DELTATEN_MESSAGE);
+        return $sub . '.message ' . XDB::formatWildcards(XDB::WILDCARD_CONTAINS, $this->message);
+    }
+}
+// }}}
 // {{{ class UFC_Contact
 /** Filters users who belong to selected user's contacts
  */
index 0f1a1cd..d32374d 100644 (file)
@@ -128,6 +128,9 @@ class XnetPage extends PlPage
                 $sub['créer une liste']     = "$dim/lists/create";
                 $sub['créer un alias']      = "$dim/alias/create";
             }
+            if (!$globals->asso('has_nl')) {
+                $sub['créer la newsletter'] = "$dim/admin/nl/enable";
+            }
             if (S::admin()) {
                 $sub['gérer les groupes'] = array('href' => 'admin', 'style' => 'color: gray;');
                 $sub['clear cache'] = array('href' => 'purge_cache?token=' . S::v('xsrf_token'), 'style' => 'color: gray;');
index bdd1e85..3930d7e 100644 (file)
@@ -28,7 +28,7 @@ class Xorg extends Platal
                             'profile', 'register', 'search', 'stats', 'admin',
                             'newsletter', 'axletter', 'epletter', 'bandeau', 'survey',
                             'fusionax', 'gadgets', 'googleapps', 'poison',
-                            'openid', 'reminder', 'api', 'urlshortener');
+                            'openid', 'reminder', 'api', 'urlshortener', 'deltaten');
     }
 
     public function find_hook()
index 06fc744..4ecaa81 100644 (file)
@@ -82,6 +82,10 @@ from="Polytechnique.org" <contact@polytechnique.org>
 from="Gestion des NLs" <support@polytechnique.org>
 to=br@staff.polytechnique.org
 
+[newsletter_group_enable]
+from="Gestion des NLs" <support@polytechnique.org>
+to=br@staff.polytechnique.org
+
 [xnet_registration]
 from=register@polytechnique.org
 subject="Inscription à Polytechnique.net"
index f4e7e78..6a5ce41 100644 (file)
@@ -208,6 +208,15 @@ event_forum = ""
 event_reply = ""
 
 
+; The deltaten section contains parameters used to handle the "N N-10"
+; operation.
+[Deltaten]
+
+; $globals->deltaten->first_promo_young
+; First promo to take part to the "N N-10" operation as the "young" promo
+first_promo_young = 2007
+
+
 ; The geocoder section contains parameters used to perform the geocoding 
 ; and the formatting of user addresses.
 [Geocoder]
diff --git a/core b/core
index f759f38..3051158 160000 (submodule)
--- a/core
+++ b/core
@@ -1 +1 @@
-Subproject commit f759f3804cfa1cba90b17baf9b6bd1f9617e0315
+Subproject commit 3051158652dd8f7be6a9d726509b2c64b7030f94
diff --git a/htdocs/css/nl.default.css b/htdocs/css/nl.default.css
new file mode 100644 (file)
index 0000000..d2ed4fa
--- /dev/null
@@ -0,0 +1,150 @@
+/***************************************************************************
+ *  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                *
+ ***************************************************************************/
+
+div.nl_background {
+    margin : 0;
+    padding : 1em 0;
+    background-color: #ddd;
+    color: #000;
+}
+
+div.nl {
+    margin : auto;
+    width : 72ex;
+    font-family : "Verdana", "Arial", "Helvetica", sans-serif;
+    font-size : 10pt;
+    text-align : justify;
+    background-color : #fff;
+    color : #000;
+}
+
+div.nl a[href] {
+    text-decoration : none;
+    background-color : #fff;
+    color : #36c;
+}
+
+div.nl a[href]:hover {
+    background-color : #fff;
+    color : #6c0;
+}
+
+div.nl div.title {
+    margin : 0 0 3ex;
+    padding : 4.5ex 1ex 3ex 15ex;
+    font-size : 130%;
+    font-weight : bold;
+    text-align : right;
+    background-color : #369;
+    color : #fff;
+    background-repeat : no-repeat;
+    background-position : 0.5ex 0ex;
+}
+
+div.nl div.title a {
+    color : #fff;
+    background-color : transparent;
+    text-decoration : none;
+    background-image: none;
+}
+
+div.nl div.title a:hover {
+    color : #fff;
+    background-color : transparent;
+    text-decoration : none;
+    background-image: none;
+}
+
+div.nl div.intro {
+    margin : 4ex 3ex;
+}
+
+div.nl div.lnk {
+    text-align: left;
+    margin : 2ex 6ex;
+}
+
+div.nl div.lnk a {
+    font-size : 95%;
+}
+
+div.nl div.top_lnk {
+    margin : 2ex;
+    padding : 0;
+    font-size : 85%;
+    text-align : right;
+}
+
+div.nl h1.xorg_nl {
+    margin : 3ex 0 2ex;
+    padding : 1.5ex 2ex 0.5ex 1ex;
+    font-size : 120%;
+    font-weight : bold;
+    text-align : right;
+    background: none;
+    background-color : #369;
+    color : #fff;
+    border: none;
+}
+
+div.nl h2.xorg_nl {
+    margin : 2ex 0 0;
+    padding : 0.4ex 2ex;
+    font-size : 100%;
+    font-weight : bold;
+    font-style : italic;
+    background-color : #fff;
+    background: none;
+    color : #369;
+    border-width : thin 0;
+    border-style : solid;
+    border-color : #369;
+}
+
+div.nl div.art {
+    margin : 2ex 3ex;
+}
+
+div.nl div.app {
+    margin : 2ex 6ex 0 3ex;
+    font-size : 95%;
+    text-align : left;
+}
+
+div.nl div.foot1 {
+    margin : 8ex 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.nl div.foot2 {
+    padding : 1ex 0;
+    font-size : 90%;
+    background-color : #fff;
+    color : #999;
+    text-align : center;
+}
+
index 6e64780..8ed2622 100644 (file)
@@ -69,7 +69,7 @@ function fill_email_combobox(PlPage $page, array $retrieve, $user = null)
                 $emails['Email annuaire AX'] = array($profile->email_directory);
             } elseif (in_array('stripped_directory', $retrieve)) {
                 if (User::isForeignEmailAddress($profile->email_directory)) {
-                    $is_redirect = XDB::fecthOneCell('SELECT  COUNT(*)
+                    $is_redirect = XDB::fetchOneCell('SELECT  COUNT(*)
                                                         FROM  email_redirect_account
                                                        WHERE  uid = {?} AND redirect = {?}',
                                                      $user->id(), $profile->email_directory);
index 2faf993..447c7b7 100644 (file)
@@ -501,10 +501,14 @@ class NewsLetter
     /** Get the prefix leading to the page for this NL
      * Only X.org / AX / X groups may be seen on X.org.
      */
-    public function prefix($enforce_xnet=true)
+    public function prefix($enforce_xnet=true, $with_group=true)
     {
         if (!empty($GLOBALS['IS_XNET_SITE'])) {
-            return $this->group . '/nl';
+            if ($with_group) {
+                return $this->group . '/nl';
+            } else {
+                return 'nl';
+            }
         }
         switch ($this->group) {
         case self::GROUP_XORG:
@@ -521,10 +525,14 @@ class NewsLetter
 
     /** Get the prefix to use for all 'admin' pages of this NL.
      */
-    public function adminPrefix($enforce_xnet=true)
+    public function adminPrefix($enforce_xnet=true, $with_group=true)
     {
         if (!empty($GLOBALS['IS_XNET_SITE'])) {
-            return $this->group . '/admin/nl';
+            if ($with_group) {
+                return $this->group . '/admin/nl';
+            } else {
+                return 'admin/nl';
+            }
         }
         switch ($this->group) {
         case self::GROUP_XORG:
@@ -559,6 +567,18 @@ class NewsLetter
         return $this->custom_css;
     }
 
+    public function canSyncWithGroup()
+    {
+        switch ($this->group) {
+          case self::GROUP_XORG:
+          case self::GROUP_AX:
+          case self::GROUP_EP:
+            return false;
+          default:
+            return true;
+        }
+    }
+
     // }}}
 }
 
@@ -825,7 +845,11 @@ class NLIssue
     public function last()
     {
         if (is_null($this->id_last)) {
-            $this->id_last = $this->nl->getIssue('last')->id;
+            try {
+                $this->id_last = $this->nl->getIssue('last')->id;
+            } catch (MailNotFound $e) {
+                $this->id_last = null;
+            }
         }
         return $this->id_last;
     }
index 40ad2fd..84f354a 100644 (file)
@@ -403,6 +403,39 @@ class UFB_MentorSearch extends UserFilterBuilder
 }
 // }}}
 
+// {{{ class UFB_DeltaTenSearch
+class UFB_DeltaTenSearch extends UserFilterBuilder
+{
+    public function __construct($envprefix = '')
+    {
+        $fields = array(
+            new UFBF_DeltaTenMessage('deltaten_message'),
+
+            new UFBF_Town('city', 'Ville / Code Postal'),
+            new UFBF_Country('countryTxt', 'country', 'Pays'),
+            new UFBF_AdminArea('administrativearea', 'Région'),
+            new UFBF_SubAdminArea('subadministrativearea', 'Département'),
+
+
+            new UFBF_EducationSchool('schoolTxt', 'school', "École d'application"),
+            new UFBF_EducationDegree('diplomaTxt', 'diploma', 'Diplôme'),
+            new UFBF_EducationField('fieldTxt', 'field', "Domaine d'études"),
+
+            new UFBF_JobCompany('entreprise', 'Entreprise'),
+            new UFBF_JobDescription('jobdescription', 'Fonction'),
+            new UFBF_JobTerms('jobterm', 'Mots-clefs'),
+
+            new UFBF_Nationality('nationaliteTxt', 'nationalite', 'Nationalité'),
+            new UFBF_Binet('binetTxt', 'binet', 'Binet'),
+            new UFBF_Group('groupexTxt', 'groupex', 'Groupe X'),
+            new UFBF_Section('sectionTxt', 'section', 'Section'),
+            new UFBF_Sex('woman', 'Sexe'),
+        );
+        parent::__construct($fields, $envprefix);
+    }
+}
+// }}}
+
 // {{{ class UFB_NewsLetter
 class UFB_NewsLetter extends UserFilterBuilder
 {
@@ -414,8 +447,8 @@ class UFB_NewsLetter extends UserFilterBuilder
     {
         $fields = array();
         if ($flags->hasFlag(self::FIELDS_PROMO)) {
-            $fields[] = new UFBF_Promo('promo1', 'Promotion', 'egal1');
-            $fields[] = new UFBF_Promo('promo2', 'Promotion', 'egal2');
+            $fields[] = new UFBF_Promo('promo1', 'Promotion', 'egal1', 'edu_type');
+            $fields[] = new UFBF_Promo('promo2', 'Promotion', 'egal2', 'edu_type');
         }
         if ($flags->hasFlag(self::FIELDS_AXID)) {
             $fields[] = new UFBF_SchoolIds('axid', 'Matricule AX', UFC_SchoolId::AX);
@@ -1422,5 +1455,15 @@ class UFBF_MentorExpertise extends UFBF_Text
 }
 // }}}
 
+// {{{ class UFBF_DeltaTenMessage
+class UFBF_DeltaTenMessage extends UFBF_Text
+{
+    protected function buildUFC(UserFilterBuilder $ufb)
+    {
+        return new UFC_DeltaTen_Message($this->val);
+    }
+}
+// }}}
+
 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
 ?>
index 2c58419..c590527 100644 (file)
@@ -123,26 +123,31 @@ class AdvancedSearchSet extends SearchSet
     }
 }
 
-/** Simple set based on an array of User objects
+/** Simple set based on an array of User emails
  */
-class ArraySet extends ProfileSet
+class UserArraySet extends UserSet
 {
-    public function __construct(array $users)
+    public function __construct(array $emails)
     {
-        $hruids = User::getBulkHruid($users, array('User', '_silent_user_callback'));
-        if (is_null($hruids) || count($hruids) == 0) {
-            $cond = new PFC_False();
-        } else {
-            $cond = new UFC_Hruid($hruids);
-        }
-        parent::__construct($cond);
+        parent::__construct(new UFC_Email($emails));
+    }
+}
+
+/** Simple set based on an array of Profile emails
+ */
+class ProfileArraySet extends ProfileSet
+{
+    public function __construct(array $emails)
+    {
+        parent::__construct(new UFC_Email($emails));
     }
 }
 
-/** A multipage view for profiles
+
+/** A multipage view for profiles or users
  * Allows the display of bounds when sorting by name or promo.
  */
-abstract class ProfileView extends MultipageView
+abstract class MixedView extends MultipageView
 {
     protected function getBoundValue($obj)
     {
@@ -156,6 +161,20 @@ abstract class ProfileView extends MultipageView
             default:
                 return null;
             }
+        } elseif ($obj instanceof User) {
+            switch ($this->bound_field) {
+            case 'name':
+                $name = $obj->lastName();
+                return strtoupper($name);
+            case 'promo':
+                if ($obj->hasProfile()) {
+                    return $obj->profile()->promo();
+                } else {
+                    return 'ext';
+                }
+            default:
+                return null;
+            }
         }
         return null;
     }
@@ -189,7 +208,7 @@ abstract class ProfileView extends MultipageView
  * - with_score: whether to allow ordering by score (set only for a quick search)
  * - starts_with: show only names beginning with the given letter
  */
-class MinificheView extends ProfileView
+class MinificheView extends MixedView
 {
     public function __construct(PlSet $set, array $params)
     {
@@ -239,7 +258,7 @@ class MinificheView extends ProfileView
     }
 }
 
-class MentorView extends ProfileView
+class MentorView extends MixedView
 {
     public function __construct(PlSet $set, array $params)
     {
@@ -264,7 +283,45 @@ class MentorView extends ProfileView
     }
 }
 
-class TrombiView extends ProfileView
+class GroupMemberView extends MixedView
+{
+    public function __construct(PlSet $set, array $params)
+    {
+        $this->entriesPerPage = 20;
+        $this->addSort(new PlViewOrder('name', array(new UFO_Name(Profile::DN_SORT)), 'nom'));
+        $this->addSort(new PlViewOrder('promo', array(
+                    new UFO_Promo(UserFilter::DISPLAY, true),
+                    new UFO_Name(Profile::DN_SORT),
+                ), 'promotion'));
+        parent::__construct($set, $params);
+    }
+
+    public function templateName()
+    {
+        return 'include/plview.groupmember.tpl';
+    }
+}
+
+class ListMemberView extends MixedView
+{
+    public function __construct(PlSet $set, array $params)
+    {
+        $this->entriesPerPage = 100;
+        $this->addSort(new PlViewOrder('name', array(new UFO_Name(Profile::DN_SORT)), 'nom'));
+        $this->addSort(new PlViewOrder('promo', array(
+                    new UFO_Promo(UserFilter::DISPLAY, true),
+                    new UFO_Name(Profile::DN_SORT),
+                ), 'promotion'));
+        parent::__construct($set, $params);
+    }
+
+    public function templateName()
+    {
+        return 'include/plview.listmember.tpl';
+    }
+}
+
+class TrombiView extends MixedView
 {
     public function __construct(PlSet $set, array $params)
     {
index 2c8a8d8..a9f4596 100644 (file)
@@ -35,6 +35,7 @@ class AXLetterModule extends NewsletterModule
             'ax/admin/edit/valid'  => $this->make_hook('admin_nl_valid',  AUTH_MDP),
             'ax/admin/edit/cancel' => $this->make_hook('admin_nl_cancel', AUTH_MDP),
             'ax/admin/edit/delete' => $this->make_hook('admin_nl_delete', AUTH_MDP),
+            'ax/admin/categories'  => $this->make_hook('admin_nl_cat',    AUTH_MDP),
         );
     }
 
diff --git a/modules/deltaten.php b/modules/deltaten.php
new file mode 100644 (file)
index 0000000..5695382
--- /dev/null
@@ -0,0 +1,95 @@
+<?php
+/***************************************************************************
+ *  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                *
+ ***************************************************************************/
+
+/** This module handles the "N N-10" operation, locally named "Delta10".
+ */
+class DeltaTenModule extends PLModule
+{
+    function handlers()
+    {
+        return array(
+            'deltaten/search'   => $this->make_hook('index', AUTH_COOKIE),
+            'deltaten'          => $this->make_hook('index', AUTH_COOKIE),
+        );
+    }
+
+    /** Check whether a given user is in a "DeltaTen" promo.
+     * This is based on "has a profile, is an X, and is in a young enough promo".
+     */
+    protected function isDeltaTenEnabled(User $user, $role)
+    {
+        if (!$user->hasProfile()) {
+            return false;
+        }
+        return $user->profile()->isDeltaTenEnabled($role);
+    }
+
+    function handler_index($page, $action='', $subaction='')
+    {
+        global $globals;
+        if (!$this->isDeltaTenEnabled(S::user(), Profile::DELTATEN_YOUNG)) {
+            $page->killError("Ta promotion ne participe pas à l'opération N N-10.");
+        }
+
+        if ($this->isDeltaTenEnabled(S::user(), Profile::DELTATEN_OLD)) {
+            $profile = S::user()->profile();
+            if ($profile->getDeltatenMessage()) {
+                $page->trigSuccess("Tu participes bien à l'opération N N-10 en tant qu'ancien.");
+            } else {
+                $page->trigWarning("Tu ne participes pas encore à l'opération N N-10 en tant qu'ancien.");
+            }
+        }
+        $page->setTitle("Opération N N-10");
+        $page->assign('deltaten_promo_old', S::user()->profile()->yearpromo() - 10);
+        $wp = new PlWikiPage('Docs.Deltaten');
+        $wp->buildCache();
+
+        require_once 'ufbuilder.inc.php';
+        $ufb = new UFB_DeltaTenSearch();
+        if (!$ufb->isEmpty()) {
+            require_once 'userset.inc.php';
+            $ufc = $ufb->getUFC();
+            if (!$ufc instanceof PFC_And) {
+                $ufc = new PFC_And($ufc);
+            }
+            $ufc->addChild(new UFC_DeltaTen());
+            $ufc->addChild(new UFC_Promo('=', UserFilter::GRADE_ING, S::user()->profile()->yearpromo() - 10));
+
+            $set = new ProfileSet($ufc);
+            $set->addMod('minifiche', 'Opération N N-10');
+            $set->apply('deltaten/search', $page, $action, $subaction);
+            $nb_tot = $set->count();
+            if ($nb_tot > $globals->search->private_max) {
+                $page->assign('formulaire', 1);
+                $page->trigError('Recherche trop générale.');
+                $page->assign('plset_count', 0);
+            } else if ($nb_tot == 0) {
+                $page->assign('formulaire', 1);
+                $page->trigError("Il n'existe personne correspondant à ces critères dans la base.");
+            }
+        }
+        $page->changeTpl('deltaten/index.tpl');
+    }
+}
+
+
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+?>
index ac4ef72..0cb1c0f 100644 (file)
@@ -35,6 +35,7 @@ class EPLetterModule extends NewsletterModule
             'epletter/admin/edit/valid'  => $this->make_hook('admin_nl_valid',  AUTH_MDP),
             'epletter/admin/edit/cancel' => $this->make_hook('admin_nl_cancel', AUTH_MDP),
             'epletter/admin/edit/delete' => $this->make_hook('admin_nl_delete', AUTH_MDP),
+            'epletter/admin/categories'  => $this->make_hook('admin_nl_cat',    AUTH_MDP),
         );
     }
 
index e02c253..72519bb 100644 (file)
@@ -83,7 +83,7 @@ class GoogleAppsModule extends PLModule
                 if ($account->pending_update_suspension) {
                     $page->trigWarning("Ton compte est déjà en cours de désactivation.");
                 } else {
-                    if ($redirect->modify_one_email('googleapps', false) == SUCCESS) {
+                    if (!$redirect_active || $redirect->modify_one_email('googleapps', false) == SUCCESS) {
                         $account->suspend();
                         $page->trigSuccess("Ton compte Google Apps est dorénavant désactivé.");
                     } else {
index eec6fa2..8b417e0 100644 (file)
@@ -377,29 +377,35 @@ class ListsModule extends PLModule
             $page->kill("La liste n'existe pas ou tu n'as pas le droit d'en voir les détails.");
         }
 
-        global $platal;
         list(,$members) = $this->client->get_members($liste);
-        $users = array();
-        foreach ($members as $m) {
-            $users[] = $m[1];
+
+        if ($action == 'moderators') {
+            $users = $owners;
+            $show_moderators = true;
+            $action = $subaction;
+            $subaction = '';
+        } else {
+            $show_moderators = false;
+            $users = array();
+            foreach ($members as $m) {
+                $users[] = $m[1];
+            }
         }
+
         require_once 'userset.inc.php';
-        $view = new ArraySet($users);
-        $view->addMod('trombi', 'Trombinoscope', true, array('with_promo' => true));
+        $view = new UserArraySet($users);
+        $view->addMod('trombi', 'Trombinoscope', false, array('with_promo' => true));
+        $view->addMod('listmember', 'Annuaire', true);
         if (empty($GLOBALS['IS_XNET_SITE'])) {
             $view->addMod('minifiche', 'Mini-fiches', false);
         }
         // TODO: Reactivate when the new map is completed.
         // $view->addMod('geoloc', 'Planisphère');
         $view->apply("lists/annu/$liste", $page, $action, $subaction);
-        if ($action == 'geoloc' && $subaction) {
-            return;
-        }
 
         $page->changeTpl('lists/annu.tpl');
-        $moderos = list_sort_owners($owners[1]);
         $page->assign_by_ref('details', $owners[0]);
-        $page->assign_by_ref('owners',  $moderos);
+        $page->assign('show_moderators', $show_moderators);
     }
 
     function handler_archives($page, $liste = null, $action = null, $artid = null)
index 3accf5f..0f57706 100644 (file)
@@ -103,7 +103,7 @@ class NewsletterModule extends PLModule
         }
 
         if (!Post::has('nl_search')) {
-            pl_redirect($nl->prefix());
+            pl_redirect($nl->prefix(true, false));
         }
 
         $nl_search = Post::t('nl_search');
@@ -199,7 +199,7 @@ class NewsletterModule extends PLModule
             S::logger()->log('nl_issue_create', $nid);
 
             $id = $nl->createPending();
-            pl_redirect($nl->adminPrefix() . '/edit/' . $id);
+            pl_redirect($nl->adminPrefix(true, false) . '/edit/' . $id);
         }
 
         $page->assign_by_ref('nl', $nl);
@@ -273,7 +273,7 @@ class NewsletterModule extends PLModule
         // Delete an article
         if($action == 'delete') {
             $issue->delArticle($aid);
-            pl_redirect($nl->adminPrefix() . "/edit/$nid");
+            pl_redirect($nl->adminPrefix(true, false) . "/edit/$nid");
         }
 
         // Save an article
@@ -281,7 +281,7 @@ class NewsletterModule extends PLModule
             $art  = new NLArticle(Post::v('title'), Post::v('body'), Post::v('append'),
                                   $aid, Post::v('cid'), Post::v('pos'));
             $issue->saveArticle($art);
-            pl_redirect($nl->adminPrefix() . "/edit/$nid");
+            pl_redirect($nl->adminPrefix(true, false) . "/edit/$nid");
         }
 
         // Edit an article
@@ -431,11 +431,30 @@ class NewsletterModule extends PLModule
     }
 
     function handler_admin_nl_cat($page, $action = 'list', $id = null) {
+        $nl = $this->getNl();
+        if (!$nl) {
+            return PL_NOT_FOUND;
+        }
+
+        if (!$nl->mayEdit()) {
+            return PL_FORBIDDEN;
+        }
+
         $page->setTitle('Administration - Newsletter : Catégories');
         $page->assign('title', 'Gestion des catégories de la newsletter');
-        $table_editor = new PLTableEditor('admin/newsletter/categories','newsletter_cat','cid');
+        $table_editor = new PLTableEditor($nl->adminPrefix() . '/categories', 'newsletter_cat','cid');
         $table_editor->describe('title','intitulé',true);
         $table_editor->describe('pos','position',true);
+        if ($nl->group == Newsletter::GROUP_XORG) {
+            $table_editor->add_option_table('newsletters', 'newsletters.id = t.nlid');
+            $table_editor->add_option_field('newsletters.name', 'newsletter_name', 'Newsletter', null, 'nlid');
+            $table_editor->describe('nlid', 'ID NL', true);
+        } else {
+            $table_editor->force_field_value('nlid', $nl->id);
+            $table_editor->describe('nlid', 'nlid', false);
+        }
+        // Prevent deletion.
+        $table_editor->on_delete(null, null);
         $table_editor->apply($page, $action, $id);
     }
 }
index 061d3ce..28f69aa 100644 (file)
@@ -55,6 +55,11 @@ class BPLCCyberPlus
     // }}}
     // {{{ function form()
 
+    private static function replaceNonAlpha($string)
+    {
+        return trim(preg_replace('/\s\s+/', ' ', preg_replace('/[^a-zA-Z0-9]/', ' ', $string)));
+    }
+
     function prepareform($pay)
     {
         global $globals, $platal;
@@ -76,7 +81,7 @@ class BPLCCyberPlus
         $this->infos['client'] = Array(
             'vads_cust_email' => S::user()->bestEmail(),
             'vads_cust_id' => S::v('uid'),
-            'vads_cust_name' => replace_accent(S::user()->fullName()));
+            'vads_cust_name' => substr(self::replaceNonAlpha(replace_accent(S::user()->shortName())), 0, 127));
         $this->infos['commande'] = Array(
             'vads_amount' => $this->val,
             'vads_currency' => '978', # Euro
@@ -84,7 +89,7 @@ class BPLCCyberPlus
             'vads_trans_date' => $trans_date,
             'vads_trans_id' => $trans_id,
             'vads_order_id' => $fullref,
-            'vads_order_info' => Env::v('comment'));
+            'vads_order_info' => substr(self::replaceNonAlpha(replace_accent(Env::v('comment'))), 0, 255));
         $this->infos['divers'] = Array(
             'vads_version' => 'V2',
             'vads_ctx_mode' => $globals->money->cyperplus_prod,
index bbdd8ea..4b830fc 100644 (file)
@@ -40,6 +40,7 @@ class ProfileModule extends PLModule
             'profile/networking'         => $this->make_hook('networking',                 AUTH_PUBLIC),
             'profile/ajax/job'           => $this->make_hook('ajax_job',                   AUTH_COOKIE, 'user', NO_AUTH),
             'profile/ajax/skill'         => $this->make_hook('ajax_skill',                 AUTH_COOKIE, 'user', NO_AUTH),
+            'profile/ajax/deltaten'      => $this->make_hook('ajax_deltaten',              AUTH_COOKIE, 'user', NO_AUTH),
             'profile/ajax/searchname'    => $this->make_hook('ajax_searchname',            AUTH_COOKIE, 'user', NO_AUTH),
             'profile/ajax/buildnames'    => $this->make_hook('ajax_buildnames',            AUTH_COOKIE, 'user', NO_AUTH),
             'profile/ajax/tree/jobterms' => $this->make_hook('ajax_tree_job_terms',        AUTH_COOKIE, 'user', NO_AUTH),
@@ -313,7 +314,7 @@ class ProfileModule extends PLModule
     {
         global $globals;
 
-        if (in_array($hrpid, array('general', 'adresses', 'emploi', 'poly', 'deco', 'skill', 'mentor'))) {
+        if (in_array($hrpid, array('general', 'adresses', 'emploi', 'poly', 'deco', 'skill', 'mentor', 'deltaten'))) {
             $aux = $opened_tab;
             $opened_tab = $hrpid;
             $hrpid = $aux;
@@ -348,6 +349,9 @@ class ProfileModule extends PLModule
             $wiz->addPage('ProfilePageSkills', 'Compétences diverses', 'skill');
             $wiz->addPage('ProfilePageMentor', 'Mentoring', 'mentor');
         }
+        if (S::user()->checkPerms(User::PERM_DIRECTORY_PRIVATE) && $profile->isDeltatenEnabled(Profile::DELTATEN_OLD)) {
+            $wiz->addPage('ProfilePageDeltaten', 'Opération N N-10', 'deltaten');
+        }
         $wiz->apply($page, 'profile/edit/' . $profile->hrid(), $opened_tab, $mode);
 
         if (!$profile->birthdate) {
diff --git a/modules/profile/deltaten.inc.php b/modules/profile/deltaten.inc.php
new file mode 100644 (file)
index 0000000..31ad0db
--- /dev/null
@@ -0,0 +1,67 @@
+<?php
+/***************************************************************************
+ *  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                *
+ ***************************************************************************/
+
+class ProfilePageDeltaten extends ProfilePage
+{
+    protected $pg_template = 'profile/deltaten.tpl';
+
+    public function __construct(PlWizard $wiz)
+    {
+        parent::__construct($wiz);
+        $this->settings['message'] = null;
+    }
+
+    protected function _fetchData()
+    {
+        $res = XDB::query('SELECT  message
+                             FROM  profile_deltaten
+                            WHERE  pid = {?}',
+                          $this->pid());
+        $this->values['message'] = $res->fetchOneCell();
+    }
+
+    protected function _saveData()
+    {
+        if ($this->changed['message']) {
+            $message = trim($this->values['message']);
+            if (empty($message)) {
+                XDB::execute('DELETE FROM  profile_deltaten
+                                    WHERE  pid = {?}',
+                             $this->pid());
+                $this->values['message'] = null;
+            } else {
+                XDB::execute('INSERT INTO  profile_deltaten (pid, message)
+                                   VALUES  ({?}, {?})
+                  ON DUPLICATE KEY UPDATE  message = VALUES(message)',
+                             $this->pid(), $message);
+                $this->values['message'] = $message;
+            }
+        }
+    }
+
+    public function _prepare(PlPage $page, $id)
+    {
+        $page->assign('hrpid', $this->profile->hrpid);
+    }
+}
+
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+?>
index 2bc4c52..242733f 100644 (file)
@@ -437,6 +437,7 @@ require_once dirname(__FILE__) . '/decos.inc.php';
 require_once dirname(__FILE__) . '/jobs.inc.php';
 require_once dirname(__FILE__) . '/skills.inc.php';
 require_once dirname(__FILE__) . '/mentor.inc.php';
+require_once dirname(__FILE__) . '/deltaten.inc.php';
 
 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
 ?>
index 48d37a8..3a4279a 100644 (file)
@@ -316,7 +316,7 @@ class RegisterModule extends PLModule
         }
 
         list($uid, $pid, $forlife, $bestalias, $emailXorg2, $password, $email, $services,
-             $birthdate, $lastname, $firstname, $promo, $yearpromo, $sex, $birthdate_ref, $type) = $res->fetchOneRow();
+             $birthdate, $lastname, $firstname, $yearpromo, $promo, $sex, $birthdate_ref, $type) = $res->fetchOneRow();
         $isX = ($type == 'x');
         $mail_domain = User::$sub_mail_domains[$type] . $globals->mail->domain;
 
@@ -502,7 +502,7 @@ class RegisterModule extends PLModule
             $market[] = " - par {$sender->fullName()} sur $maketingEmails (le plus récemment le $lastDate)";
             $mymail = new PlMailer('register/marketer.mail.tpl');
             $mymail->setSubject("$firstname $lastname s'est inscrit à Polytechnique.org !");
-            $mymail->addTo($sender);
+            $mymail->setTo($sender);
             $mymail->assign('sender', $sender);
             $mymail->assign('firstname', $firstname);
             $mymail->assign('lastname', $lastname);
index dd225ac..de4f48c 100644 (file)
@@ -324,53 +324,18 @@ class XnetGrpModule extends PLModule
     {
         global $globals;
 
-        if ($action == 'trombi') {
-            __autoload('userset');
-            if ($action == 'trombi') {
-                $view = new ProfileSet(new UFC_Group($globals->asso('id')));
-            } else {
-                $view = new UserSet(new UFC_Group($globals->asso('id')));
-            }
-            $view->addMod('trombi', 'Trombinoscope');
-            $view->apply('annuaire', $page, $action, $subaction);
-            $page->changeTpl('xnetgrp/annuaire.tpl');
-            $count = XDB::fetchOneCell('SELECT  COUNT(*)
-                                          FROM  group_members
-                                         WHERE  asso_id = {?}',
-                                       $globals->asso('id'));
-            $page->assign('nb_tot', $count);
-            return;
-        }
-
+        __autoload('userset');
+        $admins = false;
+        if ($action == 'admins') {
+            $admins = true;
+            $action = $subaction;
+        }
+        $view = new UserSet(new UFC_Group($globals->asso('id'), $admins));
+        $view->addMod('groupmember', 'Annuaire');
+        $view->addMod('trombi', 'Trombinoscope');
+        $view->apply('annuaire', $page, $action);
+        $page->assign('only_admin', $admins);
         $page->changeTpl('xnetgrp/annuaire.tpl');
-        $sort = Env::s('order', 'directory_name');
-        $ofs  = Env::i('offset');
-        if ($ofs < 0) {
-            $ofs = 0;
-        }
-
-        $sdesc = $sort{0} == '-';
-        $sf    = $sdesc ? substr($sort, 1) : $sort;
-        if ($sf == 'promo') {
-            $se = new UFO_Promo(null, $sdesc);
-        } else {
-            $se = new UFO_Name($sf, null, null, $sdesc);
-        }
-
-        if (Env::b('admin')) {
-            $uf = $globals->asso()->getAdminsFilter(null, $se);
-        } else {
-            $uf = $globals->asso()->getMembersFilter(null, $se);
-        }
-        $users = $uf->getUsers(new PlLimit(NB_PER_PAGE, $ofs * NB_PER_PAGE));
-        $count = $uf->getTotalCount();
-
-        $page->assign('nb_tot', $count);
-        $page->assign('pages', floor(($count + NB_PER_PAGE - 1) / NB_PER_PAGE));
-        $page->assign('current', $ofs);
-        $page->assign('order', $sort);
-        $page->assign('users', $users);
-        $page->assign('only_admin', Env::b('admin'));
     }
 
     function handler_trombi($page)
@@ -495,15 +460,19 @@ class XnetGrpModule extends PLModule
         }
         $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');
+        if (count($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');
+        } else {
+            $users = array();
+        }
         sort($nonusers);
 
         $page->assign('users', $users);
@@ -1299,7 +1268,7 @@ class XnetGrpModule extends PLModule
             $page->trigError('Le fichier n\'est pas une image valide au format JPEG, GIF ou PNG.');
             $upload->rm();
             return false;
-        } elseif (!$upload->resizeImage(200, 300, 100, 100, 32284)) {
+        } elseif (!$upload->resizeImage(80, 100, 100, 100, 32284)) {
             $page->trigError('Impossible de retraiter l\'image');
             return false;
         }
index 1979087..a6fb168 100644 (file)
@@ -30,6 +30,8 @@ class XnetNlModule extends NewsletterModule
             '%grp/nl/show'              => $this->make_hook('nl_show',         AUTH_MDP),
             '%grp/nl/search'            => $this->make_hook('nl_search',       AUTH_MDP),
             '%grp/admin/nl'             => $this->make_hook('admin_nl',        AUTH_MDP, 'groupadmin'),
+            '%grp/admin/nl/sync'        => $this->make_hook('admin_nl_sync',   AUTH_MDP, 'groupadmin'),
+            '%grp/admin/nl/enable'      => $this->make_hook('admin_nl_enable', AUTH_MDP, 'groupadmin'),
             '%grp/admin/nl/edit'        => $this->make_hook('admin_nl_edit',   AUTH_MDP, 'groupadmin'),
             '%grp/admin/nl/edit/cancel' => $this->make_hook('admin_nl_cancel', AUTH_MDP, 'groupadmin'),
             '%grp/admin/nl/edit/valid'  => $this->make_hook('admin_nl_valid',  AUTH_MDP, 'groupadmin'),
@@ -43,6 +45,73 @@ class XnetNlModule extends NewsletterModule
        $group = $globals->asso('shortname');
        return NewsLetter::forGroup($group);
     }
+
+    public function handler_admin_nl_sync($page)
+    {
+        global $globals;
+        $nl = $this->getNl();
+        if (!$nl) {
+            return PL_FORBIDDEN;
+        }
+
+        if (Env::has('add_users')) {
+            S::assert_xsrf_token();
+
+            XDB::execute('INSERT IGNORE INTO  newsletter_ins (uid, nlid)
+                                      SELECT  g.uid, n.id
+                                        FROM  group_members AS g
+                                  INNER JOIN  newsletters   AS n  ON (n.group_id = g.asso_id)
+                                       WHERE  g.uid IN {?} AND g.asso_id = {?}',
+                         array_keys(Env::v('add_users')), $globals->asso('id'));
+
+            $page->trigSuccess('Ajouts réalisés avec succès.');
+        }
+
+        $uids = XDB::fetchColumn('SELECT  DISTINCT(g.uid)
+                                    FROM  group_members AS g
+                                   WHERE  g.asso_id = {?} AND NOT EXISTS (SELECT  ni.*
+                                                                            FROM  newsletter_ins AS ni
+                                                                      INNER JOIN  newsletters    AS n  ON (ni.nlid = n.id)
+                                                                           WHERE  g.uid = ni.uid AND n.group_id = g.asso_id)',
+                                 $globals->asso('id'));
+
+        $users = User::getBulkUsersWithUIDs($uids);
+        usort($users, 'User::compareDirectoryName');
+
+        $page->setTitle('Synchronisation de la newsletter');
+        $page->changeTpl('newsletter/sync.tpl');
+        $page->assign('users', $users);
+    }
+
+    public function handler_admin_nl_enable($page)
+    {
+        global $globals;
+        $nl = $this->getNl();
+        if ($nl) {
+            return PL_FORBIDDEN;
+        }
+
+        if (Post::has('title')) {
+            if (!S::has_xsrf_token()) {
+                return PL_FORBIDDEN;
+            }
+
+            XDB::execute('INSERT INTO  newsletters
+                                  SET  group_id = {?}, name = {?}',
+                                  $globals->asso('id'), Post::s('title'));
+
+            $mailer = new PlMailer();
+            $mailer->assign('group', $globals->asso('nom'));
+            $mailer->assign('user', S::user());
+            $mailer->send();
+
+            $page->trigSuccessRedirect("La lettre d'informations du groupe " .
+                                       $globals->asso('nom') . " a bien été créée",
+                                       $globals->asso('shortname') . '/admin/nl');
+        }
+        $page->setTitle('Activation de la newsletter');
+        $page->changeTpl('newsletter/enable.tpl');
+    }
 }
 
 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
diff --git a/plugins/modifier.get_profile.php b/plugins/modifier.get_profile.php
new file mode 100644 (file)
index 0000000..30c393a
--- /dev/null
@@ -0,0 +1,35 @@
+<?php
+/***************************************************************************
+ *  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                *
+ ***************************************************************************/
+
+function smarty_modifier_get_profile($obj)
+{
+  if ($obj instanceof Profile) {
+    return $obj;
+  } elseif ($obj instanceof User) {
+    return $obj->profile();
+  } else {
+    return null;
+  }
+}
+
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+?>
+
diff --git a/plugins/modifier.get_user.php b/plugins/modifier.get_user.php
new file mode 100644 (file)
index 0000000..58b4590
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+/***************************************************************************
+ *  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                *
+ ***************************************************************************/
+
+function smarty_modifier_get_user($obj)
+{
+  if ($obj instanceof User) {
+    return $obj;
+  } elseif ($obj instanceof Profile) {
+    return $obj->owner();
+  } else {
+    return null;
+  }
+}
+
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+?>
+
+
diff --git a/templates/deltaten/index.tpl b/templates/deltaten/index.tpl
new file mode 100644 (file)
index 0000000..375449a
--- /dev/null
@@ -0,0 +1,424 @@
+{**************************************************************************}
+{*                                                                        *}
+{*  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 $plset_count}
+{include core=plset.tpl}
+{else}
+{include wiki=Docs.Deltaten}
+{/if}
+
+<a id="deltaten"></a>
+
+<script type="text/javascript">// <!--
+  var baseurl = $.plURL("deltaten/");
+  var baseurl_search = $.plURL("search/");
+  {literal}
+
+  // display an autocomplete row : blabla (nb of found matches)
+  function make_format_autocomplete(block) {
+    return function(row) {
+        regexp = new RegExp('(' + RegExp.escape(block.value) + ')', 'i');
+
+        name = row[0].htmlEntities().replace(regexp, '<strong>$1<\/strong>');
+
+        if (row[1] === "-1") {
+          return '&hellip;';
+        }
+
+        if (row[1] === "-2") {
+          return '<em>aucun camarade trouvé pour '+row[0].htmlEntities()+'<\/em>';
+        }
+
+        camarades = (row[1] > 1) ? "camarades" : "camarade";
+
+        return name + '<em>&nbsp;&nbsp;-&nbsp;&nbsp;' + row[1].htmlEntities() + '&nbsp;' + camarades + '<\/em>';
+      };
+  }
+
+  // when changing country, open up administrativearea choice
+  function changeCountry(a2) {
+    $(".autocompleteTarget[name='country']").attr('value',a2);
+
+    if (a2) {
+      $(".autocomplete[name='countryTxt']").addClass('hidden_valid');
+
+      $("[name='administrativearea']").parent().load(baseurl_search + 'list/administrativearea/', { country:a2 }, function() {
+          if ($("select[name='administrativearea']").children("option").size() > 1) {
+            $("select[name='administrativearea']").attr('value', '{/literal}{$smarty.request.administrativearea}{literal}');
+
+            $("tr#administrativearea_list").show();
+          } else {
+            $("select[name='administrativearea']").attr('value', '');
+
+            $("tr#administrativearea_list").hide();
+          }
+        });
+    } else {
+      $(".autocomplete[name='countryTxt']").removeClass('hidden_valid');
+
+      $("select[name='administrativearea']").attr('value', '');
+      $("select[name='subadministrativearea']").attr('value', '');
+
+      $("tr#administrativearea_list").hide();
+      $("tr#subadministrativearea_list").hide();
+    }
+  }
+
+  // when changing administrativearea, open up subadministrativearea choice
+  function changeAdministrativeArea(id) {
+    if (id) {
+      $("[name='subadministrativearea']").parent().load(baseurl_search + 'list/subadministrativearea/', { administrativearea:id }, function() {
+          if ($("select[name='subadministrativearea']").children("option").size() > 1) {
+            $("select[name='subadministrativearea']").attr('value', '{/literal}{$smarty.request.subadministrativearea}{literal}');
+            $("tr#subadministrativearea_list").show();
+          } else {
+            $("select[name='subadministrativearea']").attr('value', '');
+            $("tr#subadministrativearea_list").hide();
+          }
+        });
+    } else {
+      $("select[name='subadministrativearea']").attr('value', '');
+      $("tr#subadministrativearea_list").hide();
+    }
+  }
+
+  // when changing school, open diploma choice
+  function changeSchool(schoolId) {
+    $(".autocompleteTarget[name='school']").attr('value',schoolId);
+
+    if (schoolId) {
+      $(".autocomplete[name='schoolTxt']").addClass('hidden_valid');
+    } else {
+      $(".autocomplete[name='schoolTxt']").removeClass('hidden_valid');
+    }
+
+    $("[name='diploma']").parent().load(baseurl_search + 'list/diploma/', { school:schoolId }, function() {
+        $("select[name='diploma']").attr('value', '{/literal}{$smarty.request.diploma}{literal}');
+      });
+  }
+
+  // when choosing a job term in tree, hide tree and set job term field
+  function searchForJobTerm(treeid, jtid, full_name) {
+    $(".term_tree").remove();
+    $("input[name='jobtermTxt']").val(full_name).addClass("hidden_valid").show();
+    $("input[name='jobterm']").val(jtid);
+  }
+
+  function cancel_autocomplete(field, realfield) {
+    $(".autocomplete[name='"+field+"']").removeClass('hidden_valid').val('').focus();
+    if (typeof(realfield) != "undefined") {
+      $(".autocompleteTarget[name='"+realfield+"']").val('');
+    }
+    return;
+  }
+
+  // when choosing autocomplete from list, must validate
+  function select_autocomplete(name) {
+      nameRealField = name.replace(/Txt$/, '');
+
+      // nothing to do if field is not a text field for a list
+      if (nameRealField == name)
+        return null;
+
+      // if changing country, might want to open administrativearea choice
+      if (nameRealField == 'country')
+        return function(i) {
+            if (i.extra[0] < 0) {
+              cancel_autocomplete('countryTxt', 'country');
+              i.extra[1] = '';
+            }
+            changeCountry(i.extra[1]);
+          }
+
+      if (nameRealField == 'school')
+        return function(i) {
+            if (i.extra[0] < 0) {
+              cancel_autocomplete('schoolTxt', 'school');
+              i.extra[1] = '';
+            }
+            changeSchool(i.extra[1]);
+          }
+
+      // change field in list and display text field as valid
+      return function(i) {
+        nameRealField = this.field.replace(/Txt$/, '');
+
+        if (i.extra[0] < 0) {
+          cancel_autocomplete(this.field, nameRealField);
+          return;
+        }
+
+        $(".autocompleteTarget[name='"+nameRealField+"']").attr('value',i.extra[1]);
+
+        $(".autocomplete[name='"+this.field+"']").addClass('hidden_valid');
+      }
+    }
+
+  $(function() {
+      $(".autocompleteTarget").hide();
+      $(".autocomplete").show().each(function() {
+        targeted = $("../.autocompleteTarget",this)[0];
+
+        if (targeted && targeted.value) {
+          me = $(this);
+
+          $.get(baseurl_search + 'list/'+ targeted.name +'/'+targeted.value, {},function(textValue) {
+            me.attr('value', textValue);
+            me.addClass('hidden_valid');
+          });
+        }
+
+        $(this).autocomplete(baseurl_search + "autocomplete/"+this.name,{
+          selectOnly:1,
+          formatItem:make_format_autocomplete(this),
+          field:this.name,
+          onItemSelect:select_autocomplete(this.name),
+          matchSubset:0,
+          width:$(this).width()});
+        });
+
+      $(".autocomplete").change(function() { $(this).removeClass('hidden_valid'); });
+
+      $(".autocomplete[name='countryTxt']").change(function() { changeCountry(''); });
+
+      changeCountry({/literal}'{$smarty.request.country}'{literal});
+      changeAdministrativeArea({/literal}'{$smarty.request.administrativearea}'{literal});
+
+      $(".autocomplete[name='schoolTxt']").change(function() { changeSchool(''); });
+
+      changeSchool({/literal}'{$smarty.request.school}'{literal});
+
+      $(".autocompleteToSelect").each(function() {
+          var fieldName = $(this).attr('href');
+
+          $(this).attr('href', baseurl_search + 'list/'+fieldName).click(function() {
+              var oldval = $("input.autocompleteTarget[name='"+fieldName+"']")[0].value;
+
+              $(".autocompleteTarget[name='"+fieldName+"']").parent().load(baseurl_search + 'list/'+fieldName,{},
+                function(selectBox) {
+                  $(".autocompleteTarget[name='"+fieldName+"']").remove();
+                  $(".autocomplete[name='"+fieldName+"Txt']").remove();
+                  $("select[name='"+fieldName+"']").attr('value', oldval);
+                });
+
+              return false;
+            });
+        }).parent().find('.autocomplete').change(function() {
+          // If we change the value in the type="text" field, then the value in the 'integer id' field must not be used,
+          // to ensure that, we unset it
+          $(this).parent().find('.autocompleteTarget').val('');
+        });
+    });
+/** Regexps to wipe out from search queries */
+var default_form_values = [ /&woman=0(&|$)/, /&[^&=]+=(&|$)/g ];
+/** Uses javascript to clean form from all empty fields */
+function cleanForm(f) {
+  var query = $(f).formSerialize();
+  var old_query;
+  for (var i in default_form_values) {
+    var reg = default_form_values[i];
+    if (typeof(reg) != "undefined") {
+      do {
+        old_query = query;
+        query = query.replace(reg, '$1');
+      } while (old_query != query);
+    }
+  }
+  query = query.replace(/^&*(.*)&*$/, '$1');
+  if (query == "rechercher=Chercher") {
+    alert("Aucun critère n'a été spécifié");
+    return false;
+  }
+  document.location = baseurl + 'search?' + query;
+  return false;
+}
+-->
+{/literal}</script>
+<form id="recherche" action="deltaten/search" method="get" onsubmit="return cleanForm(this)">
+  <table class="bicol" cellpadding="3" summary="Recherche">
+    <tr>
+      <th colspan="2">
+        Opération N N-10
+      </th>
+    </tr>
+    <tr>
+      <td colspan="2" class="titre">
+      Cette recherche est effectuée uniquement au sein des membres de la promotion {$deltaten_promo_old} participant à l'opération N N-10.
+      </td>
+    </tr>
+    <tr>
+      <th colspan="2">Géographie</th>
+    </tr>
+    <tr>
+      <td>Ville ou code postal</td>
+      <td><input type="text" class="autocomplete" name="city" size="32" value="{$smarty.request.city}" /></td>
+    </tr>
+    <tr>
+      <td>Pays</td>
+      <td>
+        <input name="countryTxt" type="text" class="autocomplete" style="display:none" size="32"
+               value="{$smarty.request.countryTxt}"/>
+        <input name="country" class="autocompleteTarget" type="hidden" value="{$smarty.request.country}"/>
+        <a href="country" class="autocompleteToSelect">{icon name="table" title="Tous les pays"}</a>
+      </td>
+    </tr>
+    <tr id="administrativearea_list">
+      <td>Région, province, état&hellip;</td>
+      <td>
+        <input name="administrativearea" type="hidden" size="32" value="{$smarty.request.administrativearea}" />
+      </td>
+    </tr>
+    <tr id="subadministrativearea_list">
+      <td>Département, comté&hellip;</td>
+      <td>
+        <input name="subadministrativearea" type="hidden" size="32" value="{$smarty.request.subadministrativearea}" />
+      </td>
+    </tr>
+    <tr>
+      <td colspan="2">
+        <label for="only_current">
+          <input name="only_current" id="only_current" type="checkbox"{if $smarty.request.only_current} checked="checked"{/if}/>
+          Chercher uniquement les adresses où les camarades sont actuellement.
+        </label>
+      </td>
+    </tr>
+    <tr>
+      <th colspan="2">Activité</th>
+    </tr>
+    <tr>
+      <td>Entreprise</td>
+      <td><input type="text" class="autocomplete" name="entreprise" size="32" value="{$smarty.request.entreprise}" /></td>
+    </tr>
+    <tr>
+      <td>Description</td>
+      <td><input type="text" class="autocomplete" name="description" size="32" value="{$smarty.request.description}" /></td>
+    </tr>
+    <tr>
+      <td>Mots-clefs</td>
+      <td>
+        <input name="jobtermTxt" type="text" class="autocomplete{if $smarty.request.jobterm} hidden_valid{/if}" style="display:none" size="32"
+               value="{$smarty.request.jobtermTxt}"/>
+        <input name="jobterm" class="autocompleteTarget" type="hidden" value="{$smarty.request.jobterm}"/>
+        <a href="jobterm" class="autocompleteToSelect">{icon name="table" title="Tous les mots-clefs"}</a>
+      </td>
+    </tr>
+    <tr>
+      <th colspan="2">Divers</th>
+    </tr>
+    <tr>
+      <td>Sexe</td>
+      <td>
+        <table>
+          <tr>
+            <td style="width:100px">
+              <input type="radio" name="woman" value="0" {if !$smarty.request.woman}checked="checked"{/if} id="woman0"/><label for="woman0">indifférent</label>
+            </td>
+            <td style="width:100px">
+              <input type="radio" name="woman" value="1" {if $smarty.request.woman eq 1}checked="checked"{/if} id="woman1"/><label for="woman1">homme</label>
+            </td>
+            <td style="width:100px">
+              <input type="radio" name="woman" value="2" {if $smarty.request.woman eq 2}checked="checked"{/if} id="woman2"/><label for="woman2">femme</label>
+            </td>
+          </tr>
+        </table>
+      </td>
+    </tr>
+    <tr>
+      <td>Nationalité</td>
+      <td>
+        <input name="nationaliteTxt" type="text" class="autocomplete" style="display:none" size="32"
+               value="{$smarty.request.nationaliteTxt}"/>
+        <input name="nationalite" class="autocompleteTarget" type="hidden" value="{$smarty.request.nationalite}"/>
+        <a href="nationalite" class="autocompleteToSelect">{icon name="table" title="Toutes les nationalités"}</a>
+      </td>
+    </tr>
+    {if hasPerm('directory_private')}
+    <tr>
+      <td>Binet</td>
+      <td>
+        <input name="binetTxt" type="text" class="autocomplete" style="display:none" size="32"
+               value="{$smarty.request.binetTxt}"/>
+        <input name="binet" class="autocompleteTarget" type="hidden" value="{$smarty.request.binet}"/>
+        <a href="binet" class="autocompleteToSelect">{icon name="table" title="Tous les binets"}</a>
+      </td>
+    </tr>
+    {/if}
+    <tr>
+      <td>Groupe X</td>
+      <td>
+        <input name="groupexTxt" type="text" class="autocomplete" style="display:none" size="32"
+               value="{$smarty.request.groupexTxt}"/>
+        <input name="groupex" class="autocompleteTarget" type="hidden" value="{$smarty.request.groupex}"/>
+        <a href="groupex" class="autocompleteToSelect">{icon name="table" title="Tous les groupes X"}</a>
+      </td>
+    </tr>
+    {if hasPerm('directory_private')}
+    <tr>
+      <td>Section</td>
+      <td>
+        <input name="sectionTxt" type="text" class="autocomplete" style="display:none" size="32"
+               value="{$smarty.request.sectionTxt}"/>
+        <input name="section" class="autocompleteTarget" type="hidden" value="{$smarty.request.section}"/>
+        <a href="section" class="autocompleteToSelect">{icon name="table" title="Toutes les sections"}</a>
+      </td>
+    </tr>
+    {/if}
+    <tr>
+      <th colspan="2">Formation</th>
+    </tr>
+    <tr>
+      <td>Formation</td>
+      <td>
+        <input name="schoolTxt" type="text" class="autocomplete" style="display:none" size="32"
+               value="{$smarty.request.schoolTxt}"/>
+        <input name="school" class="autocompleteTarget" type="hidden" value="{$smarty.request.school}"/>
+        <a href="school" class="autocompleteToSelect">{icon name="table" title="Toutes les formations"}</a>
+      </td>
+    </tr>
+    <tr>
+      <td>Diplôme</td>
+      <td>
+        <input name="diploma" size="32" value="{$smarty.request.diploma}"/>
+      </td>
+    </tr>
+    <tr>
+      <th colspan="2">Opération N N-10</th>
+    </tr>
+    <tr>
+      <td>
+        Message spécifique (recherche texte)&nbsp;:
+      </td>
+      <td>
+        <input type="text" value="{$smarty.request.deltaten_message}" size="30" name="deltaten_message" />
+      </td>
+    </tr>
+    <tr><td colspan="2"></td></tr>
+    <tr>
+      <td colspan="2" style="text-align: center">
+          <input type="submit" value="Chercher" />
+      </td>
+    </tr>
+  </table>
+</form>
+
+{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
index 244ae3d..08b8026 100644 (file)
         {/if}
       {/if}
     </div>
+    {elseif hasPerm('directory_private') && $hasowner && $dead}
+    <div>
+      {if $smarty.session.user->isWatchedUser($profile)}
+      <a href="carnet/notifs/del_nonins/{$user->login()}?token={xsrf_token}">{*
+      *}{icon name=cross title="Retirer de la liste de mes surveillances"}</a>
+      {elseif $smarty.session.user->isContact($profile)}
+      <a href="carnet/contacts?action=retirer&amp;user={$profile->hrid()}&amp;token={xsrf_token}">{*
+      *}{icon name=cross title="Retirer de mes contacts"}</a>
+      {/if}
+    </div>
     {/if}
 
     {if hasPerm('admin') || ($smarty.session.user->canEdit($profile) && !$smarty.session.user->isMe($user))}
diff --git a/templates/include/plview.groupmember.entry.tpl b/templates/include/plview.groupmember.entry.tpl
new file mode 100644 (file)
index 0000000..07c7033
--- /dev/null
@@ -0,0 +1,45 @@
+{**************************************************************************}
+{*                                                                        *}
+{*  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               *}
+{*                                                                        *}
+{**************************************************************************}
+
+<tr>
+  <td>
+    {profile user=$user promo=false}
+  </td>
+  <td>
+    {if $user->group_perms eq 'admin' && $user->category()}<strong>{/if}
+    {$user->category()|default:"Extérieur"}
+    {if $user->group_perms eq 'admin' && $user->category()}</strong>{/if}
+  </td>
+  <td>{if $user->group_comm}{$user->group_comm}{else}&nbsp;{/if}</td>
+  <td class="right">
+    {if $user->hasProfile()}
+    <a href="https://www.polytechnique.org/vcard/{$user->login()}.vcf">{icon name=vcard title="[vcard]"}</a>
+    {/if}
+    <a href="mailto:{$user->bestEmail()}">{icon name=email title="email"}</a>
+  </td>
+  {if $is_admin}
+  <td class="center">
+    <a href="{$platal->ns}member/{$user->login()}">{icon name=user_edit title="Édition du profil"}</a>
+    <a href="{$platal->ns}member/del/{$user->login()}">{icon name=delete title="Supprimer de l'annuaire"}</a>
+  </td>
+  {/if}
+</tr>
diff --git a/templates/include/plview.groupmember.tpl b/templates/include/plview.groupmember.tpl
new file mode 100644 (file)
index 0000000..ae538f3
--- /dev/null
@@ -0,0 +1,40 @@
+{**************************************************************************}
+{*                                                                        *}
+{*  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               *}
+{*                                                                        *}
+{**************************************************************************}
+
+
+<table summary="membres du groupe" class="bicol">
+  <tr>
+    <th>Nom</th>
+    <th>Promo</th>
+    <th colspan="2">Infos</th>
+    {if $is_admin}
+      <th>Actions</th>
+    {/if}
+  </tr>
+  {assign var=lostUsers value=false}
+  {foreach from=$set item=user}
+    {if $user->lost}{assign var=lostUsers value=true}{/if}
+    {include file="include/plview.groupmember.entry.tpl" user=$user|get_user}
+  {/foreach}
+</table>
+
+{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
diff --git a/templates/include/plview.listmember.tpl b/templates/include/plview.listmember.tpl
new file mode 100644 (file)
index 0000000..ef2976a
--- /dev/null
@@ -0,0 +1,73 @@
+{**************************************************************************}
+{*                                                                        *}
+{*  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               *}
+{*                                                                        *}
+{**************************************************************************}
+
+
+<table summary="abonnés à la liste" class="bicol" cellpadding="0" cellspacing="0">
+  {if $details.own || hasPerms('admin,groupadmin')}
+  <tr><td colspan="2">
+  <a href="{$platal->ns}lists/csv/{$platal->argv[1]}/{$platal->argv[1]}.csv">
+    {icon name="page_excel" title="Télécharger la liste des membres"}
+    Télécharger la liste des membres au format Excel
+  </a>
+  </td></tr>
+  {/if}
+
+  {assign var=current_key value=''}
+  {foreach from=$set item=obj}
+    {assign var=user value=$obj|get_user}
+    <tr>
+      <td class="titre" style="width: 20%">
+        {if $order eq 'promo'}
+          {assign var=user_key value=$user->promo()}
+        {elseif $order eq 'name'}
+          {assign var=user_key value=$user->lastName()|string_format:'%.1s'|upper}
+        {else}
+          {assign var=user_key value=''}
+        {/if}
+        {if $user_key neq $current_key}
+          {assign var=current_key value=$user_key}
+          {$user_key}
+        {/if}
+      </td>
+      <td>
+        {if $user->hasProfile()}
+          {if $user->lost}{assign var=lostUsers value=true}{/if}
+          {profile user=$user}
+        {else}
+          {$user->displayName()}
+        {/if}
+      </td>
+      {if t($delete)}
+        <td class="center">
+          {if t($user.uid)}
+            <a href="{$platal->ns}member/{$user.uid}">{icon name=user_edit title='Éditer'}</a>&nbsp;
+          {else}
+            {icon name=null}&nbsp;
+          {/if}
+          <a href='{$platal->pl_self(1)}?{$delete}={$user.email}&amp;token={xsrf_token}'>{icon name=cross title='Retirer'}</a>
+        </td>
+      {/if}
+    </tr>
+  {/foreach}
+</table>
+
+{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
index 4f29aaa..d5b7bf0 100644 (file)
@@ -22,7 +22,7 @@
 
 <div class="contact-list" style="clear: both">
 {foreach from=$set item=res}
-  {include file="include/minifiche.tpl" profile=$res}
+  {include file="include/minifiche.tpl" profile=$res|get_profile}
 {/foreach}
 </div>
 
index 8db07cf..1c46ad1 100644 (file)
 <table cellpadding="0" cellspacing="2" style="width: 100%">
   {section name=trombi loop=$set_keys start=0}
   {if $smarty.section.trombi.index % 3 == 1}
-  {assign var=key_prev value=$set_keys[trombi.index_prev]}
-  {assign var=key_cur  value=$set_keys[trombi]}
-  {assign var=key_next value=$set_keys[trombi.index_next]}
-  <tr>
-    {include file="include/plview.trombi.entry.tpl" profile=$set[$key_prev] photo=true}
-    {include file="include/plview.trombi.entry.tpl" profile=$set[$key_cur] photo=true}
-    {include file="include/plview.trombi.entry.tpl" profile=$set[$key_next] photo=true}
-  </tr>
-  <tr>
-    {include file="include/plview.trombi.entry.tpl" profile=$set[$key_prev] photo=false}
-    {include file="include/plview.trombi.entry.tpl" profile=$set[$key_cur] photo=false}
-    {include file="include/plview.trombi.entry.tpl" profile=$set[$key_next] photo=false}
-  </tr>
+    {assign var=key_prev value=$set_keys[trombi.index_prev]}
+    {assign var=key_cur  value=$set_keys[trombi]}
+    {assign var=key_next value=$set_keys[trombi.index_next]}
+    {assign var=profile_prev value=$set[$key_prev]|get_profile}
+    {assign var=profile_cur value=$set[$key_cur]|get_profile}
+    {assign var=profile_next value=$set[$key_next]|get_profile}
+
+    <tr>
+      {include file="include/plview.trombi.entry.tpl" profile=$profile_prev photo=true}
+      {include file="include/plview.trombi.entry.tpl" profile=$profile_cur photo=true}
+      {include file="include/plview.trombi.entry.tpl" profile=$profile_next photo=true}
+    </tr>
+    <tr>
+      {include file="include/plview.trombi.entry.tpl" profile=$profile_prev photo=false}
+      {include file="include/plview.trombi.entry.tpl" profile=$profile_cur photo=false}
+      {include file="include/plview.trombi.entry.tpl" profile=$profile_next photo=false}
+    </tr>
   {elseif ($smarty.section.trombi.index % 3 == 0) && ($smarty.section.trombi.last)}
-  {assign var=key_cur  value=$set_keys[trombi]}
-  <tr>
-    {include file="include/plview.trombi.entry.tpl" profile=$set[$key_cur] photo=true}
-    <td></td><td></td>
-  </tr>
-  <tr style="margin-top: 0; padding-top: 0">
-    {include file="include/plview.trombi.entry.tpl" profile=$set[$key_cur] photo=false}
-    <td></td><td></td>
-  </tr>
+    {assign var=key_cur  value=$set_keys[trombi]}
+    {assign var=profile_cur value=$set[$key_cur]|get_profile}
+    <tr>
+      {include file="include/plview.trombi.entry.tpl" profile=$profile_cur photo=true}
+      <td></td><td></td>
+    </tr>
+    <tr style="margin-top: 0; padding-top: 0">
+      {include file="include/plview.trombi.entry.tpl" profile=$profile_cur photo=false}
+      <td></td><td></td>
+    </tr>
   {/if}
   {/section}
 </table>
index 93326ef..c80f1b6 100644 (file)
   </tr>
 </table>
 
-{include core=plset.tpl}
-
-<h1>
-  modérateurs de la liste
-</h1>
+<p class="center">
+[<a href="{$platal->ns}{$plset_base}/{$plset_mod}{$plset_args}" {if !$show_moderators}class="erreur"{/if}>membres</a>]
+[<a href="{$platal->ns}{$plset_base}/moderators/{$plset_mod}{$plset_args}" {if $show_moderators}class="erreur"{/if}>modérateurs</a>]
+</p>
 
-<table cellpadding="8" cellspacing="2" style="width:100%;">
-  {foreach from=$owners item=xs key=promo}
-    {foreach from=$xs item=x}
-      {if $promo}
-      {cycle values="1,2,3,4" assign="loop"}
-      {if $loop eq "1"}<tr>{/if}
-        <td class='center'>
-          <img src="photo/{$x.l}" width="80" alt=" [ PHOTO ] " />
-          <br />
-          <a href="profile/{$x.l}" class="popup2">
-            {$x.n} ({$promo})
-          </a>
-        </td>
-      {if $loop eq "4"}</tr>{/if}
-      {/if}
-    {/foreach}
-  {/foreach}
-  {if $loop eq "1"}
-    {cycle values="1,2,3" assign="loop"}
-    {cycle values="1,2,3" assign="loop"}
-    {cycle values="1,2,3" assign="loop"}
-    <td></td><td></td><td></td></tr>
-  {elseif $loop eq "2"}
-    {cycle values="1,2,3" assign="loop"}
-    {cycle values="1,2,3" assign="loop"}
-    <td></td><td></td></tr>
-  {elseif $loop eq "3"}
-    {cycle values="1,2,3" assign="loop"}
-    <td></td></tr>
-  {/if}
-</table>
+{include core=plset.tpl}
 
 {* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
index e4d1782..a5d2c03 100644 (file)
   {$nl->name}
 </h1>
 
+<h3>
+  <a href="{$nl->adminPrefix()}/categories">Gérer les catégories d'articles</a>
+</h3>
+
+{if $nl->canSyncWithGroup()}
+<h3>
+  <a href="{$nl->adminPrefix()}/sync">Synchroniser avec les membres du groupe</a>
+</h3>
+{/if}
+
 <table class="bicol" cellpadding="3" cellspacing="0" summary="liste des NL">
   <tr>
     <th>Date</th>
index 90ae27f..143f4cd 100644 (file)
           &nbsp;et&nbsp;
           <input type="text" name="egal2" size="1" style="text-align:center" value="{if t($smarty.request.egal2) eq '&lt;'}&lt;{else}&gt;{/if}" readonly="readonly" />
           <input type="text" name="promo2" size="4" maxlength="4" value="{$smarty.request.promo2}" />
+          <select name="edu_type" style="text-align:center">
+            <option value="{#UserFilter::GRADE_ING#}" {if $smarty.request.edu_type eq #UserFilter::GRADE_ING#}selected="selected"{/if}>X</option>
+            <option value="{#UserFilter::GRADE_MST#}" {if $smarty.request.edu_type eq #UserFilter::GRADE_MST#}selected="selected"{/if}>Master</option>
+            <option value="{#UserFilter::GRADE_PHD#}" {if $smarty.request.edu_type eq #UserFilter::GRADE_PHD#}selected="selected"{/if}>Docteur</option>
+          </select>
         </td>
       </tr>
       {/if}
diff --git a/templates/newsletter/enable.mail.tpl b/templates/newsletter/enable.mail.tpl
new file mode 100644 (file)
index 0000000..90ba6cb
--- /dev/null
@@ -0,0 +1,34 @@
+{**************************************************************************}
+{*                                                                        *}
+{*  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               *}
+{*                                                                        *}
+{**************************************************************************}
+
+{config_load file="mails.conf" section="newsletter_group_enable"}
+{if $mail_part eq 'head'}
+{from full=#from#}
+{to addr=#to#}
+{subject text="Activation de la newsletter du groupe $group"}
+{elseif $mail_part eq 'text'}
+
+La newsletter du groupe $group a été activée par {$user->fullName()}.
+{/if}
+
+{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
+
diff --git a/templates/newsletter/enable.tpl b/templates/newsletter/enable.tpl
new file mode 100644 (file)
index 0000000..dce615b
--- /dev/null
@@ -0,0 +1,48 @@
+{**************************************************************************}
+{*                                                                        *}
+{*  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               *}
+{*                                                                        *}
+{**************************************************************************}
+
+<h1>
+  Mise en place de la lettre d'informations du groupe {$asso->nom}
+</h1>
+
+<p>
+Tu peux demander sur cette page la mise en place d'une newsletter pour le groupe.
+
+Tu pourras ensuite envoyer aux membres du groupe qui auront choisi de s'y inscrire,
+   avec une structure plus adaptée que l'outil d'envoi de mails.
+</p>
+
+<p>
+Si le titre par défaut de la newsletter ne te convient pas, n'hésite pas à
+le modifier.
+
+<form method="post" action="{$platal->ns}admin/nl/enable">
+{xsrf_token_field}
+<p>
+  <label for='title'>Titre de la newsletter</label>
+  <input name='title' id='title' size="40" value="Lettre d'informations du groupe {$asso->nom}" />
+</p>
+<p>
+  <input type="submit" value="Créer" />
+</p>
+</form>
+
index 990722c..6bcb7d5 100644 (file)
 <h2>Ton statut</h2>
 
 {if $nl->subscriptionState()}
+{if $smarty.session.user->type != 'xnet'}
 <p>
-Tu es actuellement inscrit à la {$nl->name} (pour choisir le format HTML ou texte, rends toi sur la page <a href='prefs'>des préférences</a>).
+Tu es actuellement inscrit à la {$nl->name} (pour choisir le format HTML ou texte, rends toi sur la page <a href="https://{$globals->core->secure_domain}/prefs">des préférences</a>).
 </p>
+{/if}
 <div class='center'>
   [<a href='{$nl->prefix()}/out'>{icon name=delete} me désinscrire de la {$nl->name}</a>]
 </div>
diff --git a/templates/newsletter/nl.default.mail.tpl b/templates/newsletter/nl.default.mail.tpl
new file mode 100644 (file)
index 0000000..958250f
--- /dev/null
@@ -0,0 +1,131 @@
+{**************************************************************************}
+{*                                                                        *}
+{*  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               *}
+{*                                                                        *}
+{**************************************************************************}
+
+{config_load file="mails.conf" section="group_newsletter"}
+{if $mail_part eq 'head'}
+{from full=#from#}
+{subject text=$issue->title(true)}
+{if isset(#replyto#)}{add_header name='Reply-To' value=#replyto#}{/if}
+{if isset(#retpath#)}{add_header name='Return-Path' value=#retpath#}{/if}
+{elseif $mail_part eq 'text'}
+{if !$is_mail}
+<pre style="width : 72ex; margin: auto">
+{/if}
+====================================================================
+{$issue->title()}
+====================================================================
+
+{$issue->head($user, 'text')}
+
+
+{foreach from=$issue->arts key=cid item=arts name=cats}
+{$smarty.foreach.cats.iteration} *{$issue->category($cid)}*
+{foreach from=$arts item=art}
+- {$art->title()}
+{/foreach}
+
+{/foreach}
+
+{foreach from=$issue->arts key=cid item=arts}
+--------------------------------------------------------------------
+*{$issue->category($cid)}*
+--------------------------------------------------------------------
+
+{foreach from=$arts item=art}
+{$art->toText($hash, $user->login())}
+
+{/foreach}
+{/foreach}
+
+--------------------------------------------------------------------
+Cette lettre est envoyée aux membres du groupe {$nl->group} par
+l'intermédiaire de Polytechnique.org.
+
+{if $is_mail}
+archives         : <http://www.polytechnique.net/{$nl->prefix()}>
+ne plus recevoir : <http://www.polytechnique.org/{$nl->prefix()}/out/nohash/{$issue->id}>
+{else}
+archives         : &lt;http://www.polytechnique.net/{$nl->prefix()}&gt;
+ne plus recevoir : &lt;http://www.polytechnique.org/{$nl->prefix()}/out/nohash/{$issue->id}&gt;
+{/if}
+{if !$is_mail}
+</pre>
+{/if}
+{elseif $mail_part eq 'html'}
+{if $is_mail}
+<?xml version="1.0" encoding="UTF-8"?>
+<!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>{$nl->name}</title>
+    <style type="text/css">
+      {literal}
+      body      { background-color: #ddd; color: #000; }
+      {/literal}
+    <!--
+      {$issue->css()}
+    -->
+    </style>
+  </head>
+  <body>
+    <div class='nl_background'>
+{/if}
+    <div class='nl'>
+      <div class="title" style="background-image: url({$globals->baseurl}/{$nl->group}/logo);"><a href="{$globals->baseurl}">{$issue->title()}</a></div>
+      <div class="intro">{$issue->head($user, 'html')|smarty:nodefaults}</div>
+      <a id="top_lnk"></a>
+      {foreach from=$issue->arts key=cid item=arts name=cats}
+      <div class="lnk">
+        <a href="{$prefix}#cat{$cid}"><strong>{$smarty.foreach.cats.iteration}. {$issue->category($cid)}</strong></a><br />
+        {foreach from=$arts item=art}
+        <a href="{$prefix}#art{$art->aid}">&nbsp;&nbsp;- {$art->title()}</a><br />
+        {/foreach}
+      </div>
+      {/foreach}
+
+      {foreach from=$issue->arts key=cid item=arts name=cats}
+      <h1 class="xorg_nl"><a id="cat{$cid}"></a>
+        {$issue->category($cid)}
+      </h1>
+      {foreach from=$arts item=art}
+        {$art->toHtml($hash, $user->login())|smarty:nodefaults}
+        <div class="top_lnk"><a href="{$prefix}#top_lnk">Revenir au sommaire</a></div>
+      {/foreach}
+      {/foreach}
+      <div class="foot1">
+        Cette lettre est envoyée à tous les membres du groupe {$nl->group}
+        par l'intermédiaire de Polytechnique.org.
+      </div>
+      <div class="foot2">
+        [<a href="http://www.polytechnique.net/{$nl->prefix()}">archives</a>&nbsp;|
+         <a href="http://www.polytechnique.net/{$nl->prefix()}/out/nohash/{$issue->id}">ne plus recevoir</a>]
+      </div>
+      </div>
+{if $is_mail}
+    </div>
+  </body>
+</html>
+{/if}
+{/if}
+
+{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
+
diff --git a/templates/profile/deltaten.tpl b/templates/profile/deltaten.tpl
new file mode 100644 (file)
index 0000000..275ea31
--- /dev/null
@@ -0,0 +1,59 @@
+{**************************************************************************}
+{*                                                                        *}
+{*  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               *}
+{*                                                                        *}
+{**************************************************************************}
+
+<table class="bicol" summary="Profil&nbsp;: Opération N N-10">
+  <tr>
+    <th>
+      <div class="flags" style="float: left">
+        <input type="checkbox" name="accesX" checked="checked" disabled="disabled" />
+        {icon name="flag_red" title="privé"}
+      </div>
+      Expériences et expertises que tu acceptes de faire partager à la promotion N+10 :
+    </th>
+  </tr>
+  <tr>
+    <td>
+      <p>
+        Si tu acceptes de participer à l'opération N N-10 pour que les camarades de la promotion plus jeune de 10 ans puisse profiter de ton expérience, il te suffit de remplir un message ci-dessous.
+        Cette démarche est complémentaire du « Mentoring », pour lequel tu trouveras plus de détails dans l'onglet dédié.
+      </p>
+
+      <p>
+        Tu peux par exemple donner des conseils sur le choix de carrière, sur ton expérience, &hellip;
+      </p>
+    </td>
+  </tr>
+  <tr>
+    <td>
+      <textarea rows="8" cols="60" name="message">{$message}</textarea>
+    </td>
+  </tr>
+  <tr>
+    <td>
+      Une fois que tu as saisi ton message, il suffit d'enregistrer les modifications en cliquant sur le bouton ci-dessous
+      pour apparaître dans la base de recherche "N N-10".
+    </td>
+  </tr>
+</table>
+
+{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
+
index bb33904..823f592 100644 (file)
@@ -172,7 +172,7 @@ $($.closeOnEsc);
 
       {$profile->promo('details')}
 
-      {if $logged && $profile->mentor_expertise}
+      {if $logged && $view eq 'private' && $profile->mentor_expertise}
       [<a href="referent/{$profile->hrid()}" class='popup2'>Ma fiche référent</a>]
       {/if}
 
index d5eda4f..ebc782b 100644 (file)
 <div class="menu_item"><a href="groupes-x">Mes groupes X</a></div>
 {/if}
 <div class="menu_item"><a href="survey">Sondages</a></div>
+{if hasPerm('directory_private') && $smarty.session.user->hasProfile()}
+  {assign var='profile' value=$smarty.session.user->profile()}
+  {if $profile->isDeltaTenEnabled(#Profile::DELTATEN_YOUNG#)}
+    <div class="menu_item"><a href="deltaten">Opération N N-10</a></div>
+  {/if}
+{/if}
 
 <div class="menu_title">Informations</div>
 <div class="menu_item"><a href="Xorg/">Documentations</a></div>
index f86c54c..70b1c26 100644 (file)
@@ -23,7 +23,7 @@
 <h1>{$asso->nom}&nbsp;: Annuaire du groupe </h1>
 
 <p class="descr">
-Le groupe {$asso->nom} compte {$nb_tot} membres&nbsp;:
+Le groupe {$asso->nom} compte {$plset_count} membres&nbsp;:
 </p>
 
 <ul class="descr">
@@ -70,98 +70,12 @@ Le groupe {$asso->nom} compte {$nb_tot} membres&nbsp;:
   </li>
 </ul>
 
-{if $plset_base}
-{include core=plset.tpl}
-{else}
-
 <p class="center">
-[<a href="{$platal->ns}annuaire?order={$order}" {if !$only_admin}class="erreur"{/if}>tous les membres</a>]
-[<a href="{$platal->ns}annuaire?order={$order}&amp;admin=1" {if $only_admin}class="erreur"{/if}>animateurs</a>]<br/>
-{*
- XXX: This code has been temporary dropped, waiting for a cleaner way to do that stuff
-{foreach from=$alphabet item=c}
-{if $c}
-[<a href="{$platal->ns}annuaire?order={$order}&amp;admin={$only_admin}"{if $request_group eq $c} class="erreur"{/if}>{$c}</a>]
-{/if}
-{/foreach}
-*}
+[<a href="{$platal->ns}{$plset_base}/{$plset_mod}{$plset_args}" {if !$only_admin}class="erreur"{/if}>tous les membres</a>]
+[<a href="{$platal->ns}{$plset_base}/admins/{$plset_mod}{$plset_args}" {if $only_admin}class="erreur"{/if}>animateurs</a>]
 </p>
 
-<table summary="membres du groupe" class="bicol">
-  <tr>
-    <th>
-      <a href="{$platal->ns}annuaire?order={if $order eq 'directory_name'}-{/if}directory_name&amp;admin={$only_admin}">
-      {if $order eq 'directory_name'}
-        <img src="{$platal->baseurl}images/dn.png" alt="" title="Tri croissant" />
-      {elseif $order eq '-directory_name'}
-        <img src="{$platal->baseurl}images/up.png" alt="" title="Tri décroissant" />
-      {/if}
-      NOM Prénom
-      </a>
-    </th>
-    <th>
-      <a href="{$platal->ns}annuaire?order={if $order eq 'promo'}-{/if}promo&amp;admin={$only_admin}">
-      {if $order eq '-promo'}
-        <img src="{$platal->baseurl}images/dn.png" alt="" title="Tri croissant" />
-      {elseif $order eq 'promo'}
-        <img src="{$platal->baseurl}images/up.png" alt="" title="Tri décroissant" />
-      {/if}
-      Promo
-      </a>
-    </th>
-    <th colspan="2">Infos</th>
-    {if $is_admin}
-    <th>Actions</th>
-    {/if}
-  </tr>
-  {assign var=lostUsers value=false}
-  {foreach from=$users item=user}
-  <tr>
-    <td>
-      {if $user->lost}{assign var=lostUsers value=true}{/if}
-      {profile user=$user promo=false}
-    </td>
-    <td>
-      {if $user->group_perms eq 'admin' && $user->category()}<strong>{/if}
-      {$user->category()|default:"Extérieur"}
-      {if $user->group_perms eq 'admin' && $user->category()}</strong>{/if}
-    </td>
-    {if $user->group_comm}
-    <td>{$user->group_comm}</td>
-    {/if}
-    <td class="right"{if !$user->group_comm} colspan="2"{/if}>
-      {if $user->hasProfile()}
-      <a href="https://www.polytechnique.org/vcard/{$user->login()}.vcf">{icon name=vcard title="[vcard]"}</a>
-      {/if}
-      <a href="mailto:{$user->bestEmail()}">{icon name=email title="email"}</a>
-    </td>
-    {if $is_admin}
-    <td class="center">
-      <a href="{$platal->ns}member/{$user->login()}">{icon name=user_edit title="Édition du profil"}</a>
-      <a href="{$platal->ns}member/del/{$user->login()}">{icon name=delete title="Supprimer de l'annuaire"}</a>
-    </td>
-    {/if}
-  </tr>
-  {/foreach}
-</table>
-
-{if $pages gt 1}
-<p class="descr" style="text-align: center">
-{section name="links" loop=$pages}
-{if $smarty.section.links.index eq $current}
-<span class="erreur">{$smarty.section.links.iteration}</span>
-{else}
-{if $smarty.section.links.first}
-<a href="{$platal->ns}annuaire?offset={$current-1}&amp;order={$order}&amp;admin={$only_admin}">précédente</a>
-{/if}
-<a href="{$platal->ns}annuaire?offset={$smarty.section.links.index}&amp;order={$order}&amp;admin={$only_admin}">{$smarty.section.links.iteration}</a>
-{if $smarty.section.links.last}
-<a href="{$platal->ns}annuaire?offset={$current+1}&amp;order={$order}&amp;admin={$only_admin}">suivante</a>
-{/if}
-{/if}
-{/section}
-</p>
-{/if}
+{include core=plset.tpl}
 
 {if $lostUsers}
 <p class="smaller">
@@ -171,6 +85,4 @@ Le groupe {$asso->nom} compte {$nb_tot} membres&nbsp;:
 </p>
 {/if}
 
-{/if}
-
 {* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
index cd71c74..ec6019a 100644 (file)
@@ -40,7 +40,7 @@
     {/foreach}
     <tr>
       <td colspan="3" class="center">
-        <input type="submit" value="Inscrire au groupe" />
+        <input type="submit" value="Activer les comptes" />
       </td>
     </tr>
   </table>
diff --git a/upgrade/1.1.1/15_deltaten.sql b/upgrade/1.1.1/15_deltaten.sql
new file mode 100644 (file)
index 0000000..c26f3c8
--- /dev/null
@@ -0,0 +1,7 @@
+DROP TABLE IF EXISTS profile_deltaten;
+CREATE TABLE `profile_deltaten` (
+  `pid` int(11) unsigned NOT NULL DEFAULT '0',
+  `message` text NOT NULL,
+  PRIMARY KEY (`pid`),
+  CONSTRAINT FOREIGN KEY (`pid`) REFERENCES `profiles` (`pid`) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8
diff --git a/upgrade/1.1.1/group_logos.php b/upgrade/1.1.1/group_logos.php
new file mode 100755 (executable)
index 0000000..b95a046
--- /dev/null
@@ -0,0 +1,56 @@
+#!/usr/bin/php5
+<?php
+
+require_once 'connect.db.inc.php';
+
+$globals->debug = 0; // Do not store backtraces.
+$MAX_X = 200;
+$MAX_Y = 100;
+
+$it = XDB::rawIterator('SELECT  id, diminutif, logo, logo_mime
+                          FROM  groups
+                         WHERE  logo IS NOT NULL AND logo != ""');
+
+while ($row = $it->next()) {
+  $group_id = $row['id'];
+  $group_name = $row['diminutif'];
+  $logo = $row['logo'];
+  $mime = $row['mime'];
+  $img = imagecreatefromstring($logo);
+  if ($img === false) {
+    print "\n\nError reading image for:\n     $group_name\n\n";
+    continue;
+  }
+  $x = imagesx($img);
+  $y = imagesy($img);
+  $nx = $x;
+  $ny = $y;
+  if ($x > $MAX_X || $y > $MAX_Y) {
+    if ($x > $MAX_X) {
+      $ny = intval($y * $MAX_X / $x);
+      $nx = $MAX_X;
+    }
+    if ($y > $MAX_Y) {
+      $nx = intval($x*$MAX_Y/$y);
+      $ny = $MAX_Y;
+    }
+    $img2 = imagecreatetruecolor($nx, $ny);
+    imagealphablending($img2, false);
+    imagesavealpha($img2,true);
+    $transparent = imagecolorallocatealpha($img2, 255, 255, 255, 127);
+    imagefilledrectangle($img2, 0, 0, $nx, $ny, $transparent);
+    imagecopyresampled($img2, $img, 0, 0, 0, 0, $nx, $ny, $x, $y);
+    $tmpf = tempnam('/tmp', 'upgrade_111_group_logos');
+    imagepng($img2, $tmpf);
+    $f = fopen($tmpf, 'r');
+    $logo2 = fread($f, filesize($tmpf));
+    fclose($f);
+    unlink($tmpf);
+    XDB::execute("UPDATE  groups
+                     SET  logo = {?}, logo_mime = 'image/png'
+                   WHERE  id = {?}", $logo2, $group_id);
+  }
+}
+
+
+
index 9230e34..6269d56 100755 (executable)
@@ -7,3 +7,6 @@
 
 confirm "* Running database upgrade scripts"
 mysql_run_directory .
+
+confirm "* Running upgrade scripts"
+script_run ./group_logos.php
diff --git a/upgrade/1.1.2/connect.db.inc.php b/upgrade/1.1.2/connect.db.inc.php
new file mode 120000 (symlink)
index 0000000..442fab7
--- /dev/null
@@ -0,0 +1 @@
+../../bin/connect.db.inc.php
\ No newline at end of file