Enable a DeltaTen module and profile page.
authorRaphaël Barrois <raphael.barrois@polytechnique.org>
Mon, 28 Feb 2011 21:05:51 +0000 (22:05 +0100)
committerRaphaël Barrois <raphael.barrois@polytechnique.org>
Sun, 8 May 2011 23:28:54 +0000 (01:28 +0200)
Signed-off-by: Raphaël Barrois <raphael.barrois@polytechnique.org>
classes/profile.php
classes/xorg.php
configs/platal.ini
modules/deltaten.php [new file with mode: 0644]
modules/profile.php
modules/profile/deltaten.inc.php [new file with mode: 0644]
modules/profile/page.inc.php
templates/deltaten/index.tpl [new file with mode: 0644]
templates/profile/deltaten.tpl [new file with mode: 0644]
templates/skin/common.menu.tpl
upgrade/1.1.0/10_deltaten.sql [new file with mode: 0644]

index e63bfe5..177155a 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_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_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',
 
     static public $descriptions = array(
         'search_names'    => 'Noms',
@@ -144,7 +145,8 @@ class Profile implements PlExportable
         'langues'         => 'Langues',
         'expertise'       => 'Expertises (mentoring)',
         'terms'           => 'Compétences (mentoring)',
         '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;
     );
 
     private $fetched_fields  = 0x000000;
@@ -421,8 +423,8 @@ class Profile implements PlExportable
 
     /**
      * Clears a profile.
 
     /**
      * 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
      *      profile_phones, profile_skills, watch_profile
      *  *always keeps in: profile_corps, profile_display, profile_education,
      *      profile_medals, profile_name, profile_photos, search_name
@@ -433,7 +435,8 @@ class Profile implements PlExportable
         $tables = array(
             'profile_job', 'profile_langskills', 'profile_mentor',
             'profile_networking', 'profile_skills', 'watch_profile',
         $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 . '
 
         foreach ($tables as $t) {
             XDB::execute('DELETE FROM  ' . $t . '
@@ -804,6 +807,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
      */
 
     /* Binets
      */
@@ -907,16 +948,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,
                                      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,
                                      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,
                                      (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)
                                      ap.uid AS owner_id
                                FROM  profiles AS p
                          INNER JOIN  profile_display AS pd ON (pd.pid = p.pid)
@@ -935,6 +977,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_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
                           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
@@ -945,6 +988,7 @@ class Profile implements PlExportable
                            $visibility->isVisible(ProfileVisibility::VIS_PRIVATE), // nickname
                            $visibility->levels(), // mobile
                            $visibility->levels(), // photo
                            $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);
                            $pids
                        );
         return new ProfileIterator($it, $pids, $fields, $visibility);
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',
                             '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()
     }
 
     public function find_hook()
index a057415..ebdb03a 100644 (file)
@@ -208,6 +208,15 @@ event_forum = ""
 event_reply = ""
 
 
 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]
 ; The geocoder section contains parameters used to perform the geocoding 
 ; and the formatting of user addresses.
 [Geocoder]
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 9416557..b45d510 100644 (file)
@@ -39,6 +39,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/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),
             '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),
@@ -312,7 +313,7 @@ class ProfileModule extends PLModule
     {
         global $globals;
 
     {
         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;
             $aux = $opened_tab;
             $opened_tab = $hrpid;
             $hrpid = $aux;
@@ -347,6 +348,9 @@ class ProfileModule extends PLModule
             $wiz->addPage('ProfilePageSkills', 'Compétences diverses', 'skill');
             $wiz->addPage('ProfilePageMentor', 'Mentoring', 'mentor');
         }
             $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) {
         $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__) . '/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:
 ?>
 
 // 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: *}
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 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>
 <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>
 
 <div class="menu_title">Informations</div>
 <div class="menu_item"><a href="Xorg/">Documentations</a></div>
diff --git a/upgrade/1.1.0/10_deltaten.sql b/upgrade/1.1.0/10_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