================================================================================
+VERSION 1.0.2 XX XX XXXX
+
+Bug/Wish:
+
+ * Admin:
+ - #1362: List last profile modifications for secretary -JAC
+
+ * Core:
+ - #1352: Fixes csv downloading with IE8. -JAC
+ - #1355: Mode with propagation of the skinning mode -FRU
+
+ * Payments:
+ - #1290: Fixes display of payments on xnet -JAC
+ - #1318: Fixes PHP errors in PayPal payments -JAC
+
+ * Profile:
+ - #1270: Adapts default picture to main education -JAC
+ - #1340: Allows secretaries and admin to fully edit profiles' name -JAC
+ - #1354: Do not notify death to a deceased user -JAC
+ - #1356: Indicates delivery issues on addresses -JAC
+ - #1360: Default profile publicity is now ax -JAC
+ - #1361: Allows secretaries to validate entreprises -JAC
+ - #1363: Prevents deletion of private information by secretaries -JAC
+ - #1364: Only admin can edit original corps -JAC
+ - #1367: Improves postal address formatting -JAC
+ - #1368: Allows admin profile edition even if birthdate is unknown -JAC
+ - #1369: Properly displays moderated jobs -JAC
+
+ * Register:
+ - #1374: Adapts registration for master and doctorate -JAC
+
+ * Search:
+ - #1365: Outputs csv of postal addresses for advanced search -JAC
+ - #1366: Adds 'by AX id' advanced search for admins -Xel
+
+ * XnetEvent:
+ - #1373: Fixes acceptance of non member in xnet events. -JAC
+
+================================================================================
VERSION 1.0.1 26 10 2010
New:
INNER JOIN profile_display AS pd ON (pm.pid = pd.pid)
INNER JOIN account_profiles AS ap ON (pm.pid = ap.pid AND FIND_IN_SET(\'owner\', ap.perms))
INNER JOIN aliases AS al ON (ap.uid = al.uid AND FIND_IN_SET(\'bestalias\', al.flags))
- ORDER BY pm.pid, pm.field');
+ WHERE pm.type = \'third_party\' AND pm.field != \'deathdate\'
+ ORDER BY pm.pid, pm.field, pm.timestamp');
if ($res->total() > 0) {
$date = time();
$mailer->assign('date', $date);
$mailer->send();
- XDB::execute('DELETE FROM profile_modifications');
+ XDB::execute('DELETE FROM profile_modifications
+ WHERE type = \'third_party\'');
}
// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
--- /dev/null
+#!/usr/bin/php5 -q
+<?php
+/***************************************************************************
+ * Copyright (C) 2003-2010 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 *
+ ***************************************************************************/
+
+require './connect.db.inc.php';
+require_once '../classes/address.php';
+
+$globals->debug = 0; // Do not store backtraces
+
+print "(Re)Formats postal addresses for all addresses in the database.\n";
+$it = XDB::rawIterator('SELECT *
+ FROM profile_addresses
+ ORDER BY pid, jobid, type, id');
+$total = $it->total();
+$i = 0;
+$j = 0;
+printf("\r%u / %u", $i, $total);
+while ($item = $it->next()) {
+ $address = new Address($item);
+ $address->format(array('postalText' => true));
+ $address->delete();
+ $address->save();
+
+ ++$i;
+ if ($i == 100) {
+ ++$j;
+ $i = 0;
+ printf("\r%u / %u", $i + 100 * $j, $total);
+ }
+}
+print "Done.\n";
+
+// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
+?>
const LINK_COMPANY = 'hq';
const LINK_PROFILE = 'home';
+ // List of all available postal formattings.
+ private static $formattings = array('FRANCE' => 'FR');
+
+ // Abbreviations to be used to format French postal addresses.
+ private static $streetAbbreviations = array(
+ 'ALLEE' => 'ALL',
+ 'AVENUE' => 'AV',
+ 'BOULEVARD' => 'BD',
+ 'CENTRE' => 'CTRE',
+ 'CENTRE COMMERCIAL' => 'CCAL',
+ 'IMMEUBLE' => 'IMM',
+ 'IMMEUBLES' => 'IMM',
+ 'IMPASSE' => 'IMP',
+ 'LIEU-DIT' => 'LD',
+ 'LOTISSEMENT' => 'LOT',
+ 'PASSAGE' => 'PAS',
+ 'PLACE' => 'PL',
+ 'RESIDENCE' => 'RES',
+ 'ROND-POINT' => 'RPT',
+ 'ROUTE' => 'RTE',
+ 'SQUARE' => 'SQ',
+ 'VILLAGE' => 'VLGE',
+ 'ZONE D\'ACTIVITE' => 'ZA',
+ 'ZONE D\'AMENAGEMENT CONCERTE' => 'ZAC',
+ 'ZONE D\'AMENAGEMENT DIFFERE' => 'ZAD',
+ 'ZONE INDUSTRIELLE' => 'ZI'
+ );
+ private static $otherAbbreviations = array(
+ 'ADJUDANT' => 'ADJ',
+ 'AERODROME' => 'AERD',
+ 'AEROGARE' => 'AERG',
+ 'AERONAUTIQUE' => 'AERN',
+ 'AEROPORT' => 'AERP',
+ 'AGENCE' => 'AGCE',
+ 'AGRICOLE' => 'AGRIC',
+ 'ANCIEN' => 'ANC',
+ 'ANCIENNEMENT' => 'ANC',
+ 'APPARTEMENT' => 'APP',
+ 'APPARTEMENTS' => 'APP',
+ 'ARMEMENT' => 'ARMT',
+ 'ARRONDISSEMENT' => 'ARR',
+ 'ASPIRANT' => 'ASP',
+ 'ASSOCIATION' => 'ASSOC',
+ 'ASSURANCE' => 'ASSUR',
+ 'ATELIER' => 'AT',
+ 'BARAQUEMENT' => 'BRQ',
+ 'BAS' => 'BAS',
+ 'BASSE' => 'BAS',
+ 'BASSES' => 'BAS',
+ 'BATAILLON' => 'BTN',
+ 'BATAILLONS' => 'BTN',
+ 'BATIMENT' => 'BAT',
+ 'BATIMENTS' => 'BAT',
+ 'BIS' => 'B',
+ 'BOITE POSTALE' => 'BP',
+ 'CABINET' => 'CAB',
+ 'CANTON' => 'CANT',
+ 'CARDINAL' => 'CDL',
+ 'CASE POSTALE' => 'CP',
+ 'CHAMBRE' => 'CHBR',
+ 'CITADELLE' => 'CTD',
+ 'COLLEGE' => 'COLL',
+ 'COLONEL' => 'CNL',
+ 'COLONIE' => 'COLO',
+ 'COMITE' => 'CTE',
+ 'COMMANDANT' => 'CDT',
+ 'COMMERCIAL' => 'CIAL',
+ 'COMMUNE' => 'COM',
+ 'COMMUNAL' => 'COM',
+ 'COMMUNAUX' => 'COM',
+ 'COMPAGNIE' => 'CIE',
+ 'COMPAGNON' => 'COMP',
+ 'COMPAGNONS' => 'COMP',
+ 'COOPERATIVE' => 'COOP',
+ 'COURSE SPECIALE' => 'CS',
+ 'CROIX' => 'CRX',
+ 'DELEGATION' => 'DELEG',
+ 'DEPARTEMENTAL' => 'DEP',
+ 'DEPARTEMENTAUX' => 'DEP',
+ 'DIRECTEUR' => 'DIR',
+ 'DIRECTECTION' => 'DIR',
+ 'DIVISION' => 'DIV',
+ 'DOCTEUR' => 'DR',
+ 'ECONOMIE' => 'ECO',
+ 'ECONOMIQUE' => 'ECO',
+ 'ECRIVAIN' => 'ECRIV',
+ 'ECRIVAINS' => 'ECRIV',
+ 'ENSEIGNEMENT' => 'ENST',
+ 'ENSEMBLE' => 'ENS',
+ 'ENTREE' => 'ENT',
+ 'ENTREES' => 'ENT',
+ 'ENTREPRISE' => 'ENTR',
+ 'EPOUX' => 'EP',
+ 'EPOUSE' => 'EP',
+ 'ETABLISSEMENT' => 'ETS',
+ 'ETAGE' => 'ETG',
+ 'ETAT MAJOR' => 'EM',
+ 'EVEQUE' => 'EVQ',
+ 'FACULTE' => 'FAC',
+ 'FORET' => 'FOR',
+ 'FORESTIER' => 'FOR',
+ 'FRANCAIS' => 'FR',
+ 'FRANCAISE' => 'FR',
+ 'FUSILIER' => 'FUS',
+ 'GENDARMERIE' => 'GEND',
+ 'GENERAL' => 'GAL',
+ 'GOUVERNEMENTAL' => 'GOUV',
+ 'GOUVERNEUR' => 'GOU',
+ 'GRAND' => 'GD',
+ 'GRANDE' => 'GDE',
+ 'GRANDES' => 'GDES',
+ 'GRANDS' => 'GDS',
+ 'HAUT' => 'HT',
+ 'HAUTE' => 'HTE',
+ 'HAUTES' => 'HTES',
+ 'HAUTS' => 'HTS',
+ 'HOPITAL' => 'HOP',
+ 'HOPITAUX' => 'HOP',
+ 'HOSPICE' => 'HOSP',
+ 'HOSPITALIER' => 'HOSP',
+ 'HOTEL' => 'HOT',
+ 'INFANTERIE' => 'INFANT',
+ 'INFERIEUR' => 'INF',
+ 'INFERIEUR' => 'INF',
+ 'INGENIEUR' => 'ING',
+ 'INSPECTEUR' => 'INSP',
+ 'INSTITUT' => 'INST',
+ 'INTERNATIONAL' => 'INTERN',
+ 'INTERNATIONALE' => 'INTERN',
+ 'LABORATOIRE' => 'LABO',
+ 'LIEUTENANT' => 'LT',
+ 'LIEUTENANT DE VAISSEAU' => 'LTDV',
+ 'MADAME' => 'MME',
+ 'MADEMOISELLE' => 'MLLE',
+ 'MAGASIN' => 'MAG',
+ 'MAISON' => 'MAIS',
+ 'MAITRE' => 'ME',
+ 'MARECHAL' => 'MAL',
+ 'MARITIME' => 'MAR',
+ 'MEDECIN' => 'MED',
+ 'MEDICAL' => 'MED',
+ 'MESDAMES' => 'MMES',
+ 'MESDEMOISELLES' => 'MLLES',
+ 'MESSIEURS' => 'MM',
+ 'MILITAIRE' => 'MIL',
+ 'MINISTERE' => 'MIN',
+ 'MONSEIGNEUR' => 'MGR',
+ 'MONSIEUR' => 'M',
+ 'MUNICIPAL' => 'MUN',
+ 'MUTUEL' => 'MUT',
+ 'NATIONAL' => 'NAL',
+ 'NOTRE DAME' => 'ND',
+ 'NOUVEAU' => 'NOUV',
+ 'NOUVEL' => 'NOUV',
+ 'NOUVELLE' => 'NOUV',
+ 'OBSERVATOIRE' => 'OBS',
+ 'PASTEUR' => 'PAST',
+ 'PETIT' => 'PT',
+ 'PETITE' => 'PTE',
+ 'PETITES' => 'PTES',
+ 'PETITS' => 'PTS',
+ 'POLICE' => 'POL',
+ 'PREFET' => 'PREF',
+ 'PREFECTURE' => 'PREF',
+ 'PRESIDENT' => 'PDT',
+ 'PROFESSEUR' => 'PR',
+ 'PROFESSIONNEL' => 'PROF',
+ 'PROFESSIONNELE' => 'PROF',
+ 'PROLONGE' => 'PROL',
+ 'PROLONGEE' => 'PROL',
+ 'PROPRIETE' => 'PROP',
+ 'QUATER' => 'Q',
+ 'QUINQUIES' => 'C',
+ 'RECTEUR' => 'RECT',
+ 'REGIMENT' => 'RGT',
+ 'REGION' => 'REG',
+ 'REGIONAL' => 'REG',
+ 'REGIONALE' => 'REG',
+ 'REPUBLIQUE' => 'REP',
+ 'RESTAURANT' => 'REST',
+ 'SAINT' => 'ST',
+ 'SAINTE' => 'STE',
+ 'SAINTES' => 'STES',
+ 'SAINTS' => 'STS',
+ 'SANATORIUM' => 'SANA',
+ 'SERGENT' => 'SGT',
+ 'SERVICE' => 'SCE',
+ 'SOCIETE' => 'SOC',
+ 'SOUS COUVERT' => 'SC',
+ 'SOUS-PREFET' => 'SPREF',
+ 'SUPERIEUR' => 'SUP',
+ 'SUPERIEURE' => 'SUP',
+ 'SYNDICAT' => 'SYND',
+ 'TECHNICIEN' => 'TECH',
+ 'TECHNICIENNE' => 'TECH',
+ 'TECHNICIQUE' => 'TECH',
+ 'TER' => 'T',
+ 'TRI SERVICE ARRIVEE' => 'TSA',
+ 'TUNNEL' => 'TUN',
+ 'UNIVERSITAIRE' => 'UNVT',
+ 'UNIVERSITE' => 'UNIV',
+ 'VELODROME' => 'VELOD',
+ 'VEUVE' => 'VVE',
+ 'VIEILLE' => 'VIEL',
+ 'VIEILLES' => 'VIEL',
+ 'VIEUX' => 'VX'
+ );
+ private static $entrepriseAbbreviations = array(
+ 'COOPERATIVE D\'UTILISATION DE MATERIEL AGRICOLE EN COMMUN' => 'CUMA',
+ 'ETABLISSEMENT PUBLIC A CARACTERE INDUSTRIEL ET COMMERCIAL' => 'EPIC',
+ 'ETABLISSEMENT PUBLIC ADMINISTRATIF' => 'EPA',
+ 'GROUPEMENT AGRICOLE D\'EXPLOITATION EN COMMUN' => 'GAEC',
+ 'GROUPEMENT D\'INTERET ECONOMIQUE' => 'GIE',
+ 'GROUPEMENT D\'INTERET PUBLIC' => 'GIP',
+ 'GROUPEMENT EUROPEEN D\'INTERET ECONOMIQUE' => 'GEIE',
+ 'OFFICE PUBLIC D\'HABITATION A LOYER MODERE' => 'OPHLM',
+ 'SOCIETE A RESPONSABILITE LIMITEE' => 'SARL',
+ 'SOCIETE ANONYME' => 'SA',
+ 'SOCIETE CIVILE DE PLACEMENT COLLECTIF IMMOBILIER' => 'SCPI',
+ 'SOCIETE CIVILE PROFESSIONNELLE' => 'SCP',
+ 'SOCIETE COOPERATIVE OUVRIERE DE PRODUCTION ET DE CREDIT' => 'SCOP',
+ 'SOCIETE D\'AMENAGEMENT FONCIER ET D\'EQUIPEMENT RURAL' => 'SAFER',
+ 'SOCIETE D\'ECONOMIE MIXTE' => 'SEM',
+ 'SOCIETE D\'INTERET COLLECTIF AGRICOLE' => 'SICA',
+ 'SOCIETE D\'INVESTISSEMENT A CAPITAL VARIABLE' => 'SICAV',
+ 'SOCIETE EN NOM COLLECTIF' => 'SNC',
+ 'SOCIETE IMMOBILIERE POUR LE COMMERCE ET L\'INDUSTRIE' => 'SICOMI',
+ 'SOCIETE MIXTE D\'INTERET AGRICOLE' => 'SMIA',
+ 'SYNDICAT INTERCOMMUNAL A VOCATION MULTIPLE' => 'SIVOM',
+ 'SYNDICAT INTERCOMMUNAL A VOCATION UNIQUE' => 'SIVU'
+ );
+
// Primary key fields: the quadruplet ($pid, $jobid, $type, $id) defines a unique address.
public $pid = 0;
public $jobid = 0;
public $localityName = null;
public $subAdministrativeAreaName = null;
public $administrativeAreaName = null;
+ public $localityNameLocal = null;
+ public $subAdministrativeAreaNameLocal = null;
+ public $administrativeAreaNameLocal = null;
public $countryId = null;
public $latitude = null;
public $longitude = null;
public $east = null;
public $west = null;
public $geocodedText = null;
- public $geocodedPostalText = null;
public $geocodeChosen = null;
// Database's field required for both 'home' and 'job' addresses.
- public $pub = 'private';
+ public $pub = 'ax';
// Database's fields required for 'home' addresses.
- public $flags = null; // 'current', 'temporary', 'secondary', 'mail', 'cedex'
+ public $flags = null; // 'current', 'temporary', 'secondary', 'mail', 'cedex', 'deliveryIssue'
public $comment = null;
public $current = null;
public $temporary = null;
public $secondary = null;
public $mail = null;
+ public $deliveryIssue = null;
// Remaining fields that do not belong to profile_addresses.
public $phones = array();
if (!is_null($this->flags)) {
$this->flags = new PlFlagSet($this->flags);
} else {
- static $flags = array('current', 'temporary', 'secondary', 'mail');
+ static $flags = array('current', 'temporary', 'secondary', 'mail', 'deliveryIssue');
$this->flags = new PlFlagSet();
foreach ($flags as $flag) {
return ($this->flags != null && $this->flags->hasFlag($flag));
}
+ public function addFlag($flag)
+ {
+ $this->flags->addFlag($flag);
+ }
+
+ /** Auxilary function for formatting postal addresses.
+ * If the needle is found in the haystack, it notifies the substitution's
+ * success, modifies the length accordingly and returns either the matching
+ * substitution or the needle.
+ */
+ private function substitute($needle, $haystack, &$length, &$success, $trim = false)
+ {
+ if (array_key_exists($needle, $haystack)) {
+ $success = true;
+ $length -= (strlen($needle) - strlen($haystack[$needle]));
+ return $haystack[$needle];
+ } elseif ($trim) {
+ $success = true;
+ if (strlen($needle) > 4) {
+ $length -= (strlen($needle) - 4);
+ $needle = $needle{4};
+ }
+ }
+ return $needle;
+ }
+
+ /** Checks if the line corresponds to a French street line.
+ * A line is considered a French street line if it starts by between 1 and 4 numbers.
+ */
+ private function isStreetFR($line)
+ {
+ return preg_match('/^\d{1,4}\D/', $line);
+ }
+
+ /** Retrieves a French street number and slit the rest of the line into an array.
+ * @param $words: array containing the rest of the line (a word per cell).
+ * @param $line: line to consider.
+ * Returns the street number.
+ */
+ private function getStreetNumberFR(&$line)
+ {
+ // First we define numbers and separators.
+ $numberReq = '(\d{1,4})\s*(BIS|TER|QUATER|[A-Z])?';
+ $separatorReq = '\s*(?:\\|-|&|A|ET)?\s*';
+
+ // Then we retrieve the number(s) and the rest of the line.
+ // $matches contains:
+ // -0: the full patern, here the given line,
+ // -1: the number,
+ // -2: its optionnal quantifier,
+ // -3: an optionnal second number,
+ // -4: the second number's optionnal quantifier,
+ // -5: the rest of the line.
+ preg_match('/^' . $numberReq . '(?:' . $separatorReq . $numberReq . ')?\s+(.*)/', $line, $matches);
+ $number = $matches[1];
+ $line = $matches[5];
+
+ // If there is a precision on the address, we concatenate it to the number.
+ if ($matches[2] != '') {
+ $number .= $matches[2]{0};
+ } elseif ($matches[4] != '') {
+ $number .= $matches[4]{0};
+ }
+
+ return $number;
+ }
+
+ /** Checks if the line corresponds to a French locality line.
+ * A line is considered a French locality line if it starts by exactly a
+ * postal code of exactly 5 numbers.
+ */
+ private function isLocalityFR($line)
+ {
+ return preg_match('/^\d{5}\D/', $line);
+ }
+
+ /** Retrieves a French postal code and slit the rest of the line into an array.
+ * @param $words: array containing the rest of the line (a word per cell).
+ * @param $line: line to consider.
+ * Returns the postal code, and cuts it out from the line.
+ */
+ private function getPostalCodeFR(&$line)
+ {
+ $number = substr($line, 0, 5);
+ $line = trim(substr($line, 5));
+ return $number;
+ }
+
+ /** Returns the address formated for French postal use (cf AFNOR XPZ 10-011).
+ * A postal addresse containts at most 6 lines of at most 38 characters each:
+ * - addressee's identification ("MONSIEUR JEAN DURAND", "DURAND SA"…),
+ * - delivery point identification ("CHEZ TOTO APPARTEMENT 2", "SERVICE ACHAT"…),
+ * - building localisation complement ("ENTREE A BATIMENT DES JONQUILLES", "ZONE INDUSTRIELLE OUEST"…),
+ * - N° and street name ("25 RUE DES FLEURS", "LES VIGNES"…),
+ * - delivery service, street localisation complement ("BP 40122", "BP 40112 AREYRES"…),
+ * - postal code and locality or cedex code and cedex ("33500 LIBOURNE", "33506 LIBOURNE CEDEX"…).
+ * Punctuation must be removed, all leters must be uppercased.
+ * Both locality and street name must not take more than 32 characters.
+ *
+ * @param $arrayText: array containing the address to be formated, one
+ * address line per array line.
+ * @param $count: array size.
+ */
+ private function formatPostalAddressFR($arrayText)
+ {
+ // First removes country if any.
+ $count = count($arrayText);
+ if ($arrayText[$count - 1] == 'FRANCE') {
+ unset($arrayText[$count - 1]);
+ --$count;
+ }
+
+ // All the lines must have less than 38 characters but street and
+ // locality lines whose limit is 32 characters.
+ foreach ($arrayText as $lineNumber => $line) {
+ if ($isStreetLine = $this->isStreetFR($line)) {
+ $formattedLine = $this->getStreetNumberFR($line) . ' ';
+ $limit = 32;
+ } elseif ($this->isLocalityFR($line)) {
+ $formattedLine = $this->getPostalCodeFR($line) . ' ';
+ $limit = 32;
+ } else {
+ $formattedLine = '';
+ $limit = 38;
+ }
+
+ $words = explode(' ', $line);
+ $count = count($words);
+ $length = $count - 1;
+ foreach ($words as $word) {
+ $length += strlen($word);
+ }
+
+ // Checks is length is ok. Otherwise, we try to shorten words and
+ // update the length of the current line accordingly.
+ for ($i = 0; $i < $count && $length > $limit; ++$i) {
+ $success = false;
+ if ($isStreetLine) {
+ $sub = $this->substitute($words[$i], Address::$streetAbbreviations, $length, $success, ($i == 0));
+ }
+ // Entreprises' substitution are only suitable for the first two lines.
+ if ($lineNumber <= 2 && !$success) {
+ $sub = $this->substitute($words[$i], Address::$entrepriseAbbreviations, $length, $success);
+ }
+ if (!$success) {
+ $sub = $this->substitute($words[$i], Address::$otherAbbreviations, $length, $success);
+ }
+
+ $formattedLine .= $sub . ' ';
+ }
+ for (; $i < $count; ++$i) {
+ $formattedLine .= $words[$i] . ' ';
+ }
+ $arrayText[$lineNumber] = trim($formattedLine);
+ }
+
+ return implode("\n", $arrayText);
+ }
+
+ // Formats postal addresses.
+ // First erases punctuation, accents… Then uppercase the address and finally
+ // calls the country's dedicated formatting function.
+ public function formatPostalAddress()
+ {
+ // Performs rough formatting.
+ $text = mb_strtoupper(replace_accent($this->text));
+ $text = str_replace(array(',', ';', '.', ':', '!', '?', '"', '«', '»'), '', $text);
+ $text = preg_replace('/( |\t)+/', ' ', $text);
+ $arrayText = explode("\n", $text);
+ $arrayText = array_map('trim', $arrayText);
+
+ // Formats according to country rules. Thus we first identify the
+ // country, then apply corresponding formatting or translate country
+ // into default language.
+ $count = count($arrayText);
+ if (in_array(strtoupper($this->countryId), Address::$formattings)) {
+ $text = call_user_func(array($this, 'formatPostalAddress' . strtoupper($this->countryId)), $arrayText);
+ } else {
+ list($countryId, $country) = XDB::fetchOneRow('SELECT gc.iso_3166_1_a2, gc.country
+ FROM geoloc_countries AS gc
+ INNER JOIN geoloc_languages AS gl ON (gc.iso_3166_1_a2 = gl.iso_3166_1_a2)
+ WHERE gc.iso_3166_1_a2 = {?} OR gl.countryPlain = {?} OR gc.countryPlain = {?}',
+ $this->countryId, $arrayText[$count - 1], $arrayText[$count - 1]);
+ if (is_null($countryId)) {
+ $text = $this->formatPostalAddressFR($arrayText);
+ } elseif (in_array(strtoupper($countryId), Address::$formattings)) {
+ $text = call_user_func(array($this, 'formatPostalAddress' . strtoupper($countryId)), $arrayText);
+ } else {
+ $arrayText[$count - 1] = mb_strtoupper(replace_accent($country));
+ $text = implode("\n", $arrayText);
+ }
+ }
+
+ $this->postalText = $text;
+ }
+
public function format(array $format = array())
{
if (empty($format)) {
$format['requireGeocoding'] = false;
$format['stripGeocoding'] = false;
+ $format['postalText'] = false;
+ } else {
+ foreach (array('requireGeocoding', 'stripGeocoding', 'postalText') as $type) {
+ $format[$type] = (isset($format[$type])) ? $format[$type] : false;
+ }
}
$this->text = trim($this->text);
if ($this->removed == 1) {
$this->countryId = null;
}
$this->geocodeChosen = null;
- $this->phones = Phone::formatFormArray($this->phones, $this->error);
+ $this->phones = Phone::formatFormArray($this->phones, $this->error, new ProfileVisibility($this->pub));
+ if ($format['postalText']) {
+ $this->formatPostalAddress();
+ }
return !$this->error;
}
public function toFormArray()
{
$address = array(
- 'accuracy' => $this->accuracy,
- 'text' => $this->text,
- 'postalText' => $this->postalText,
- 'postalCode' => $this->postalCode,
- 'localityId' => $this->localityId,
- 'subAdministrativeAreaId' => $this->subAdministrativeAreaId,
- 'administrativeAreaId' => $this->administrativeAreaId,
- 'countryId' => $this->countryId,
- 'localityName' => $this->localityName,
- 'subAdministrativeAreaName' => $this->subAdministrativeAreaName,
- 'administrativeAreaName' => $this->administrativeAreaName,
- 'latitude' => $this->latitude,
- 'longitude' => $this->longitude,
- 'north' => $this->north,
- 'south' => $this->south,
- 'east' => $this->east,
- 'west' => $this->west,
- 'error' => $this->error,
- 'changed' => $this->changed,
- 'removed' => $this->removed,
+ 'accuracy' => $this->accuracy,
+ 'text' => $this->text,
+ 'postalText' => $this->postalText,
+ 'postalCode' => $this->postalCode,
+ 'localityId' => $this->localityId,
+ 'subAdministrativeAreaId' => $this->subAdministrativeAreaId,
+ 'administrativeAreaId' => $this->administrativeAreaId,
+ 'countryId' => $this->countryId,
+ 'localityName' => $this->localityName,
+ 'subAdministrativeAreaName' => $this->subAdministrativeAreaName,
+ 'administrativeAreaName' => $this->administrativeAreaName,
+ 'localityNameLocal' => $this->localityNameLocal,
+ 'subAdministrativeAreaNameLocal' => $this->subAdministrativeAreaNameLocal,
+ 'administrativeAreaNameLocal' => $this->administrativeAreaNameLocal,
+ 'latitude' => $this->latitude,
+ 'longitude' => $this->longitude,
+ 'north' => $this->north,
+ 'south' => $this->south,
+ 'east' => $this->east,
+ 'west' => $this->west,
+ 'error' => $this->error,
+ 'changed' => $this->changed,
+ 'removed' => $this->removed,
);
if (!is_null($this->geocodedText)) {
$address['geocodedText'] = $this->geocodedText;
- $address['geocodedPostalText'] = $this->geocodedPostalText;
$address['geocodeChosen'] = $this->geocodeChosen;
}
$address['pub'] = $this->pub;
}
if ($this->type == self::LINK_PROFILE) {
- static $flags = array('current', 'temporary', 'secondary', 'mail', 'cedex');
+ static $flags = array('current', 'temporary', 'secondary', 'mail', 'cedex', 'deliveryIssue');
foreach ($flags as $flag) {
$address[$flag] = $this->flags->hasFlag($flag);
private function toString()
{
- $address = 'Adresse : ' . $this->text;
+ $address = $this->text;
if ($this->type == self::LINK_PROFILE || $this->type == self::LINK_JOB) {
- $address .= ', affichage : ' . $this->pub;
+ static $pubs = array('public' => 'publique', 'ax' => 'annuaire AX', 'private' => 'privé');
+ $address .= ' (affichage ' . $pubs[$this->pub];
}
if ($this->type == self::LINK_PROFILE) {
static $flags = array(
- 'current' => 'actuelle',
- 'temporary' => 'temporaire',
- 'secondary' => 'secondaire',
- 'mail' => 'conctactable par courier',
- 'cedex' => 'type cédex',
+ 'current' => 'actuelle',
+ 'temporary' => 'temporaire',
+ 'secondary' => 'secondaire',
+ 'mail' => 'conctactable par courier',
+ 'deliveryIssue' => 'n\'habite pas à l\'adresse indiquée',
+ 'cedex' => 'type cédex',
);
- $address .= ', commentaire : ' . $this->comment;
+ if (!$this->flags->hasFlag('temporary')) {
+ $address .= ', permanente';
+ }
+ if (!$this->flags->hasFlag('secondary')) {
+ $address .= ', principale';
+ }
foreach ($flags as $flag => $flagName) {
if ($this->flags->hasFlag($flag)) {
$address .= ', ' . $flagName;
}
}
+ if ($this->comment) {
+ $address .= ', commentaire : ' . $this->comment;
+ }
if ($phones = Phone::formArrayToString($this->phones)) {
$address .= ', ' . $phones;
}
+ } elseif ($this->type == self::LINK_JOB) {
+ $address .= ')';
}
return $address;
}
{
static $areas = array('administrativeArea', 'subAdministrativeArea', 'locality');
- $this->format();
+ $this->format(array('postalText' => true));
if (!$this->isEmpty()) {
foreach ($areas as $area) {
Geocoder::getAreaId($this, $area);
$this->pid, $this->jobid, $this->type, $this->id);
}
- static public function deleteAddresses($pid, $type, $jobid = null)
+ static public function deleteAddresses($pid, $type, $jobid = null, $deletePrivate = true)
{
$where = '';
if (!is_null($pid)) {
$where = XDB::format(' AND jobid = {?}', $jobid);
}
XDB::execute('DELETE FROM profile_addresses
- WHERE type = {?}' . $where,
+ WHERE type = {?}' . $where . (($deletePrivate) ? '' : ' AND pub IN (\'public\', \'ax\')'),
$type);
if ($type == self::LINK_PROFILE) {
- Phone::deletePhones($pid, Phone::LINK_ADDRESS);
+ Phone::deletePhones($pid, Phone::LINK_ADDRESS, null, $deletePrivate);
}
}
static public function formArrayToString(array $data)
{
- return implode(' ; ', self::formArrayWalk($data, 'toString'));
+ return implode(', ', self::formArrayWalk($data, 'toString'));
}
static public function iterate(array $pids = array(), array $types = array(),
pa.administrativeAreaId, pa.countryId,
pa.latitude, pa.longitude, pa.north, pa.south, pa.east, pa.west,
pa.pub, pa.comment,
- gl.name AS locality, gs.name AS subAdministrativeArea,
- ga.name AS administrativeArea, gc.countryFR AS country
+ gl.name AS locality, gl.nameLocal AS localityLocal,
+ gs.name AS subAdministrativeArea, gs.nameLocal AS subAdministrativeAreaLocal,
+ ga.name AS administrativeArea, ga.nameLocal AS administrativeAreaLocal,
+ gc.country
FROM profile_addresses AS pa
LEFT JOIN geoloc_localities AS gl ON (gl.id = pa.localityId)
LEFT JOIN geoloc_administrativeareas AS ga ON (ga.id = pa.administrativeAreaId)
class DE_Countries extends DirEnumeration
{
protected $idfield = 'geoloc_countries.iso_3166_1_a2';
- protected $valfield = 'geoloc_countries.countryFR';
- protected $valfield2 = 'geoloc_countries.country';
+ protected $valfield = 'geoloc_countries.country';
+ protected $valfield2 = 'geoloc_countries.countryEn';
protected $from = 'geoloc_countries';
protected $ac_join = 'INNER JOIN profile_addresses ON (geoloc_countries.iso_3166_1_a2 = profile_addresses.countryId)';
'subAdministrativeArea' => 'geoloc_subadministrativeareas',
'locality' => 'geoloc_localities',
);
+ static $extras = array(
+ 'subAdministrativeArea' => array(
+ 'field' => 'administrativearea',
+ 'name' => 'administrativeAreaName'
+ )
+ );
$areaName = $area . 'Name';
+ $areaNameLocal = $areaName . 'Local';
$areaId = $area . 'Id';
if (!is_null($address->$areaName) && isset($databases[$area])) {
- $res = XDB::query('SELECT id
+ $extra = (isset($extras[$area]) ? $extras[$area]['administrativeAreaName'] : false);
+
+ $res = XDB::query('SELECT id, nameLocal
FROM ' . $databases[$area] . '
WHERE name = {?}',
$address->$areaName);
if ($res->numRows() == 0) {
- XDB::execute('INSERT INTO ' . $databases[$area] . ' (name, country)
- VALUES ({?}, {?})',
- $address->$areaName, $address->countryId);
+ XDB::execute('INSERT INTO ' . $databases[$area] . ' (name, nameLocal, country' .
+ ($extra ? ', ' . $extras[$area]['field'] : '') . ')
+ VALUES ({?}, {?}, {?}' . ($extra ? ', {?}' : '') . ')',
+ $address->$areaName, $address->$areaNameLocal, $address->countryId,
+ ($extra ? $address->$extra : null));
$address->$areaId = XDB::insertId();
} else {
- $address->$areaId = $res->fetchOneCell();
+ // XXX: remove this once all areas have both nameLocal and name.
+ list($id, $name) = $res->fetchOneRow();
+ if (is_null($name) && !is_null($address->$areaNameLocal)) {
+ XDB::execute('UPDATE ' . $databases[$area] . '
+ SET nameLocal = {?}
+ WHERE id = {?}',
+ $address->$areaNameLocal, $id);
+ }
+ $address->$areaId = $id;
}
} elseif (empty($address->$areaId)) {
$address->$areaId = null;
// and the city name, within the limit of $limit number of lines.
static public function getFirstLines($text, $postalCode, $limit)
{
- $textArray = explode("\n", $text);
+ $text = str_replace("\r", '', $text);
+ $textArray = explode("\n", $text);
+ $linesNb = $limit;
+
for ($i = 0; $i < count($textArray); ++$i) {
- if ($i > $limit || strpos($textLine, $postalCode) !== false) {
- $limit = $i;
+ if ($i > $limit || strpos($textArray[$i], $postalCode) !== false) {
+ $linesNb = $i;
break;
}
}
- return implode("\n", array_slice($textArray, 0, $limit));
+ $firstLines = implode("\n", array_slice($textArray, 0, $linesNb));
+
+ // Adds empty lines to complete the $limit lines required.
+ for (; $i < $limit; ++$i) {
+ $firstLines .= "\n";
+ }
+ return $firstLines;
}
// Returns the number of non geocoded addresses for a user.
// Maximum levenshtein distance authorized between input and geocoded text in the whole text.
const MAX_TOTAL_DISTANCE = 6;
- public function getGeocodedAddress(Address &$address) {
+ public function getGeocodedAddress(Address &$address, $defaultLanguage = null, $forceLanguage = false) {
$this->prepareAddress($address);
$textAddress = $this->getTextToGeocode($address->text);
+ if (is_null($defaultLanguage)) {
+ $defaultLanguage = Platal::globals()->geocoder->gmaps_hl;
+ }
// Try to geocode the full address.
- if (($geocodedData = $this->getPlacemarkForAddress($textAddress))) {
- $this->getUpdatedAddress($address, $geocodedData, null);
+ if (($geocodedData = $this->getPlacemarkForAddress($textAddress, $defaultLanguage))) {
+ $this->getUpdatedAddress($address, $geocodedData, null, $forceLanguage);
return;
}
for ($i = max(1, $linesCount - self::MAX_GMAPS_RPC_CALLS + 1); $i < $linesCount; ++$i) {
$extraLines = implode("\n", array_slice($addressLines, 0, $i));
$toGeocode = implode("\n", array_slice($addressLines, $i));
- if (($geocodedData = $this->getPlacemarkForAddress($toGeocode))) {
- $this->getUpdatedAddress($address, $geocodedData, $extraLines);
+ if (($geocodedData = $this->getPlacemarkForAddress($toGeocode, $defaultLanguage))) {
+ $this->getUpdatedAddress($address, $geocodedData, $extraLines, $forceLanguage);
return;
}
}
public function stripGeocodingFromAddress(Address &$address) {
$address->geocodedText = null;
- $address->geocodedPostalText = null;
$address->geoloc_choice = null;
$address->countryId = null;
$address->country = null;
// Updates the address with the geocoded information from Google Maps. Also
// cleans up the final informations.
- private function getUpdatedAddress(Address &$address, array $geocodedData, $extraLines) {
- $this->fillAddressWithGeocoding($address, $geocodedData);
- $this->formatAddress($address, $extraLines);
+ private function getUpdatedAddress(Address &$address, array $geocodedData, $extraLines, $forceLanguage) {
+ $this->fillAddressWithGeocoding($address, $geocodedData, false);
+ $this->formatAddress($address, $extraLines, $forceLanguage);
}
// Retrieves the Placemark object (see #getPlacemarkFromJson()) for the @p
// address, by querying the Google Maps API. Returns the array on success,
// and null otherwise.
- private function getPlacemarkForAddress($address) {
- $url = $this->getGeocodingUrl($address);
+ private function getPlacemarkForAddress($address, $defaultLanguage) {
+ $url = $this->getGeocodingUrl($address, $defaultLanguage);
$geoData = $this->getGeoJsonFromUrl($url);
return ($geoData ? $this->getPlacemarkFromJson($geoData) : null);
// Prepares address to be geocoded
private function prepareAddress(Address &$address) {
$address->text = preg_replace('/\s*\n\s*/m', "\n", trim($address->text));
- $address->postalText = $this->getPostalAddress($address->text);
}
// Builds the Google Maps geocoder url to fetch information about @p address.
// Returns the built url.
- private function getGeocodingUrl($address) {
+ private function getGeocodingUrl($address, $defaultLanguage) {
global $globals;
$parameters = array(
'key' => $globals->geocoder->gmaps_key,
'sensor' => 'false', // The queried address wasn't obtained from a GPS sensor.
- 'hl' => 'fr', // Output langage.
+ 'hl' => $defaultLanguage,
'oe' => 'utf8', // Output encoding.
'output' => 'json', // Output format.
- 'gl' => 'fr', // Location preferences (addresses are in France by default).
+ 'gl' => $globals->geocoder->gmaps_gl,
'q' => $address, // The queries address.
);
}
// Fills the address with the geocoded data
- private function fillAddressWithGeocoding(Address &$address, $geocodedData) {
+ private function fillAddressWithGeocoding(Address &$address, $geocodedData, $isLocal) {
// The geocoded address three is
// Country -> AdministrativeArea -> SubAdministrativeArea -> Locality -> Thoroughfare
// with all the possible shortcuts
// The address is formatted as xAL, or eXtensible Address Language, an international
// standard for address formatting.
// xAL documentation: http://www.oasis-open.org/committees/ciq/ciq.html#6
- $address->geocodedText = str_replace(', ', "\n", $geocodedData['address']);
+ if ($isLocal) {
+ $ext = 'Local';
+ } else {
+ $ext = ucfirst(Platal::globals()->geocoder->gmaps_hl);
+ $address->geocodedText = str_replace(', ', "\n", $geocodedData['address']);
+ }
+
if (isset($geocodedData['AddressDetails']['Accuracy'])) {
$address->accuracy = $geocodedData['AddressDetails']['Accuracy'];
}
$currentPosition = $geocodedData['AddressDetails'];
if (isset($currentPosition['Country'])) {
+ $country = 'country' . $ext;
$currentPosition = $currentPosition['Country'];
$address->countryId = $currentPosition['CountryNameCode'];
- $address->country = $currentPosition['CountryName'];
+ $address->$country = $currentPosition['CountryName'];
}
if (isset($currentPosition['AdministrativeArea'])) {
- $currentPosition = $currentPosition['AdministrativeArea'];
- $address->administrativeAreaName = $currentPosition['AdministrativeAreaName'];
+ $administrativeAreaName = 'administrativeAreaName' . $ext;
+ $currentPosition = $currentPosition['AdministrativeArea'];
+ $address->$administrativeAreaName = $currentPosition['AdministrativeAreaName'];
}
if (isset($currentPosition['SubAdministrativeArea'])) {
- $currentPosition = $currentPosition['SubAdministrativeArea'];
- $address->subAdministrativeAreaName = $currentPosition['SubAdministrativeAreaName'];
+ $subAdministrativeAreaName = 'subAdministrativeAreaName' . $ext;
+ $currentPosition = $currentPosition['SubAdministrativeArea'];
+ $address->$subAdministrativeAreaName = $currentPosition['SubAdministrativeAreaName'];
}
if (isset($currentPosition['Locality'])) {
- $currentPosition = $currentPosition['Locality'];
- $address->localityName = $currentPosition['LocalityName'];
- }
- if (isset($currentPosition['Thoroughfare'])) {
- $address->thoroughfareName = $currentPosition['Thoroughfare']['ThoroughfareName'];
+ $localityName = 'localityName' . $ext;
+ $currentPosition = $currentPosition['Locality'];
+ $address->$localityName = $currentPosition['LocalityName'];
}
if (isset($currentPosition['PostalCode'])) {
$address->postalCode = $currentPosition['PostalCode']['PostalCodeNumber'];
}
}
- // Formats the text of the geocoded address using the unused data and
- // compares it to the given address. If they are too different, the user
- // will be asked to choose between them.
- private function formatAddress(Address &$address, $extraLines) {
+ // Compares the geocoded address with the given address and returns true
+ // iff their are close enough to be considered as equals or not.
+ private function compareAddress($address)
+ {
$same = true;
- if ($extraLines) {
- $address->geocodedText = $extraLines . "\n" . $address->geocodedText;
- }
- $address->geocodedPostalText = $this->getPostalAddress($address->geocodedText);
$geoloc = strtoupper(preg_replace(array("/[0-9,\"'#~:;_\- ]/", "/\r\n/"),
array('', "\n"), $address->geocodedText));
$text = strtoupper(preg_replace(array("/[0-9,\"'#~:;_\- ]/", "/\r\n/"),
}
}
- if ($same) {
- $address->geocodedText = null;
- $address->geocodedPostalText = null;
- } else {
- $address->geocodedText = str_replace("\n", "\r\n", $address->geocodedText);
- $address->geocodedPostalText = str_replace("\n", "\r\n", $address->geocodedPostalText);
- }
- $address->text = str_replace("\n", "\r\n", $address->text);
- $address->postalText = str_replace("\n", "\r\n", $address->postalText);
+ return $same;
}
- // Returns the address formated for postal use.
- // The main rules are (cf AFNOR XPZ 10-011):
- // -everything in upper case;
- // -if there are more then than 38 characters in a line, split it;
- // -if there are more then than 32 characters in the description of the "street", use abbreviations.
- private function getPostalAddress($text) {
- static $abbreviations = array(
- 'IMPASSE' => 'IMP',
- 'RUE' => 'R',
- 'AVENUE' => 'AV',
- 'BOULEVARD' => 'BVD',
- 'ROUTE' => 'R',
- 'STREET' => 'ST',
- 'ROAD' => 'RD',
- );
-
- $text = strtoupper($text);
- $arrayText = explode("\n", $text);
- $postalText = '';
-
- foreach ($arrayText as $i => $line) {
- $postalText .= (($i == 0) ? '' : "\n");
- if (($length = strlen($line)) > 32) {
- $words = explode(' ', $line);
- $count = 0;
- foreach ($words as $word) {
- if (isset($abbreviations[$word])) {
- $word = $abbreviations[$word];
+ // Formats the text of the geocoded address using the unused data and
+ // compares it to the given address. If they are too different, the user
+ // will be asked to choose between them.
+ private function formatAddress(Address &$address, $extraLines, $forceLanguage)
+ {
+ if ($extraLines) {
+ $address->geocodedText = $extraLines . "\n" . $address->geocodedText;
+ }
+
+ if ($this->compareAddress($address)) {
+ $address->geocodedText = null;
+ } elseif (!$forceLanguage) {
+ $languages = XDB::fetchOneCell('SELECT IF(ISNULL(gc1.belongsTo), gl1.language, gl2.language)
+ FROM geoloc_countries AS gc1
+ INNER JOIN geoloc_languages AS gl1 ON (gc1.iso_3166_1_a2 = gl1.iso_3166_1_a2)
+ LEFT JOIN geoloc_countries AS gc2 ON (gc1.belongsTo = gc2.iso_3166_1_a2)
+ LEFT JOIN geoloc_languages AS gl2 ON (gc2.iso_3166_1_a2 = gl2.iso_3166_1_a2)
+ WHERE gc1.iso_3166_1_a2 = {?}',
+ $address->countryId);
+ $toGeocode = substr($address->text, strlen($extraLines));
+ foreach (explode(',', $languages) as $language) {
+ if ($language != Platal::globals()->geocoder->gmaps_hl) {
+ $geocodedData = $this->getPlacemarkForAddress($toGeocode, $language);
+ $address->geocodedText = str_replace(', ', "\n", $geocodedData['address']);
+ if ($extraLines) {
+ $address->geocodedText = $extraLines . "\n" . $address->geocodedText;
}
- if ($count + ($wordLength = strlen($word)) <= 38) {
- $postalText .= (($count == 0) ? '' : ' ') . $word;
- $count += (($count == 0) ? 0 : 1) + $wordLength;
- } else {
- $postalText .= "\n" . $word;
- $count = strlen($word);
+ if ($this->compareAddress($address)) {
+ $this->fillAddressWithGeocoding($address, $geocodedData, true);
+ $address->geocodedText = null;
+ break;
}
}
- } else {
- $postalText .= $line;
}
+ $address->geocodedText = str_replace("\n", "\r\n", $address->geocodedText);
}
- return $postalText;
+ $address->text = str_replace("\n", "\r\n", $address->text);
}
// Trims the name of the real country if it contains an ISO 3166-1 non-country
// all non-country items of ISO 3166-1.
private function getTextToGeocode($text)
{
- $res = XDB::iterator('SELECT country, countryFR
+ $res = XDB::iterator('SELECT countryEn, country
FROM geoloc_countries
WHERE belongsTo IS NOT NULL');
$countries = array();
$countLines = count($textLines);
$needle = strtoupper(trim($textLines[$countLines - 2]));
$isPseudoCountry = false;
- foreach ($countries as $country) {
- if (strtoupper($country) == $needle) {
- $isPseudoCountry = true;
- break;
+ if ($needle) {
+ foreach ($countries as $country) {
+ if (strtoupper($country) === $needle) {
+ $isPseudoCountry = true;
+ break;
+ }
}
}
// The following fields are the fields of the form in the profile edition.
private $type = 'fixed';
public $display = '';
- private $pub = 'private';
+ public $pub = 'ax';
public $comment = '';
private $error = false;
private function toString()
{
- return 'type : ' . $this->type .', numéro : ' . $this->display
- . ', commentaire : « ' . $this->comment . ' », affichage : ' . $this->pub;
+ static $pubs = array('public' => 'publique', 'ax' => 'annuaire AX', 'private' => 'privé');
+ static $types = array('fax' => 'fax', 'fixed' => 'fixe', 'mobile' => 'mobile');
+ return $this->display . ' (' . $types[$this->type] . (($this->comment) ? ', commentaire : « ' . $this->comment . ' »' : '')
+ . ', affichage ' . $pubs[$this->pub] . ')';
}
private function isEmpty()
$this->pid, $this->link_type, $this->link_id, $this->id);
}
- static public function deletePhones($pid, $link_type, $link_id = null)
+ static public function deletePhones($pid, $link_type, $link_id = null, $deletePrivate = true)
{
$where = '';
if (!is_null($link_id)) {
$where = XDB::format(' AND link_id = {?}', $link_id);
}
XDB::execute('DELETE FROM profile_phones
- WHERE pid = {?} AND link_type = {?}' . $where,
+ WHERE pid = {?} AND link_type = {?}' . $where . (($deletePrivate) ? '' : ' AND pub IN (\'public\', \'ax\')'),
$pid, $link_type);
}
}
}
- static private function formArrayWalk(array $data, $function, &$success = true, $requiresEmptyPhone = false)
+ static private function formArrayWalk(array $data, $function, &$success = true, $requiresEmptyPhone = false, $maxPublicity = null)
{
$phones = array();
foreach ($data as $item) {
$phone = new Phone($item);
$success = (!$phone->error && ($phone->format() || $phone->isEmpty()) && $success);
if (!$phone->isEmpty()) {
+ if (!is_null($maxPublicity) && $maxPublicity->isVisible($phone->pub)) {
+ $phone->pub = $maxPublicity->level();
+ }
$phones[] = call_user_func(array($phone, $function));
}
}
if (count($phones) == 0 && $requiresEmptyPhone) {
$phone = new Phone();
+ if (!is_null($maxPublicity) && $maxPublicity->isVisible($phone->pub)) {
+ $phone->pub = $maxPublicity->level();
+ }
$phones[] = call_user_func(array($phone, $function));
}
return $phones;
}
// Formats an array of form phones into an array of form formatted phones.
- static public function formatFormArray(array $data, &$success = true)
+ static public function formatFormArray(array $data, &$success = true, $maxPublicity = null)
{
- return self::formArrayWalk($data, 'toFormArray', $success, true);
+ return self::formArrayWalk($data, 'toFormArray', $success, true, $maxPublicity);
}
static public function formArrayToString(array $data)
{
- return implode(' ; ', self::formArrayWalk($data, 'toString'));
+ return implode(', ', self::formArrayWalk($data, 'toString'));
}
static public function iterate(array $pids = array(), array $link_types = array(),
const FETCH_ALL = 0x0007FF; // OR of FETCH_*
+ static public $descriptions = array(
+ 'search_names' => 'Noms',
+ 'nationality1' => 'Nationalité',
+ 'nationality2' => '2e nationalité',
+ 'nationality3' => '3e nationalité',
+ 'promo_display' => 'Promotion affichée',
+ 'email_directory' => 'Email annuaire papier',
+ 'networking' => 'Messageries…',
+ 'tels' => 'Téléphones',
+ 'edus' => 'Formations',
+ 'promo' => 'Promotion de sortie',
+ 'birthdate' => 'Date de naissance',
+ 'yourself' => 'Nom affiché',
+ 'freetext' => 'Commentaire',
+ 'freetext_pub' => 'Affichage du commentaire',
+ 'photo' => 'Photographie',
+ 'photo_pub' => 'Affichage de la photographie',
+ 'addresses' => 'Adresses',
+ 'corps' => 'Corps',
+ 'cv' => 'CV',
+ 'jobs' => 'Emplois',
+ 'section' => 'Section',
+ 'binets' => 'Binets',
+ 'medals' => 'Décorations',
+ 'medals_pub' => 'Affichage des décorations',
+ 'competences' => 'Compétences',
+ 'langues' => 'Langues',
+ 'expertise' => 'Expertises (mentoring)',
+ 'terms' => 'Compétences (mentoring)',
+ 'countries' => 'Pays (mentoring)'
+ );
+
private $fetched_fields = 0x000000;
private $pid;
{
if ($this->has_photo) {
if ($data && ($this->photo == null || $this->photo->mimeType == null)) {
- $res = XDB::fetchOneAssoc('SELECT attach, attachmime, x, y
+ $res = XDB::fetchOneAssoc('SELECT attach, attachmime, x, y, last_update
FROM profile_photos
WHERE pid = {?}', $this->pid);
- $this->photo = PlImage::fromData($res['attach'], $res['attachmime'], $res['x'], $res['y']);
+ $this->photo = PlImage::fromData($res['attach'], 'image/' .$res['attachmime'], $res['x'], $res['y'], $res['last_update']);
} else if ($this->photo == null) {
$this->photo = PlImage::fromData(null, null, $this->photo_width, $this->photo_height);
}
return $this->photo;
} else if ($fallback) {
- return PlImage::fromFile(dirname(__FILE__).'/../htdocs/images/none.png',
- 'image/png');
+ if ($this->mainEducation() == 'X') {
+ return PlImage::fromFile(dirname(__FILE__) . '/../htdocs/images/none_x.png', 'image/png');
+ }
+ return PlImage::fromFile(dirname(__FILE__) . '/../htdocs/images/none_md.png', 'image/png');
}
return null;
}
// {{{ class UFC_SchoolId
/** Filters users based on their shoold identifier
* @param type Parameter type (Xorg, AX, School)
- * @param value School id value
+ * @param value Array of school ids
*/
class UFC_SchoolId implements UserFilterCondition
{
}
}
- public function __construct($type, $id)
+ /** Construct a UFC_SchoolId
+ * The first argument is the type, all following arguments can be either ids
+ * or arrays of ids to use:
+ * $ufc = new UFC_SchoolId(UFC_SchoolId::AX, $id1, $id2, array($id3, $id4));
+ */
+ public function __construct($type)
{
$this->type = $type;
- $this->id = $id;
+ $ids = func_get_args();
+ array_shift($ids);
+ $this->ids = pl_flatten($ids);
self::assertType($type);
}
public function buildCondition(PlFilter &$uf)
{
$uf->requireProfiles();
- $id = $this->id;
+ $ids = $this->ids;
$type = $this->type;
if ($type == self::School) {
$type = self::Xorg;
- $id = Profile::getXorgId($id);
+ $ids = array_map(array('Profile', 'getXorgId'), $ids);
}
- return XDB::format('p.' . $type . '_id = {?}', $id);
+ return XDB::format('p.' . $type . '_id IN {?}', $ids);
}
}
// }}}
return $this->getUsers($limit);
}
+ public function getIds($limit = null)
+ {
+ return $this->getUIDs();
+ }
public function getTotalCount()
{
return $this->getProfiles($limit);
}
+ public function getIds($limit = null)
+ {
+ return $this->getPIDs();
+ }
+
public function filter(array $profiles, $limit = null)
{
return $this->filterProfiles($profiles, self::defaultLimit($limit));
; URL of geocoding webservice
gmaps_url = "http://maps.google.com/maps/geo"
+; $globals->geocoder->gmaps_hl
+; Default output language.
+gmaps_hl = "fr"
+
+; $globals->geocoder->gmaps_gl
+; Default location preference.
+gmaps_gl = "fr"
; The lists section contains parameters used to interact with mailman.
[Lists]
-Subproject commit 798c1f4b15f14569c1f37d848db93ec4f65518b6
+Subproject commit 80c3b5792bea15876ef8f79b8a64421733c1c001
}
break;
case 'emploi':
- if ($('#job_0').find("[name='jobs[0][name]']").val() == '') {
+ if ($('#jobs_0').find("[name='jobs[0][name]']").val() == '') {
registerEnterpriseAutocomplete(0);
}
break;
var subgrades;
var names;
+// Publicity follows the following ordering: private < ax < public.
+var publicity = [];
+publicity['private'] = 0;
+publicity['ax'] = 1;
+publicity['public'] = 2;
+
// Names {{{1
function toggleNamesAdvanced()
{
if (geoloc == 1) {
$('#' + prefid + '_cont').find('[name*=text]').val($('#' + prefid + '_cont').find('[name*=geocodedText]').val());
- $('#' + prefid + '_cont').find('[name*=postalText]').val($('#' + prefid + '_cont').find('[name*=geocodedPostalText]').val());
+ $('#' + prefid + '_cont').find('[name*=postalText]').val('');
}
if (geoloc > 0) {
$('#' + prefid + '_cont').find("[name*='[geocodedText]']").remove();
- $('#' + prefid + '_cont').find("[name*='[geocodedPostalText]']").remove();
}
$('#' + prefid + '_cont').find('[name*=text]').removeClass('error');
$('#' + prefid + '_cont').find('[name*=geocodeChosen]').val(geoloc);
// {{{1 Phones
-function addTel(prefid, prefname)
+function addTel(prefid, prefname, subField, mainField, mainId)
{
var i = 0;
var prefix = prefid + '_';
i++;
}
$('#' + prefix + 'add').before('<div id="' + prefix + i + '" style="clear: both; padding-top: 4px; padding-bottom: 4px"></div>');
- Ajax.update_html(prefix + i, 'profile/ajax/tel/' + prefid + '/' + prefname + '/' + i);
+ Ajax.update_html(prefix + i, 'profile/ajax/tel/' + prefid + '/' + prefname + '/' + i + '/' + subField + '/' + mainField + '/' + mainId);
}
function removeTel(prefname, prefid, id)
function addJob()
{
var i = 0;
- while ($('#job_' + i).length != 0) {
+ while ($('#jobs_' + i).length != 0) {
++i;
}
$.get(platal_baseurl + 'profile/ajax/job/' + i, makeAddJob(i));
jobid = '';
formvarname = 'terms';
} else {
- parentpath = '#job_'+jobid+' ';
+ parentpath = '#jobs_'+jobid+' ';
formvarname = 'jobs['+jobid+'][terms]';
}
- var lastJobTerm = $(parentpath + '.job_term:last');
+ var lastJobTerm = $(parentpath + '.jobs_term:last');
if (lastJobTerm.length != 0) {
termid = parseInt(lastJobTerm.children('input').attr('name').replace(/^(jobs\[[0-9]+\]\[terms\]|terms)\[([0-9]+)\]\[jtid\]/, '$2')) + 1;
if ($('#job'+jobid+'_term'+jtid).length > 0) {
return false;
}
}
- var newdiv = '<div class="job_term" id="job'+jobid+'_term'+jtid+'">'+
+ var newdiv = '<div class="jobs_term" id="job'+jobid+'_term'+jtid+'">'+
'<span>'+full_name+'</span>'+
'<input type="hidden" name="'+formvarname+'['+termid+'][jtid]" value="'+jtid+'" />'+
'<img title="Retirer ce mot-clef" alt="retirer" src="images/icons/cross.gif" />'+
'</div>';
if (lastJobTerm.length == 0) {
- $(parentpath + '.job_terms').prepend(newdiv);
+ $(parentpath + '.jobs_terms').prepend(newdiv);
} else {
lastJobTerm.after(newdiv);
}
if (jobid < 0) {
search_input = $('.term_search')[0];
} else {
- search_input = $('#job_'+jobid+' .term_search')[0];
+ search_input = $('#jobs_'+jobid+' .term_search')[0];
}
if (li.extra[0] >= 0) {
search_input.value = '';
if (jobid < 0) {
treepath = '';
} else {
- treepath = '#job_'+jobid+' ';
+ treepath = '#jobs_'+jobid+' ';
}
treepath += '.term_tree';
if ($(treepath + ' ul').length > 0) {
updateElement(cat);
}
+function updateSubPublicity(subFieldId, name, mainPub)
+{
+ var subPub = $(subFieldId).find("[name='" + name + "']:checked").val();
+ if (publicity[subPub] > publicity[mainPub]) {
+ $(subFieldId).find("[name='" + name + "']:checked").removeAttr('checked');
+ $(subFieldId).find('[value=' + mainPub + ']').attr('checked', 'checked');
+ }
+}
+
+function updatePublicity(mainField, mainId, subField, subId)
+{
+ var mainFieldId = '#' + mainField + '_' + mainId;
+ var mainPub = $(mainFieldId).find("[name='" + mainField + "[" + mainId + "][pub]']:checked").val();
+ if (subId == -1) {
+ var subFields = subField.split(',');
+ for (var i =0; i < subFields.length; ++i) {
+ var subFieldBaseId = mainFieldId + '_' + subFields[i];
+ var name = mainField + '[' + mainId + '][' + subFields[i] + ']';
+ if ($(subFieldBaseId).length != 0) {
+ updateSubPublicity(subFieldBaseId, name + '[pub]', mainPub);
+ updateSubPublicity(subFieldBaseId, mainField + '[' + mainId + '][' + subFields[i] + '_pub]', mainPub);
+ }
+ subId = 0;
+ while ($(subFieldBaseId + '_' + subId).length != 0) {
+ updateSubPublicity(subFieldBaseId + '_' + subId, name + '[' + subId + '][pub]', mainPub);
+ ++subId;
+ }
+ }
+ } else {
+ if (subId == '') {
+ updateSubPublicity(mainFieldId + '_' + subField, mainField + '[' + mainId + '][' + subField + '_pub]', mainPub);
+ updateSubPublicity(mainFieldId + '_' + subField, mainField + '[' + mainId + '][' + subField + '][pub]', mainPub);
+ } else {
+ updateSubPublicity(mainFieldId + '_' + subField + '_' + subId, mainField + '[' + mainId + '][' + subField + '][' + subId + '][pub]', mainPub);
+ }
+ }
+}
+
// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
function education_options($current = 0)
{
$html = '<option value="-1"> </option>';
- $res = XDB::iterator("SELECT e.id AS id, gc.countryFR AS country,
+ $res = XDB::iterator("SELECT e.id AS id, gc.country,
IF(CHAR_LENGTH(e.name) > 76, e.abbreviation, e.name) AS name
FROM profile_education_enum AS e
LEFT JOIN geoloc_countries AS gc ON (e.country = gc.iso_3166_1_a2)
WHERE EXISTS (SELECT *
FROM profile_education_degree AS d
WHERE e.id = d.eduid)
- ORDER BY gc.countryFR, e.name");
+ ORDER BY gc.country, e.name");
$country = "";
while ($arr_edu = $res->next()) {
if ($arr_edu["country"] != $country) {
$has_new = false;
foreach ($sn_new as $typeid => $sn) {
if (isset($sn['pub'])) {
- if (isset($sn_old[$typeid]) && ($sn_old[$typeid]['fullname'] == $sn['fullname'] && $update_new)) {
+ if (isset($sn_old[$typeid]) && $update_new) {
XDB::execute("UPDATE profile_name
SET particle = {?}, name = {?}, typeid = {?}
WHERE id = {?} AND pid = {?}",
$sn['particle'], $sn['name'], $typeid, $sn_old[$typeid]['id'], $pid);
unset($sn_old[$typeid]);
- } elseif ($update_new
- || (isset($sn_old[$typeid]) && compare_basename($sn_old[$typeid]['fullname'], $sn['fullname']))) {
- XDB::execute("INSERT INTO profile_name (particle, name, typeid, pid)
- VALUES ({?}, {?}, {?}, {?})",
- $sn['particle'], $sn['name'], $typeid, $pid);
- unset($sn_old[$typeid]);
} else {
$has_new = true;
}
return $user->profile()->last_change;
}
- static private $descriptions = array('search_names' => 'L\'un de ses noms',
- 'freetext' => 'Le texte libre',
- 'mobile' => 'Son numéro de téléphone portable',
- 'nationalite' => 'Sa nationalité',
- 'nationalite2' => 'Sa seconde nationalité',
- 'nationalite3' => 'Sa troisième nationalité',
- 'nick' => 'Son surnom',
- 'networking' => 'La liste de ses adresses de networking',
- 'edus' => 'Ses formations',
- 'addresses' => 'Ses adresses',
- 'section' => 'Sa section sportive',
- 'binets' => 'La liste de ses binets',
- 'medals' => 'Ses décorations',
- 'cv' => 'Son Curriculum Vitae',
- 'corps' => 'Son Corps d\'État',
- 'jobs' => 'Ses informations professionnelles',
- 'photo' => 'Sa photographie');
public function getData(PlUser &$user)
{
$data = XDB::fetchColumn("SELECT field
} else {
$text = array();
foreach ($data as $f) {
- $text[] = self::$descriptions[$f];
+ $text[] = Profile::$descriptions[$f];
}
return $text;
}
}
$this->company = CompanyList::get($this->jobid);
if (is_null($this->company)) {
- $entreprise = ProfileValidate::get_typed_requests($this->pid, 'entreprise');
- $this->company = new Company(array('name' => $entreprise[$this->id]->name));
+ $entreprises = ProfileValidate::get_typed_requests($this->pid, 'entreprise');
+ foreach ($entreprises as $entreprise) {
+ if ($entreprise->id == $this->id) {
+ $this->company = new Company(array('name' => $entreprise->name));
+ }
+ }
}
}
$data = XDB::iterator('SELECT pe.id, pe.pid,
pe.entry_year, pe.grad_year, pe.program, pe.flags,
pee.name AS school, pee.abbreviation AS school_short,
- pee.url AS school_url, gc.countryFR AS country,
+ pee.url AS school_url, gc.country,
pede.degree, pede.abbreviation AS degree_short, pede.level AS degree_level,
pefe.field
FROM profile_education AS pe
public static function fetchData(array $pids, ProfileVisibility $visibility)
{
- $data = XDB::iterator('SELECT pmc.pid, pmc.country AS id, gc.countryFR AS name
+ $data = XDB::iterator('SELECT pmc.pid, pmc.country AS id, gc.country AS name
FROM profile_mentor_country AS pmc
LEFT JOIN geoloc_countries AS gc ON (gc.iso_3166_1_a2 = pmc.country)
WHERE pmc.pid IN {?}
if (!array_key_exists($id, self::$companies)) {
self::preload();
}
- return self::$companies[$id];
+ if (isset(self::$companies[$id])) {
+ return self::$companies[$id];
+ }
+ return null;
}
}
{
$fields = array(
new UFBF_Quick('quick', 'Recherche rapide'),
+ new UFBF_NotRegistered('nonins', 'Non inscrits'),
);
parent::__construct($fields, $envprefix);
}
// {{{ class UFB_AdvancedSearch
class UFB_AdvancedSearch extends UserFilterBuilder
{
- public function __construct($envprefix = '')
+ /** Create a UFB_AdvancedSearch.
+ * @param $include_admin Whether to include 'admin-only' fields
+ * @param $include_ax Whether to include 'ax-only' fields
+ * @param $envprefix Optional prefix for form field names.
+ */
+ public function __construct($include_admin = false, $include_ax = false, $envprefix = '')
{
$fields = array(
new UFBF_Name('name', 'Nom'),
new UFBF_Mentor('only_referent', 'Référent'),
);
+
+ if ($include_admin || $include_ax) {
+ $fields[] = new UFBF_SchoolIds('schoolid_ax', 'Matricule AX', UFC_SchoolId::AX);
+ }
+
parent::__construct($fields, $envprefix);
}
}
}
// }}}
+// {{{ class UFBF_SchoolIds
+class UFBF_SchoolIds extends UFB_Field
+{
+ // One of UFC_SchoolId types
+ protected $type;
+
+ public function __construct($envfield, $formtext, $type = UFC_SchoolId::AX)
+ {
+ parent::__construct($envfield, $formtext);
+ $this->type = $type;
+ }
+
+ protected function check(UserFilterBuilder &$ufb)
+ {
+ if ($ufb->blank($this->envfield)) {
+ $this->empty = true;
+ return true;
+ }
+
+ $value = $ufb->t($this->envfield);
+ $values = explode("\n", $value);
+ $ids = array();
+ foreach ($values as $val) {
+ if (preg_match('/^[0-9A-Z]{0,8}$/', $val)) {
+ $ids[] = $val;
+ }
+ }
+ if (count($ids) == 0) {
+ return $this->raise("Le champ %s ne contient aucune valeur valide.");
+ }
+
+ $this->val = $ids;
+ return true;
+ }
+
+ protected function buildUFC(UserFilterBuilder &$ufb)
+ {
+ return new UFC_SchoolId($this->type, $this->val);
+ }
+}
+// }}}
+
// {{{ class UFBF_Name
class UFBF_Name extends UFBF_Text
{
}
// }}}
+// {{{ class UFBF_NotRegistered
+// Simple field for selecting only alive, not registered users (for quick search)
+class UFBF_NotRegistered extends UFBF_Bool
+{
+ protected function buildUFC(UserFilterBuilder &$ufb)
+ {
+ if ($this->val) {
+ return new PFC_And(
+ new PFC_Not(new UFC_Dead()),
+ new PFC_Not(new UFC_Registered())
+ );
+ }
+ }
+}
+// }}}
+
// {{{ class UFBF_Registered
class UFBF_Registered extends UFBF_Enum
{
}
}
+require_once "ufbuilder.inc.php";
+
class SearchSet extends ProfileSet
{
- public $advanced = false;
- private $score = null;
- private $quick = false;
- private $valid = true;
+ protected $score = null;
+ protected $valid = true;
- public function __construct($quick = false, PlFilterCondition $cond = null)
+ public function __construct(UserFilterBuilder &$ufb, PlFilterCondition $cond = null)
{
- if ($no_search) {
- return;
- }
-
- $this->quick = $quick;
-
if (is_null($cond)) {
$conds = new PFC_And();
} else if ($cond instanceof PFC_And) {
$conds = new PFC_And($cond);
}
- if ($quick) {
- $this->getQuick($conds);
- } else {
- $this->getAdvanced($conds);
- }
- }
-
- public function isValid()
- {
- return $this->valid;
- }
-
- /** Sets up the conditions for a Quick Search
- * @param $conds Additional conds (as a PFC_And)
- */
- private function getQuick($conds)
- {
- if (!S::logged()) {
- Env::kill('with_soundex');
- }
-
- require_once 'ufbuilder.inc.php';
- $ufb = new UFB_QuickSearch();
-
if (!$ufb->isValid()) {
$this->valid = false;
return;
$orders = $ufb->getOrders();
- if (S::logged() && Env::has('nonins')) {
- $conds = new PFC_And($conds,
- new PFC_Not(new UFC_Dead()),
- new PFC_Not(new UFC_Registered())
- );
- }
-
parent::__construct($conds, $orders);
}
- /** Sets up the conditions for an Advanced Search
- * @param $conds Additional conds (as a PFC_And)
- */
- private function getAdvanced($conds)
+ public function isValid()
{
- $this->advanced = true;
- require_once 'ufbuilder.inc.php';
- $ufb = new UFB_AdvancedSearch();
-
- if (!$ufb->isValid()) {
- $this->valid = false;
- return;
- }
-
- $ufc = $ufb->getUFC();
- $conds->addChild($ufc);
-
- $orders = $ufb->getOrders();
-
- parent::__construct($conds, $orders);
+ return $this->valid;
}
/** Add a "rechercher=Chercher" field to the query to simulate the POST
}
}
+// Specialized SearchSet for quick search.
+class QuickSearchSet extends SearchSet
+{
+ public function __construct(PlFilterCondition $cond = null)
+ {
+ if (!S::logged()) {
+ Env::kill('with_soundex');
+ }
+
+ parent::__construct(new UFB_QuickSearch(), $cond);
+ }
+}
+
+// Specialized SearchSet for advanced search.
+class AdvancedSearchSet extends SearchSet
+{
+ public function __construct($xorg_admin_fields, $ax_admin_fields,
+ PlFilterCondition $cond = null)
+ {
+ parent::__construct(new UFB_AdvancedSearch($xorg_admin_fields, $ax_admin_fields),
+ $cond);
+ }
+}
+
/** Simple set based on an array of User objects
*/
class ArraySet extends ProfileSet
}
}
+class AddressesView implements PlView
+{
+ private $set;
+
+ public function __construct(PlSet &$set, array $params)
+ {
+ $this->set =& $set;
+ }
+
+ public function apply(PlPage &$page)
+ {
+ $pids = $this->set->getIds(new PlLimit());
+ $visibility = new ProfileVisibility(ProfileVisibility::VIS_AX);
+ pl_cached_content_headers('text/x-csv', 1);
+
+ $csv = fopen('php://output', 'w');
+ fputcsv($csv, array('adresses'), ';');
+ $res = XDB::query('SELECT pd.public_name, pa.postalText
+ FROM profile_addresses AS pa
+ INNER JOIN profile_display AS pd ON (pd.pid = pa.pid)
+ WHERE pa.type = \'home\' AND pa.pub IN (\'public\', \'ax\') AND FIND_IN_SET(\'mail\', pa.flags) AND pa.pid IN {?}
+ GROUP BY pa.pid', $pids);
+ foreach ($res->fetchAllAssoc() as $item) {
+ fputcsv($csv, $item, ';');
+ }
+ fclose($csv);
+ exit();
+ }
+
+ public function args()
+ {
+ return $this->set->args();
+ }
+}
+
// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
?>
// Validations rules: comments for administrators.
public $rules = 'Mieux vaut laisser une demande de validation à un autre administrateur que de valider une requête illégale ou que de refuser une demande légitime.';
+ // Unless differently stated, a validation must be done by a site administrator.
+ public $requireAdmin = true;
+
// }}}
// {{{ constructor
*/
public function handle_formu()
{
+ if ($this->requireAdmin && !S::admin()) {
+ $this->trigError('Vous n\'avez pas les permissions nécessaires pour valider cette demande.');
+ return false;
+ }
+
if (Env::has('delete')) {
$this->clean();
$this->trigSuccess('Requête supprimée.');
{
$res = XDB::iterRow('SELECT data
FROM requests
- WHERE pid = {?} and type = {?}',
+ WHERE pid = {?} and type = {?}
+ ORDER BY stamp',
$pid, $type);
$array = array();
while (list($data) = $res->next()) {
public $suggestions;
public $rules = 'Si l\'entreprise est déjà présente sous un autre nom dans la liste des suggestions, remplacer son nom par celui-ci avant de valider. Laisser les autres champs tels quels.';
+ public $requireAdmin = false;
+
// }}}
// {{{ constructor
'admin/skins' => $this->make_hook('skins', AUTH_MDP, 'admin'),
'admin/user' => $this->make_hook('user', AUTH_MDP, 'admin'),
'admin/add_accounts' => $this->make_hook('add_accounts', AUTH_MDP, 'admin'),
- 'admin/validate' => $this->make_hook('validate', AUTH_MDP, 'admin'),
+ 'admin/validate' => $this->make_hook('validate', AUTH_MDP, 'admin,edit_directory'),
'admin/validate/answers' => $this->make_hook('validate_answers', AUTH_MDP, 'admin'),
'admin/wiki' => $this->make_hook('wiki', AUTH_MDP, 'admin'),
'admin/ipwatch' => $this->make_hook('ipwatch', AUTH_MDP, 'admin'),
'admin/accounts' => $this->make_hook('accounts', AUTH_MDP, 'admin'),
'admin/account/watch' => $this->make_hook('account_watch', AUTH_MDP, 'admin'),
'admin/account/types' => $this->make_hook('account_types', AUTH_MDP, 'admin'),
- 'admin/jobs' => $this->make_hook('jobs', AUTH_MDP, 'admin'),
+ 'admin/jobs' => $this->make_hook('jobs', AUTH_MDP, 'admin,edit_directory'),
+ 'admin/profile' => $this->make_hook('profile', AUTH_MDP, 'admin,edit_directory')
);
}
global $globals;
$globals->updateNbValid();
$page->assign('vit', Validate::iterate());
+ $page->assign('isAdmin', S::admin());
}
function handler_validate_answers(&$page, $action = 'list', $id = null)
'link_type' => Phone::LINK_COMPANY, 'pub' => 'public'));
$fax = new Phone(array('display' => Env::v('fax'), 'link_id' => $id, 'id' => 1, 'type' => 'fax',
'link_type' => Phone::LINK_COMPANY, 'pub' => 'public'));
- $address = new Address(array('jobid' => $jobid, 'type' => Address::LINK_COMPANY, 'text' => Env::t('address')));
+ $address = new Address(array('jobid' => $id, 'type' => Address::LINK_COMPANY, 'text' => Env::t('address')));
$phone->save();
$fax->save();
$address->save();
}
}
}
+
+ function handler_profile(&$page)
+ {
+ $page->changeTpl('admin/profile.tpl');
+
+ if (Post::has('checked')) {
+ S::assert_xsrf_token();
+ $res = XDB::iterator('SELECT DISTINCT(pm.pid), pd.public_name
+ FROM profile_modifications AS pm
+ INNER JOIN profile_display AS pd ON (pm.pid = pd.pid)
+ WHERE pm.type = \'self\'');
+
+ while ($profile = $res->next()) {
+ if (Post::has('checked_' . $profile['pid'])) {
+ XDB::execute('DELETE FROM profile_modifications
+ WHERE type = \'self\' AND pid = {?}', $profile['pid']);
+
+ $page->trigSuccess('Profil de ' . $profile['public_name'] . ' vérifié.');
+ }
+ }
+ }
+
+ $res = XDB::iterator('SELECT p.hrpid, pm.pid, pd.directory_name, GROUP_CONCAT(pm.field SEPARATOR \', \') AS field
+ FROM profile_modifications AS pm
+ INNER JOIN profiles AS p ON (pm.pid = p.pid)
+ INNER JOIN profile_display AS pd ON (pm.pid = pd.pid)
+ WHERE pm.type = \'self\'
+ GROUP BY pd.directory_name
+ ORDER BY pd.directory_name');
+ $page->assign('updates', $res);
+ }
}
// vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:
}
if ($search && trim(Env::v('quick'))) {
$base = 'carnet/contacts/search';
- $view = new SearchSet(true, new UFC_Contact($user));
+ $view = new QuickSearchSet(new UFC_Contact($user));
} else {
$base = 'carnet/contacts';
$view = new ProfileSet(new UFC_Contact($user));
if ($list == '') {
$page->trigError('La liste est vide.');
} else {
- global $platal;
-
$broken_user_list = array();
$broken_list = explode("\n", $list);
sort($broken_list);
if (!empty($x['nb_mails'])) {
$mail = new PlMailer('emails/broken.mail.tpl');
$mail->addTo("\"{$x['full_name']}\" <{$x['alias']}@"
- . $globals->mail->domain . '>');
+ . Platal::globals()->mail->domain . '>');
$mail->assign('x', $x);
$mail->assign('email', $email);
$mail->send();
// Output the list of users with recently broken addresses,
// along with the count of valid redirections.
require_once 'notifs.inc.php';
- pl_content_headers("text/x-csv");
+ pl_cached_content_headers('text/x-csv', 1);
$csv = fopen('php://output', 'w');
- fputcsv($csv, array('nom', 'promo', 'alias', 'bounce', 'nbmails', 'url'), ';');
+ fputcsv($csv, array('nom', 'promo', 'alias', 'bounce', 'nbmails', 'url', 'corps', 'job', 'networking'), ';');
foreach ($broken_user_list as $alias => $mails) {
$sel = Xdb::query(
- "SELECT acc.uid, count(e.email) AS nb_mails,
+ "SELECT acc.uid, count(DISTINCT(e.email)) AS nb_mails,
IFNULL(pd.public_name, acc.full_name) AS fullname,
- IFNULL(pd.promo, 0) AS promo
- FROM aliases AS a
- INNER JOIN accounts AS acc ON (a.uid = acc.uid)
- LEFT JOIN emails AS e ON (e.uid = acc.uid
- AND FIND_IN_SET('active', e.flags) AND e.panne = 0)
- LEFT JOIN account_profiles AS ap ON (acc.uid = ap.uid AND FIND_IN_SET('owner', ap.perms))
- LEFT JOIN profile_display AS pd ON (pd.pid = ap.pid)
+ IFNULL(pd.promo, 0) AS promo, IFNULL(pce.name, 'Aucun') AS corps,
+ IFNULL(pje.name, 'Aucun') AS job, GROUP_CONCAT(pn.address SEPARATOR ', ') AS networking
+ FROM aliases AS a
+ INNER JOIN accounts AS acc ON (a.uid = acc.uid)
+ LEFT JOIN emails AS e ON (e.uid = acc.uid
+ AND FIND_IN_SET('active', e.flags) AND e.panne = 0)
+ LEFT JOIN account_profiles AS ap ON (acc.uid = ap.uid AND FIND_IN_SET('owner', ap.perms))
+ LEFT JOIN profile_display AS pd ON (pd.pid = ap.pid)
+ LEFT JOIN profile_corps AS pc ON (pc.pid = ap.pid)
+ LEFT JOIN profile_corps_enum AS pce ON (pc.current_corpsid = pce.id)
+ LEFT JOIN profile_job AS pj ON (pj.pid = ap.pid)
+ LEFT JOIN profile_job_enum AS pje ON (pj.jobid = pje.id)
+ LEFT JOIN profile_networking AS pn ON (pn.pid = ap.pid)
WHERE a.alias = {?}
GROUP BY acc.uid", $alias);
}
fputcsv($csv, array($x['fullname'], $x['promo'], $alias,
join(',', $mails), $x['nb_mails'],
- 'https://www.polytechnique.org/marketing/broken/' . $alias), ';');
+ 'https://www.polytechnique.org/marketing/broken/' . $alias,
+ $x['corps'], $x['job'], $x['networking']), ';');
}
}
fclose($csv);
'fusionax/deceased' => $this->make_hook('deceased', AUTH_MDP, 'admin'),
'fusionax/promo' => $this->make_hook('promo', AUTH_MDP, 'admin'),
'fusionax/names' => $this->make_hook('names', AUTH_MDP, 'admin'),
- 'fusionax/edu' => $this->make_hook('edu', AUTH_MDP, 'admin')
+ 'fusionax/edu' => $this->make_hook('edu', AUTH_MDP, 'admin'),
+ 'fusionax/corps' => $this->make_hook('corps', AUTH_MDP, 'admin')
);
} elseif (Platal::globals()->merge->state == 'done') {
return array(
} else {
// séparation de l'archive en fichiers par tables
$file = $spoolpath . $file;
- // Removes master and doctorate students
- exec('grep -v "^[A-Z]\{2\}.[0-9]\{4\}[MD][0-9]\{3\}" ' . $file . ' > ' . $file . '.tmp');
- exec('mv -f ' . $file . '.tmp ' . $file);
// Split export into specialised files
exec('grep "^AD" ' . $file . ' > ' . $spoolpath . 'Adresses.txt');
exec('grep "^AN" ' . $file . ' > ' . $spoolpath . 'Anciens.txt');
+ exec('grep "^FO.[0-9]\{4\}[MD][0-9]\{3\}.Etudiant" ' . $file . ' > ' . $spoolpath . 'Formations_MD.txt');
+ exec('grep "^FO.[0-9]\{4\}[MD][0-9]\{3\}.Doct. de" ' . $file . ' >> ' . $spoolpath . 'Formations_MD.txt');
exec('grep "^FO" ' . $file . ' > ' . $spoolpath . 'Formations.txt');
exec('grep "^AC" ' . $file . ' > ' . $spoolpath . 'Activites.txt');
exec('grep "^EN" ' . $file . ' > ' . $spoolpath . 'Entreprises.txt');
exec($modulepath . 'formation.pl');
exec('mv -f ' . $spoolpath . 'Formations_out.txt ' . $spoolpath . 'Formations.txt');
+ exec('mv -f ' . $spoolpath . 'Formations_MD_out.txt ' . $spoolpath . 'Formations_MD.txt');
$report[] = 'Fichier parsé.';
$report[] = 'Import dans la base en cours...';
$next = 'integrateSQL';
1 => 'Adresses.sql',
2 => 'Anciens.sql',
3 => 'Formations.sql',
- 4 => 'Entreprises.sql'
+ 4 => 'Entreprises.sql',
+ 5 => 'Formations_MD.sql'
);
if ($file != '') {
// récupère le contenu du fichier sql
} else {
$nextfile = 0;
}
- if ($nextfile > 4) {
+ if ($nextfile > 5) {
// tous les fichiers ont été exécutés, on passe à l'étape suivante
$next = 'adds1920';
} else {
$next = 'clean';
} elseif ($action == 'clean') {
// nettoyage du fichier temporaire
- exec('rm -Rf ' . $spoolpath);
+ //exec('rm -Rf ' . $spoolpath);
$report[] = 'Import finit.';
}
foreach($report as $t) {
{
$page->changeTpl('fusionax/education.tpl');
- $missingEducation = XDB::rawIterator("SELECT DISTINCT(f.Intitule_diplome)
+ $missingEducation = XDB::rawIterator("SELECT DISTINCT(f.Intitule_formation)
FROM fusionax_formations AS f
- WHERE f.Intitule_diplome != '' AND NOT EXISTS (SELECT *
- FROM profile_education_enum AS e
- WHERE f.Intitule_diplome = e.name)");
- $missingDegree = XDB::rawIterator("SELECT DISTINCT(f.Intitule_formation)
+ WHERE f.Intitule_formation != '' AND NOT EXISTS (SELECT *
+ FROM profile_education_enum AS e
+ WHERE f.Intitule_formation = e.name)");
+ $missingDegree = XDB::rawIterator("SELECT DISTINCT(f.Intitule_diplome)
FROM fusionax_formations AS f
- WHERE f.Intitule_formation != '' AND NOT EXISTS (SELECT *
- FROM profile_education_degree_enum AS e
- WHERE f.Intitule_formation = e.abbreviation)");
- $missingCouple = XDB::rawIterator("SELECT DISTINCT(f.Intitule_diplome) AS edu, f.Intitule_formation AS degree, ee.id AS eduid, de.id AS degreeid
+ WHERE f.Intitule_diplome != '' AND NOT EXISTS (SELECT *
+ FROM profile_education_degree_enum AS e
+ WHERE f.Intitule_diplome = e.abbreviation)");
+ $missingCouple = XDB::rawIterator("SELECT DISTINCT(f.Intitule_formation) AS edu, f.Intitule_diplome AS degree, ee.id AS eduid, de.id AS degreeid
FROM fusionax_formations AS f
- INNER JOIN profile_education_enum AS ee ON (f.Intitule_diplome = ee.name)
- INNER JOIN profile_education_degree_enum AS de ON (f.Intitule_formation = de.abbreviation)
+ INNER JOIN profile_education_enum AS ee ON (f.Intitule_formation = ee.name)
+ INNER JOIN profile_education_degree_enum AS de ON (f.Intitule_diplome = de.abbreviation)
WHERE f.Intitule_diplome != '' AND f.Intitule_formation != ''
AND NOT EXISTS (SELECT *
FROM profile_education_degree AS d
$page->assign('missingCoupleCount', $missingCouple->total());
}
+ function handler_corps(&$page)
+ {
+ $page->changeTpl('fusionax/corps.tpl');
+
+ $missingCorps = XDB::rawIterator('SELECT DISTINCT(f.corps_sortie) AS name
+ FROM fusionax_anciens AS f
+ WHERE NOT EXISTS (SELECT *
+ FROM profile_corps_enum AS c
+ WHERE f.corps_sortie = c.abbreviation)');
+ $missingGrade = XDB::rawIterator('SELECT DISTINCT(f.grade) AS name
+ FROM fusionax_anciens AS f
+ WHERE NOT EXISTS (SELECT *
+ FROM profile_corps_rank_enum AS c
+ WHERE f.grade = c.name)');
+
+ $page->assign('missingCorps', $missingCorps);
+ $page->assign('missingGrade', $missingGrade);
+ $page->assign('missingCorpsCount', $missingCorps->total());
+ $page->assign('missingGradeCount', $missingGrade->total());
+ }
+
function handler_issues_deathdate(&$page, $action = '')
{
$page->changeTpl('fusionax/deathdate_issues.tpl');
`Raison_sociale` VARCHAR(255) NOT NULL COMMENT 'Raison sociale de l''établissement',
`Libelle_fonctio` VARCHAR(255) NOT NULL COMMENT 'Libéllé de la fonction',
`Annuaire` BOOLEAN NOT NULL COMMENT 'publiable dans l''annuaire papier',
+ `Date_maj` DATE NOT NULL COMMENT 'Date de mise à jour de ces informations',
pid INT(11) UNSIGNED DEFAULT NULL,
jobid INT(6) UNSIGNED DEFAULT NULL,
description VARCHAR(255) DEFAULT NULL,
LOAD DATA LOCAL INFILE '{?}Activites.txt' INTO TABLE `fusionax_activites` CHARACTER SET utf8 FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\r\n'
(AC, ax_id, Code_etab, Raison_sociale, Libelle_fonctio, Annuaire,
-@Ligne1, @Ligne2, @Ligne3, @code_postal, @ville, @zip_cedex, @etat_distr, @pays, @tel, @fax, @StringDate_maj);
+@Ligne1, @Ligne2, @Ligne3, @code_postal, @ville, @zip_cedex, @etat_distr, @pays, @tel, @fax, @StringDate_maj)
+SET
+`Date_maj` = CONCAT(SUBSTRING(@StringDate_maj,7),'-',SUBSTRING(@StringDate_maj,4,2),'-',SUBSTRING(@StringDate_maj,1,2));
UPDATE fusionax_activites SET Raison_sociale = TRIM(Raison_sociale), Libelle_fonctio = TRIM(Libelle_fonctio);
pays VARCHAR(50) NOT NULL,
tel VARCHAR(30) NOT NULL,
fax VARCHAR(30) NOT NULL,
+ Date_maj DATE NOT NULL COMMENT 'Date de mise à jour de ces informations',
Code_etab BIGINT(10) DEFAULT NULL,
pid INT(11) UNSIGNED DEFAULT NULL,
jobid INT(6) UNSIGNED DEFAULT NULL,
LOAD DATA LOCAL INFILE '{?}Adresses.txt' INTO TABLE `fusionax_adresses` CHARACTER SET utf8 FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\r\n'
(provenance, ax_id, @Type_adr, Ligne1, Ligne2, Ligne3, code_postal, ville, zip_cedex, etat_distr, pays, tel, fax, @StringDate_maj)
SET
-`Type_adr` = IF(@Type_adr = 'E', 'E', IF(@Type_adr = '', '', 'P'));
+`Type_adr` = IF(@Type_adr = 'E', 'E', IF(@Type_adr = '', '', 'P')),
+`Date_maj` = CONCAT(SUBSTRING(@StringDate_maj,7),'-',SUBSTRING(@StringDate_maj,4,2),'-',SUBSTRING(@StringDate_maj,1,2));
LOAD DATA LOCAL INFILE '{?}Anciens.txt' INTO TABLE `fusionax_adresses` CHARACTER SET utf8 FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\r\n'
(provenance, ax_id, @login, @password, @promotion_etude, @gpe_promo, @Nom_patronymique, @partic_patro, @prenom, @Nom_usuel, @partic_nom,
@Nom_complet, @civilite, @Code_nationalite, @type, @corps_sortie, @StringDate_deces, @grade, @Mel_usage, @Mel_publiable, @xxx, @xxx,
@tel_mobile, @xxx, @xxx, @xxx, @xxx, @xxx, @xxx, @xxx, @X_M_D, @xxx, @xxx, @xxx, @xxx, @xxx, @xxx, @Type_adr,
- Ligne1, Ligne2, Ligne3, code_postal, ville, zip_cedex, etat_distr, pays, tel, fax, @date_MAJ)
+ Ligne1, Ligne2, Ligne3, code_postal, ville, zip_cedex, etat_distr, pays, tel, fax, @StringDate_maj)
SET
-Type_adr = IF(@Type_adr = 'E', 'E', IF(@Type_adr = '', '', 'P'));
+Type_adr = IF(@Type_adr = 'E', 'E', IF(@Type_adr = '', '', 'P')),
+`Date_maj` = CONCAT(SUBSTRING(@StringDate_maj,7),'-',SUBSTRING(@StringDate_maj,4,2),'-',SUBSTRING(@StringDate_maj,1,2));
LOAD DATA LOCAL INFILE '{?}Activites.txt' INTO TABLE `fusionax_adresses` CHARACTER SET utf8 FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\r\n'
(provenance, ax_id, Code_etab, @Raison_sociale, @Libelle_fonctio, @Annuaire,
Ligne1, Ligne2, Ligne3, code_postal, ville, zip_cedex, etat_distr, pays, tel, fax, @StringDate_maj)
SET
-`Type_adr` = 'E';
+`Type_adr` = 'E',
+`Date_maj` = CONCAT(SUBSTRING(@StringDate_maj,7),'-',SUBSTRING(@StringDate_maj,4,2),'-',SUBSTRING(@StringDate_maj,1,2));
UPDATE fusionax_adresses SET Ligne1 = TRIM(Ligne1), Ligne2 = TRIM(Ligne2), Ligne3 = TRIM(Ligne3), pays = TRIM(pays),
code_postal = TRIM(code_postal), ville = TRIM(ville), zip_cedex = TRIM(zip_cedex),
Mel_publiable TINYINT(4) NOT NULL COMMENT 'Autorisation d''utiliser le mail',
Mob_publiable TINYINT(4) NOT NULL COMMENT 'Autorisation d''utiliser le mobile',
tel_mobile VARCHAR(30) NOT NULL COMMENT 'Numéro de téléphone mobile',
+ Date_maj DATE NOT NULL COMMENT 'Date de mise à jour de ces informations',
pid INT(11) UNSIGNED DEFAULT NULL,
PRIMARY KEY (ax_id),
INDEX (pid)
(AN, ax_id, @login, @password, promotion_etude, @gpe_promo, Nom_patronymique, partic_patro, prenom, Nom_usuel, partic_nom,
Nom_complet, @civilite, Code_nationalite, @type, corps_sortie, @StringDate_deces, grade, Mel_usage, Mel_publiable, @xxx, Mob_publiable,
tel_mobile, @xxx, @xxx, @xxx, @xxx, @xxx, @xxx, @xxx, @X_M_D, @xxx, @xxx, @xxx, @xxx, @xxx, @xxx, @Type_adr,
- @Ligne1, @Ligne2, @Ligne3, @code_postal, @ville, @zip_cedex, @etat_distr, @pays, @tel, @fax, @date_MAJ)
+ @Ligne1, @Ligne2, @Ligne3, @code_postal, @ville, @zip_cedex, @etat_distr, @pays, @tel, @fax, @StringDate_maj)
SET
- Date_deces = CONCAT(SUBSTRING(@StringDate_deces,7),'-',SUBSTRING(@StringDate_deces,4,2),'-',SUBSTRING(@StringDate_deces,1,2));
+ Date_deces = CONCAT(SUBSTRING(@StringDate_deces,7),'-',SUBSTRING(@StringDate_deces,4,2),'-',SUBSTRING(@StringDate_deces,1,2)),
+ Date_maj = CONCAT(SUBSTRING(@StringDate_maj,7),'-',SUBSTRING(@StringDate_maj,4,2),'-',SUBSTRING(@StringDate_maj,1,2));
-- Mel_publiable is not certain yet :/
ALTER TABLE fusionax_anciens ADD INDEX (ax_id);
+UPDATE fusionax_anciens SET corps_sortie = TRIM(corps_sortie), grade = TRIM(grade);
-- Correspondances entre fiches X.org et fiches AX
DROP TABLE IF EXISTS `fusionax_import`;
DROP TABLE IF EXISTS `fusionax_formations`;
CREATE TABLE IF NOT EXISTS `fusionax_formations` (
+ Date_maj DATE NOT NULL COMMENT 'Date de mise à jour de ces informations',
FO CHAR(2) NOT NULL COMMENT 'Vaut toujours FO pour cette table',
ax_id VARCHAR(8) NOT NULL COMMENT 'Id unique de l''ancien',
- Intitule_diplome VARCHAR(255) NOT NULL DEFAULT 0 COMMENT 'Intitulé du diplôme',
Intitule_formation VARCHAR(255) NOT NULL DEFAULT 0 COMMENT 'Intitulé de la formation',
+ Intitule_diplome VARCHAR(255) NOT NULL DEFAULT 0 COMMENT 'Intitulé du diplôme',
Descr_formation VARCHAR(255) NOT NULL COMMENT 'Description de la formation',
pid INT(11) UNSIGNED DEFAULT NULL,
eduid INT(4) DEFAULT NULL,
) ENGINE=InnoDB, CHARSET=utf8;
LOAD DATA LOCAL INFILE '{?}Formations.txt' INTO TABLE fusionax_formations CHARACTER SET utf8 FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n'
-(FO, ax_id, Intitule_diplome, Intitule_formation, Descr_formation);
+(@StringDate_maj, FO, ax_id, Intitule_formation, Intitule_diplome, Descr_formation)
+SET
+Date_maj = CONCAT(SUBSTRING(@StringDate_maj,7),'-',SUBSTRING(@StringDate_maj,4,2),'-',SUBSTRING(@StringDate_maj,1,2));
+
UPDATE fusionax_formations AS f
-INNER JOIN profile_education_enum AS e ON (f.Intitule_diplome = e.abbreviation)
- SET f.Intitule_diplome = e.name
- WHERE f.Intitule_diplome != '';
+INNER JOIN profile_education_enum AS e ON (f.Intitule_formation = e.abbreviation)
+ SET f.Intitule_formation = e.name
+ WHERE f.Intitule_formation != '';
--- /dev/null
+-- Import complet des formations
+
+DROP TABLE IF EXISTS `fusionax_formations_md`;
+
+CREATE TABLE IF NOT EXISTS `fusionax_formations_md` (
+ FO CHAR(2) NOT NULL COMMENT 'Vaut toujours FO pour cette table',
+ ax_id VARCHAR(8) NOT NULL COMMENT 'Id unique de l''ancien',
+ field VARCHAR(255) DEFAULT NULL COMMENT 'Domaine de la formation',
+ pid INT(11) UNSIGNED DEFAULT NULL,
+ fieldid INT(2) DEFAULT NULL,
+ PRIMARY KEY (ax_id),
+ INDEX (pid),
+ INDEX (fieldid)
+) ENGINE=InnoDB, CHARSET=utf8;
+
+LOAD DATA LOCAL INFILE '{?}Formations.txt' INTO TABLE fusionax_formations_md CHARACTER SET utf8 FIELDS TERMINATED BY '\t' LINES TERMINATED BY '\n'
+(FO, ax_id, field);
+
+UPDATE fusionax_formations_md SET field = TRIM(field);
+ UPDATE fusionax_formations_md AS f
+INNER JOIN profile_education_field_enum AS e ON (f.field = e.field)
+ SET f.fieldid = e.id, f.field = NULL;
{
# Dates removal.
s/\r$//;
- s/(\t)*[0-9]+\t[0-9]+\t([0-9]{2}\/){2}[0-9]+$//;
+ s/^(FO\t\w{8}\t[^\t]*)\t[0-9]+\t[0-9]+\t([0-9]{2}\/[0-9]{2}\/[0-9]+)$/\2\t\1/;
# Trailing tab, spaces and dot removal.
s/(\t| )*$//;
s/( \t|\t )/\t/g;
s/ +/ /g;
# Removes empty educations and jobs (they have nothing to do there).
- s/^FO\t\w{8}$//;
- s/^FO\t\w{8}\tProfdes Universités$//;
- s/^FO\t\w{8}\tPréshonColonie Frdu Caire$//;
- s/^FO\t\w{8}\tInspgénhonCEA$//;
- s/^FO\t\w{8}\tProf Emérite Gén Méca$//;
- s/^FO\t\w{8}\tAncDG Dassault Aviation$//;
- s/^FO\t\w{8}\tPilote militaire Hélicoptère$//;
- s/^FO\t\w{8}\tProfHonSupAéro$//;
- s/^FO\t\w{8}\tPilote de chasse$//;
- s/^FO\t\w{8}\tProf ENSMP$//;
- s/^FO\t\w{8}\tProf hon Univ Bordeaux I$//;
- s/^FO\t\w{8}\tProf$//;
- s/^FO\t\w{8}\tIng Navigant d'Essais Hélicoptère$//;
- s/^FO\t\w{8}\tMandataire agrée OEB$//;
- s/^FO\t\w{8}\tIngSt$//;
- s/^FO\t\w{8}\tIngretrAérospatiale$//;
- s/^FO\t\w{8}\tIngénieur$//;
- s/^FO\t\w{8}\tIng EURATOM$//;
- s/^FO\t\w{8}\tInspGénCRdes Affd'OM$//;
- s/^FO\t\w{8}\tAvocat au Barreau de Paris$//;
- s/^FO\t\w{8}\tCambridge Profic$//;
- s/^FO\t\w{8}\tPilotage militaire$//;
- s/^FO\t\w{8}\tDirectHonBNP$//;
- s/^FO\t\w{8}\tInspecteur des Finances$//;
- s/^FO\t\w{8}\tMITI Japon$//;
- s/^FO\t\w{8}\tEuropean Patent Attorney$//;
- s/^FO\t\w{8}\tAdmciv$//;
- s/^FO\t\w{8}\tDirecthon SNCF$//;
- s/^FO\t\w{8}\tDDI Informatique$//;
- s/^FO\t\w{8}\tDDI$//;
- s/^FO\t\w{8}\tSFAF$//;
- s/^FO\t\w{8}\tGestalt praticien$//;
- s/^FO\t\w{8}\tAdmciv HC$//;
- s/^FO\t\w{8}\tPsychologue Clinicien$//;
- s/^FO\t\w{8}\tAnc Avocat au Bareau de Toulon$//;
- s/^FO\t\w{8}\tAnalyste SFAF$//;
- s/^FO\t\w{8}\tEcole de Chasse$//;
- s/^FO\t\w{8}\tPost Doc$//;
- s/^FO\t\w{8}\tSFAF CIIA$//;
- s/^FO\t\w{8}\tINSEE$//;
- s/^FO\t\w{8}\tEconomiste Statisticien$//;
+ s/^.*\tFO\t\w{8}$//;
+ s/^.*\tFO\t\w{8}\tProfdes Universités$//;
+ s/^.*\tFO\t\w{8}\tPréshonColonie Frdu Caire$//;
+ s/^.*\tFO\t\w{8}\tInspgénhonCEA$//;
+ s/^.*\tFO\t\w{8}\tProf Emérite Gén Méca$//;
+ s/^.*\tFO\t\w{8}\tAncDG Dassault Aviation$//;
+ s/^.*\tFO\t\w{8}\tPilote militaire Hélicoptère$//;
+ s/^.*\tFO\t\w{8}\tProfHonSupAéro$//;
+ s/^.*\tFO\t\w{8}\tPilote de chasse$//;
+ s/^.*\tFO\t\w{8}\tProf ENSMP$//;
+ s/^.*\tFO\t\w{8}\tProf hon Univ Bordeaux I$//;
+ s/^.*\tFO\t\w{8}\tProf$//;
+ s/^.*\tFO\t\w{8}\tIng Navigant d'Essais Hélicoptère$//;
+ s/^.*\tFO\t\w{8}\tMandataire agrée OEB$//;
+ s/^.*\tFO\t\w{8}\tIngSt$//;
+ s/^.*\tFO\t\w{8}\tIngretrAérospatiale$//;
+ s/^.*\tFO\t\w{8}\tIngénieur$//;
+ s/^.*\tFO\t\w{8}\tIng EURATOM$//;
+ s/^.*\tFO\t\w{8}\tInspGénCRdes Affd'OM$//;
+ s/^.*\tFO\t\w{8}\tAvocat au Barreau de Paris$//;
+ s/^.*\tFO\t\w{8}\tCambridge Profic$//;
+ s/^.*\tFO\t\w{8}\tPilotage militaire$//;
+ s/^.*\tFO\t\w{8}\tDirectHonBNP$//;
+ s/^.*\tFO\t\w{8}\tInspecteur des Finances$//;
+ s/^.*\tFO\t\w{8}\tMITI Japon$//;
+ s/^.*\tFO\t\w{8}\tEuropean Patent Attorney$//;
+ s/^.*\tFO\t\w{8}\tAdmciv$//;
+ s/^.*\tFO\t\w{8}\tDirecthon SNCF$//;
+ s/^.*\tFO\t\w{8}\tDDI Informatique$//;
+ s/^.*\tFO\t\w{8}\tDDI$//;
+ s/^.*\tFO\t\w{8}\tSFAF$//;
+ s/^.*\tFO\t\w{8}\tGestalt praticien$//;
+ s/^.*\tFO\t\w{8}\tAdmciv HC$//;
+ s/^.*\tFO\t\w{8}\tPsychologue Clinicien$//;
+ s/^.*\tFO\t\w{8}\tAnc Avocat au Bareau de Toulon$//;
+ s/^.*\tFO\t\w{8}\tAnalyste SFAF$//;
+ s/^.*\tFO\t\w{8}\tEcole de Chasse$//;
+ s/^.*\tFO\t\w{8}\tPost Doc$//;
+ s/^.*\tFO\t\w{8}\tSFAF CIIA$//;
+ s/^.*\tFO\t\w{8}\tINSEE$//;
+ s/^.*\tFO\t\w{8}\tEconomiste Statisticien$//;
s/^\n//;
# Places education in third place as if it is not reconized, it will only be stored as a description.
- s/^(FO\t\w{8}\t)/\1\t\t/;
+ s/^(.*\tFO\t\w{8}\t)/\1\t\t/;
# Fixes what can be fixed.
# École d'Ingénieurs
s/\t\t\tInstForm SupBiomédicale$/\t\t\tBiomédical/;
# Double diploma that need to be splitted.
- s/^(FO\t\w{8}\t\t)\tDoct HDR Ecotoxicologie$/\1PhD\tÉcotoxicologie\n\1HDR\tÉcotoxicologie/;
- s/^(FO\t\w{8}\t\t)\tAgrégé et Doct en Génie civil$/\1PhD\tGénie civil\n\1Agr.\tGénie civil/;
- s/^(FO\t\w{8}\t\t)\tDoct Habilité à la dir de rech en Philosophie$/\1PhD\tPhilosophie\n\1HDR\tPhilosophie/;
- s/^(FO\t\w{8}\t\t)\tDEA\+ Thèse Doctorat Pharmacochimie moléculaire$/\1PhD\tPharmacochimie moléculaire\n\1DEA\tPharmacochimie moléculaire/;
- s/^(FO\t\w{8}\t\t)\tDoctorat\, HDR Informatique$/\1PhD\tInformatique\n\1HDR\tInformatique/;
- s/^(FO\t\w{8}\t\t)\tDoctorat et Habilitation$/\1PhD\t\n\1HDR\t/;
- s/^(FO\t\w{8}\t)\t\tPhD et Habil à diriger les RechUniv Paris 6$/\1UPMC\tPhD\t\n\1UPMC\tHDR\t/;
- s/^(FO\t\w{8}\t)\t\tMS & PhD EHESS$/\1EHESS\tPhD\t\n\1EHESS\tMSc\t/;
- s/^(FO\t\w{8}\t)\t\tMBAIEP Paris Lic de Droit Assas$/\1Sciences Po\tDipl.\t\n\1Assas\tLic.\tDroit/;
- s/^(FO\t\w{8}\t)\t\tIEP Paris Lic de Droit Assas$/\1Sciences Po\tDipl.\t\n\1Assas\tLic.\tDroit/;
- s/^(FO\t\w{8}\t)\t\tIngENST licencié sciences économiques$/\1Télécom\tIng.\t\n\1\tLic.\tÉconomie/;
- s/^(FO\t\w{8}\t\t)\tMastère Aménagement et Maitrise d'Ouvrage Urbaine$/\1M\tAménagement\n\1Maîtr.\tOuvrage Urbain/;
- s/^(FO\t\w{8}\t\t)\tDEA et Thèse de Biologie$/\1PhD\tBiologie\n\1DEA\tBiologie/;
- s/^(FO\t\w{8}\t)\t\tDEA Thèse Jussieu$/\1UPMC\tPhD\t\n\1UPMC\tDEA\t/;
- s/^(FO\t\w{8}\t\t)\tDESS CAAE MBA$/\1DESS\t\n\1MBA\t/;
- s/^(FO\t\w{8}\t)\t\tIngSupelec 86 - EMBA HEC 04$/\1Supélec\tIng.\t\n\1HEC\tMBA\t/;
- s/^(FO\t\w{8}\t)\t\tMBA MscMassachus$/\1MIT\tMBA\t\n\1MIT\tMSc\t/;
- s/^(FO\t\w{8}\t)\t\tMBA Columbia \+ LBS/\1Columbia University\tMBA\t\n\1London Business School\tM\t/;
- s/^(FO\t\w{8}\t)\t\tMS Columbia & sciences Po/\1Columbia University\tMSc\t\n\1Sciences Po\tDipl.\t/;
+ s/^(.*\tFO\t\w{8}\t\t)\tDoct HDR Ecotoxicologie$/\1PhD\tÉcotoxicologie\n\1HDR\tÉcotoxicologie/;
+ s/^(.*\tFO\t\w{8}\t\t)\tAgrégé et Doct en Génie civil$/\1PhD\tGénie civil\n\1Agr.\tGénie civil/;
+ s/^(.*\tFO\t\w{8}\t\t)\tDoct Habilité à la dir de rech en Philosophie$/\1PhD\tPhilosophie\n\1HDR\tPhilosophie/;
+ s/^(.*\tFO\t\w{8}\t\t)\tDEA\+ Thèse Doctorat Pharmacochimie moléculaire$/\1PhD\tPharmacochimie moléculaire\n\1DEA\tPharmacochimie moléculaire/;
+ s/^(.*\tFO\t\w{8}\t\t)\tDoctorat\, HDR Informatique$/\1PhD\tInformatique\n\1HDR\tInformatique/;
+ s/^(.*\tFO\t\w{8}\t\t)\tDoctorat et Habilitation$/\1PhD\t\n\1HDR\t/;
+ s/^(.*\tFO\t\w{8}\t)\t\tPhD et Habil à diriger les RechUniv Paris 6$/\1UPMC\tPhD\t\n\1UPMC\tHDR\t/;
+ s/^(.*\tFO\t\w{8}\t)\t\tMS & PhD EHESS$/\1EHESS\tPhD\t\n\1EHESS\tMSc\t/;
+ s/^(.*\tFO\t\w{8}\t)\t\tMBAIEP Paris Lic de Droit Assas$/\1Sciences Po\tDipl.\t\n\1Assas\tLic.\tDroit/;
+ s/^(.*\tFO\t\w{8}\t)\t\tIEP Paris Lic de Droit Assas$/\1Sciences Po\tDipl.\t\n\1Assas\tLic.\tDroit/;
+ s/^(.*\tFO\t\w{8}\t)\t\tIngENST licencié sciences économiques$/\1Télécom\tIng.\t\n\1\tLic.\tÉconomie/;
+ s/^(.*\tFO\t\w{8}\t\t)\tMastère Aménagement et Maitrise d'Ouvrage Urbaine$/\1M\tAménagement\n\1Maîtr.\tOuvrage Urbain/;
+ s/^(.*\tFO\t\w{8}\t\t)\tDEA et Thèse de Biologie$/\1PhD\tBiologie\n\1DEA\tBiologie/;
+ s/^(.*\tFO\t\w{8}\t)\t\tDEA Thèse Jussieu$/\1UPMC\tPhD\t\n\1UPMC\tDEA\t/;
+ s/^(.*\tFO\t\w{8}\t\t)\tDESS CAAE MBA$/\1DESS\t\n\1MBA\t/;
+ s/^(.*\tFO\t\w{8}\t)\t\tIngSupelec 86 - EMBA HEC 04$/\1Supélec\tIng.\t\n\1HEC\tMBA\t/;
+ s/^(.*\tFO\t\w{8}\t)\t\tMBA MscMassachus$/\1MIT\tMBA\t\n\1MIT\tMSc\t/;
+ s/^(.*\tFO\t\w{8}\t)\t\tMBA Columbia \+ LBS/\1Columbia University\tMBA\t\n\1London Business School\tM\t/;
+ s/^(.*\tFO\t\w{8}\t)\t\tMS Columbia & sciences Po/\1Columbia University\tMSc\t\n\1Sciences Po\tDipl.\t/;
#############################################################################
# Devel formatting.
# # Both university and diploma missing.
- #s/^FO\t\w{8}\t\t\tExpertise comptable$//;
- #s/^FO\t\w{8}\t\t\tLangues orientales \(Chinois\)$//;
- #s/^FO\t\w{8}\t\t\tÉducateur spécialisé$//;
- #s/^FO\t\w{8}\t\t\tGestion$//;
- #s/^FO\t\w{8}\t\t\tBiomédical$//;
- #s/^FO\t\w{8}\t\t\tBrth$//;
- #s/^FO\t\w{8}\t\t\tDEM$//;
- #s/^FO\t\w{8}\t\t\tDT$//;
- #s/^FO\t\w{8}\t\t\tBESG$//;
- #s/^FO\t\w{8}\t\t\tESO$//;
- #s/^FO\t\w{8}\t\t\tBT$//;
- #s/^FO\t\w{8}\t\t\tBEL$//;
- #s/^FO\t\w{8}\t\t\tDipl Lt Et Sup Banq$//;
- #s/^FO\t\w{8}\t\t\tDiplôme Nepali-Tibétain$//;
- #s/^FO\t\w{8}\t\t\tReact School Harwell$//;
- #s/^FO\t\w{8}\t\t\tEATG$//;
- #s/^FO\t\w{8}\t\t\tDESA$//;
- #s/^FO\t\w{8}\t\t\tDIUUP$//;
- #s/^FO\t\w{8}\t\t\tDrrerNat$//;
- #s/^FO\t\w{8}\t\t\tIAC$//;
- #s/^FO\t\w{8}\t\t\tCESDR$//;
- #s/^FO\t\w{8}\t\t\tAuditeur ScPolitique$//;
- #s/^FO\t\w{8}\t\t\tCES Informatique$//;
- #s/^FO\t\w{8}\t\t\tDon en religion$//;
- #s/^FO\t\w{8}\t\t\tDSN$//;
- #s/^FO\t\w{8}\t\t\tBEMS\/CHEM$//;
- #s/^FO\t\w{8}\t\t\tCESSID$//;
- #s/^FO\t\w{8}\t\t\tBiologie Moléculaire$//;
- #s/^FO\t\w{8}\t\t\tMécanique des Transfert$//;
- #s/^FO\t\w{8}\t\t\tGestion$//;
- #s/^FO\t\w{8}\t\t\tDECS$//;
- #s/^FO\t\w{8}\t\t\tCFAF$//;
- #s/^FO\t\w{8}\t\t\tCRC$//;
- #s/^FO\t\w{8}\t\t\tMASE$//;
- #s/^FO\t\w{8}\t\t\tCollège des Sciences Soc et Eco$//;
- #s/^FO\t\w{8}\t\t\tInstitut de Contrôle de Gestion$//;
- #s/^FO\t\w{8}\t\t\tICG$//;
- #s/^FO\t\w{8}\t\t\tETS II$//;
- #s/^FO\t\w{8}\t\t\tFRM$//;
- #s/^FO\t\w{8}\t\t\tArchitecte DPLG$//;
- #s/^FO\t\w{8}\t\t\tCycle des Hautes Etudes CHEE$//;
- #s/^FO\t\w{8}\t\t\tCHEE&DD Session 9$//;
- #s/^FO\t\w{8}\t\t\tCSME Session 29$//;
- #s/^FO\t\w{8}\t\t\tInternat Teachers Progr$//;
- #s/^FO\t\w{8}\t\t\tCSCP$//;
- #s/^FO\t\w{8}\t\t\tBaccalauréat canonique$//;
- #s/^FO\t\w{8}\t\t\tCertif européen de Psychothérapie$//;
- #s/^FO\t\w{8}\t\t\tIFG$//;
- #s/^FO\t\w{8}\t\t\tIFP$//;
- #s/^FO\t\w{8}\t\t\tArchitecte dplg$//;
- #s/^FO\t\w{8}\t\t\tLLCE Chinois INALCO$//;
- #s/^FO\t\w{8}\t\t\tInst du Contrôle de Gestion$//;
- #s/^FO\t\w{8}\t\t\tInstitut Auguste Comte$//;
- #s/^FO\t\w{8}\t\t\tInst Auguste Comte$//;
- #s/^FO\t\w{8}\t\t\tUSMC Command & Staff College$//;
- #s/^FO\t\w{8}\t\t\tISNSE Argunne National Laboratory USA$//;
+ #s/^.*\tFO\t\w{8}\t\t\tExpertise comptable$//;
+ #s/^.*\tFO\t\w{8}\t\t\tLangues orientales \(Chinois\)$//;
+ #s/^.*\tFO\t\w{8}\t\t\tÉducateur spécialisé$//;
+ #s/^.*\tFO\t\w{8}\t\t\tGestion$//;
+ #s/^.*\tFO\t\w{8}\t\t\tBiomédical$//;
+ #s/^.*\tFO\t\w{8}\t\t\tBrth$//;
+ #s/^.*\tFO\t\w{8}\t\t\tDEM$//;
+ #s/^.*\tFO\t\w{8}\t\t\tDT$//;
+ #s/^.*\tFO\t\w{8}\t\t\tBESG$//;
+ #s/^.*\tFO\t\w{8}\t\t\tESO$//;
+ #s/^.*\tFO\t\w{8}\t\t\tBT$//;
+ #s/^.*\tFO\t\w{8}\t\t\tBEL$//;
+ #s/^.*\tFO\t\w{8}\t\t\tDipl Lt Et Sup Banq$//;
+ #s/^.*\tFO\t\w{8}\t\t\tDiplôme Nepali-Tibétain$//;
+ #s/^.*\tFO\t\w{8}\t\t\tReact School Harwell$//;
+ #s/^.*\tFO\t\w{8}\t\t\tEATG$//;
+ #s/^.*\tFO\t\w{8}\t\t\tDESA$//;
+ #s/^.*\tFO\t\w{8}\t\t\tDIUUP$//;
+ #s/^.*\tFO\t\w{8}\t\t\tDrrerNat$//;
+ #s/^.*\tFO\t\w{8}\t\t\tIAC$//;
+ #s/^.*\tFO\t\w{8}\t\t\tCESDR$//;
+ #s/^.*\tFO\t\w{8}\t\t\tAuditeur ScPolitique$//;
+ #s/^.*\tFO\t\w{8}\t\t\tCES Informatique$//;
+ #s/^.*\tFO\t\w{8}\t\t\tDon en religion$//;
+ #s/^.*\tFO\t\w{8}\t\t\tDSN$//;
+ #s/^.*\tFO\t\w{8}\t\t\tBEMS\/CHEM$//;
+ #s/^.*\tFO\t\w{8}\t\t\tCESSID$//;
+ #s/^.*\tFO\t\w{8}\t\t\tBiologie Moléculaire$//;
+ #s/^.*\tFO\t\w{8}\t\t\tMécanique des Transfert$//;
+ #s/^.*\tFO\t\w{8}\t\t\tGestion$//;
+ #s/^.*\tFO\t\w{8}\t\t\tDECS$//;
+ #s/^.*\tFO\t\w{8}\t\t\tCFAF$//;
+ #s/^.*\tFO\t\w{8}\t\t\tCRC$//;
+ #s/^.*\tFO\t\w{8}\t\t\tMASE$//;
+ #s/^.*\tFO\t\w{8}\t\t\tCollège des Sciences Soc et Eco$//;
+ #s/^.*\tFO\t\w{8}\t\t\tInstitut de Contrôle de Gestion$//;
+ #s/^.*\tFO\t\w{8}\t\t\tICG$//;
+ #s/^.*\tFO\t\w{8}\t\t\tETS II$//;
+ #s/^.*\tFO\t\w{8}\t\t\tFRM$//;
+ #s/^.*\tFO\t\w{8}\t\t\tArchitecte DPLG$//;
+ #s/^.*\tFO\t\w{8}\t\t\tCycle des Hautes Etudes CHEE$//;
+ #s/^.*\tFO\t\w{8}\t\t\tCHEE&DD Session 9$//;
+ #s/^.*\tFO\t\w{8}\t\t\tCSME Session 29$//;
+ #s/^.*\tFO\t\w{8}\t\t\tInternat Teachers Progr$//;
+ #s/^.*\tFO\t\w{8}\t\t\tCSCP$//;
+ #s/^.*\tFO\t\w{8}\t\t\tBaccalauréat canonique$//;
+ #s/^.*\tFO\t\w{8}\t\t\tCertif européen de Psychothérapie$//;
+ #s/^.*\tFO\t\w{8}\t\t\tIFG$//;
+ #s/^.*\tFO\t\w{8}\t\t\tIFP$//;
+ #s/^.*\tFO\t\w{8}\t\t\tArchitecte dplg$//;
+ #s/^.*\tFO\t\w{8}\t\t\tLLCE Chinois INALCO$//;
+ #s/^.*\tFO\t\w{8}\t\t\tInst du Contrôle de Gestion$//;
+ #s/^.*\tFO\t\w{8}\t\t\tInstitut Auguste Comte$//;
+ #s/^.*\tFO\t\w{8}\t\t\tInst Auguste Comte$//;
+ #s/^.*\tFO\t\w{8}\t\t\tUSMC Command & Staff College$//;
+ #s/^.*\tFO\t\w{8}\t\t\tISNSE Argunne National Laboratory USA$//;
## # Formatted stuff.
- #s/^FO\t\w{8}((\t|\t\t)[a-zA-Z1-9'\.éèêùüàäïîşńÉÈÊÙÀÜÄÏÎŞŃ \-\(\)]+)\t.*//;
+ #s/^.*\tFO\t\w{8}((\t|\t\t)[a-zA-Z1-9'\.éèêùüàäïîşńÉÈÊÙÀÜÄÏÎŞŃ \-\(\)]+)\t.*//;
# # Removes empty lines.
s/^\n//;
close(FILE);
close(OUT);
+
+$path = $0;
+$path =~ s/modules\/fusionax\/formation\.pl//;
+$path .= "spool/fusionax/";
+$in = $path . "Formations_MD.txt";
+$out = $path . "Formations_MD_out.txt";
+open(FILE, "<:encoding(UTF-8)", $in) || die ("Formations_MD.txt failed to open.");
+open(OUT, ">:encoding(UTF-8)", $out) || die ("Formations_MD_out.txt failed to open.");
+
+while (<FILE>)
+{
+ # Dates removal.
+ s/\r$//;
+ s/^(FO\t\w{8}\t(\w|\.|'|&| )+)\t.*$/\1/;
+ # Trailing tab, spaces and dot removal.
+ s/(\t| )*$//;
+ s/( \t|\t )/\t/g;
+ s/ +/ /g;
+
+ # Removes diploma
+ s/Doct. de l'Ec. polytechnique//;
+ s/Doct. de l'Ec. Polytechnique//;
+ s/Etudiante en Master de l'Ec. polytechnique//;
+ s/Etudiant en Master de l'Ec. polytechnique//;
+
+ print OUT $_;
+}
+
+close(FILE);
+close(OUT);
global $globals;
require_once 'userset.inc.php';
- $view = new SearchSet(true);
+ $view = new QuickSearchSet();
$view->addMod('gadget', 'Gadget', true);
$view->apply(null, $page);
}
return array(
- 'googleapps' => $this->make_hook('index', AUTH_MDP),
+ 'googleapps' => $this->make_hook('index', AUTH_MDP, 'mail'),
'admin/googleapps' => $this->make_hook('admin', AUTH_MDP, 'admin'),
'admin/googleapps/job' => $this->make_hook('admin_job', AUTH_MDP, 'admin'),
'admin/googleapps/user' => $this->make_hook('admin_user', AUTH_MDP, 'admin'),
$this->prepare_client($page);
$members = $this->client->get_members($liste);
$list = list_fetch_basic_info(list_extract_members($members[1]));
- pl_content_headers("text/x-csv");
+ pl_cached_content_headers('text/x-csv', 1);
echo "email,nom,promo\n";
echo implode("\n", $list);
// {{{ function list_sort_owners
-function list_sort_owners(&$members, $tri_promo = true)
+function list_sort_owners($members, $tri_promo = true)
{
global $globals;
- $membres = Array();
+ // $membres' structure is the following: $sortKey => $key => $listMember
+ $membres = array();
- foreach($members as $mem) {
- $user = User::getSilent($mem);
+ foreach($members as $member) {
+ $user = User::getSilent($member);
if (!$user) {
- $membres[0][] = array('l' => $mem, 'p' => (!$tri_promo ? 'inconnus' : null), 'n' => null, 'x' => null, 'b' => null);
+ $membres[0][$member] = array('name' => null, 'email' => $member, 'category' => null, 'uid' => null, 'lost' => null, 'hasProfile' => null);
} else {
+ $hasProfile = $user->hasProfile();
$uid = $user->id();
- $nom = $user->directoryName();
- $promo = $user->category();
- if (!$promo) {
- $promo = 'extérieurs';
- }
- $key = $tri_promo ? ($promo != 'extérieurs' ? $promo : 0) : strtoupper(@$nom{0});
- if ($tri_promo) {
- $promo = null;
+ $name = $user->directoryName();
+ $category = $user->category();
+ $key = $tri_promo ? ($category ? $category : 'AAAAA') : strtoupper($name{0});
+ if (!$category) {
+ $category = 'extérieurs';
}
- $membres[$key][$nom.$mem] = array('n' => $nom, 'l' => $mem, 'p' => $promo, 'x' => $uid, 'b' => $user->lost);
+ $membres[$key][$name . $member] = array('name' => $name, 'email' => $member, 'category' => $category,
+ 'uid' => $uid, 'lost' => $user->lost, 'hasProfile' => $hasProfile);
}
}
ksort($membres);
- foreach($membres as $key=>$val) ksort($membres[$key]);
+ foreach($membres as $membre) {
+ ksort($membre);
+ }
return $membres;
}
$page->assign('meth', $meth);
$page->assign('pay', $pay);
$page->assign('evtlink', $pay->event());
+ $page->assign('sex', S::user()->isFemale());
}
function handler_cyber_return(&$page, $uid = null)
$this->val = 100 * strtr(sprintf("%.02f", (float)$val), '.', ',');
}
- // }}}
+ // }}}
// {{{ function form()
function prepareform(&$pay)
$prefix = ($pay->flags->hasflag('unique')) ? str_pad("",15,"0") : rand_url_id();
$fullref = substr("$prefix-{$pay->id}",-12); // FIXME : check for duplicates
$ts = time();
- $trans_date = date("YmdHis", $ts);
- $trans_id = date("His", $ts); // FIXME : check for duplicates
-
+ $trans_date = date("YmdHis", $ts);
+ $trans_id = date("His", $ts); // FIXME : check for duplicates
+
// contenu du formulaire
$this->urlform = "https://systempay.cyberpluspaiement.com/vads-payment/";
$this->infos['commercant'] = Array(
$this->infos['commande'] = Array(
'vads_amount' => $this->val,
'vads_currency' => '978', # Euro
- 'vads_payment_config' => 'SINGLE',
- 'vads_trans_date' => $trans_date,
+ 'vads_payment_config' => 'SINGLE',
+ 'vads_trans_date' => $trans_date,
'vads_trans_id' => $trans_id,
'vads_order_id' => $fullref,
'vads_order_info' => Env::v('comment'));
$this->urlform = 'https://' . $globals->money->paypal_site . '/cgi-bin/webscr';
$user = S::user();
- $name = $user->lastName();
$roboturl = str_replace("https://","http://",$globals->baseurl)
. '/' . $platal->ns . "payment/paypal_return/" . S::v('uid')
. "?comment=" . urlencode(Env::v('comment'));
- $this->infos = array();
-
- $this->infos['commercant'] = array(
- 'business' => $globals->money->paypal_compte,
- 'rm' => 2,
- 'return' => $roboturl,
- 'cn' => 'Commentaires',
- 'no_shipping' => 1,
- 'cbt' => empty($GLOBALS['IS_XNET_SITE']) ?
- 'Revenir sur polytechnique.org.' :
- 'Revenir sur polytechnique.net.'
+ $this->infos = array(
+ 'commercant' => array(
+ 'business' => $globals->money->paypal_compte,
+ 'rm' => 2,
+ 'return' => $roboturl,
+ 'cn' => 'Commentaires',
+ 'no_shipping' => 1,
+ 'cbt' => empty($GLOBALS['IS_XNET_SITE']) ? 'Revenir sur polytechnique.org.' : 'Revenir sur polytechnique.net.'
+ )
);
$info_client = array(
- 'first_name' => S::v('prenom'),
- 'last_name' => $name,
- 'email' => S::user()->bestEmail()
+ 'first_name' => $user->firstName(),
+ 'last_name' => $user->lastName(),
+ 'email' => $user->bestEmail()
);
$res = XDB::query("SELECT pa.text, gl.name AS city, pa.postalCode AS zip, pa.countryId AS country,
LEFT JOIN geoloc_localities AS gl ON (gl.id = pa.localityId)
WHERE pa.pid = {?} AND FIND_IN_SET('current', pa.flags)
LIMIT 1",
- S::i('pid'));
+ $user->profile()->id());
$this->infos['client'] = array_map('replace_accent', array_merge($info_client, $res->fetchOneAssoc()));
list($this->infos['client']['address1'], $this->infos['client']['address2']) =
explode("\n", Geocoder::getFirstLines($this->infos['client']['text'],
$opened_tab = $hrpid;
$hrpid = $aux;
$url_error = true;
+ } else {
+ $url_error = false;
}
$profile = $this->findProfile($hrpid);
if (! ($profile instanceof Profile) && ($profile == PL_NOT_FOUND || $profile == PL_FORBIDDEN)) {
$page->assign('address', array());
}
- function handler_ajax_tel(&$page, $prefid, $prefname, $telid)
+ function handler_ajax_tel(&$page, $prefid, $prefname, $telid, $subField, $mainField, $mainId)
{
pl_content_headers("text/html");
$page->changeTpl('profile/phone.tpl', NO_SKIN);
$page->assign('telid', $telid);
$phone = new Phone();
$page->assign('tel', $phone->toFormArray());
+ if ($mainField) {
+ $page->assign('subField', $subField);
+ $page->assign('mainField', $mainField);
+ $page->assign('mainId', $mainId);
+ }
}
function handler_ajax_edu(&$page, $eduid, $class)
// Retrieves referents' countries.
$res = XDB::query(
- "SELECT gc.countryFR
+ "SELECT gc.country
FROM profile_mentor_country AS m
LEFT JOIN geoloc_countries AS gc ON (m.country = gc.iso_3166_1_a2)
WHERE pid = {?}", $pf->id());
pl_content_headers("text/html");
$page->changeTpl('include/field.select.tpl', NO_SKIN);
$page->assign('name', 'pays_sel');
- $it = XDB::iterator("SELECT gc.iso_3166_1_a2 AS id, gc.countryFR AS field
+ $it = XDB::iterator("SELECT gc.iso_3166_1_a2 AS id, gc.country AS field
FROM geoloc_countries AS gc
INNER JOIN profile_mentor_country AS mp ON (mp.country = gc.iso_3166_1_a2)
GROUP BY iso_3166_1_a2
- ORDER BY countryFR");
+ ORDER BY country");
$page->assign('list', $it);
}
$table_editor->describe('degree', 'niveau', true);
$table_editor->apply($page, $action, $id);
}
- function handler_admin_education_degree_set(&$page, $action = 'list', $id = null) {
+ function handler_admin_education_degree_set(&$page, $action = 'list', $id = null, $id2 = null) {
$page->setTitle('Administration - Correspondances formations - niveau de formation');
$page->assign('title', 'Gestion des correspondances formations - niveau de formation');
- $table_editor = new PLTableEditor('admin/education_degree_set', 'profile_education_degree', 'eduid', true);
+ $table_editor = new PLTableEditor('admin/education_degree_set', 'profile_education_degree', 'eduid', true, 'degreeid');
$table_editor->describe('eduid', 'id formation', true);
$table_editor->describe('degreeid', 'id niveau', true);
$table_editor->add_option_table('profile_education_degree_enum','profile_education_degree_enum.id = t.degreeid');
$table_editor->add_option_field('profile_education_degree_enum.degree', 'degree_name', 'niveau');
- $table_editor->apply($page, $action, $id);
+ $table_editor->apply($page, $action, $id, $id2);
}
function handler_admin_sections(&$page, $action = 'list', $id = null) {
$page->setTitle('Administration - Sections');
public function save(ProfilePage &$page, $field, $value)
{
- Phone::deletePhones($page->pid(), Phone::LINK_ADDRESS);
- Address::deleteAddresses($page->pid(), Address::LINK_PROFILE);
+ Phone::deletePhones($page->pid(), Phone::LINK_ADDRESS, null, S::user()->isMe($page->owner) || S::admin());
+ Address::deleteAddresses($page->pid(), Address::LINK_PROFILE, null, S::user()->isMe($page->owner) || S::admin());
Address::saveFromArray($value, $page->pid(), Address::LINK_PROFILE);
}
$this->search_names = array();
foreach ($value as &$sn) {
$sn['name'] = trim($sn['name']);
- if ($sn['type'] == 'firstname' || $sn['type'] == 'lastname') {
+ if (S::user()->isMe($this->owner) && ($sn['type'] == 'firstname' || $sn['type'] == 'lastname')) {
$sn['name'] = $this->prepare($page, $sn['type'], $sn['name'],
$initial[$sn['type']], $success_tmp);
$success = $success && $success_tmp;
$names = array();
foreach ($value as $name) {
if ($name['name'] != '') {
- $names[] = $name['type_name'] . ' : ' . $name['name'];
+ $names[] = mb_strtolower($name['type_name']) . ' : ' . $name['name'];
}
}
return implode(', ' , $names);
$degreesList = DirEnum::getOptions(DirEnum::EDUDEGREES);
$fieldsList = DirEnum::getOptions(DirEnum::EDUFIELDS);
$educations = array();
- foreach ($value as $education) {
- $educations[] = 'Université : ' . $schoolsList[$education['eduid']]
- . ', diplôme : ' . $degreesList[$education['degreeid']]
- . ', domaine : ' . $fieldsList[$education['fieldid']]
- . ', année d\'obtention : ' . $education['grad_year']
- . ', intitulé : ' . $education['program'];
+ foreach ($value as $id => $education) {
+ // XXX: the following condition should be removed once there are no more incomplete educations.
+ if (is_null($education['eduid']) || is_null($education['degreeid'])) {
+ if (is_null($education['eduid']) && is_null($education['degreeid'])) {
+ $educations[$id] = 'formation manquante';
+ } else {
+ $educations[$id] = (is_null($education['eduid']) ? 'université manquante' : $schoolsList[$education['eduid']]) . ', '
+ . (is_null($education['degreeid']) ? 'diplôme manquant' : $degreesList[$education['degreeid']]);
+ }
+ } else {
+ $educations[$id] = $schoolsList[$education['eduid']] . ', ' . $degreesList[$education['degreeid']];
+ }
+
+ $details = array();
+ if ($education['grad_year']) {
+ $details[] = $education['grad_year'];
+ }
+ if ($education['program']) {
+ $details[] = '« ' . $education['program'] . ' »';
+ }
+ if ($education['fieldid']) {
+ $details[] = $fieldsList[$education['fieldid']];
+ }
+ if (count($details)) {
+ $educations[$id] .= ' (' . implode(', ', $details) . ')';
+ }
}
return implode(', ', $educations);
}
}
public function getText($value) {
+ static $pubs = array('public' => 'publique', 'ax' => 'annuaire AX', 'private' => 'privé');
$networkings = array();
foreach ($value as $network) {
- $networkings[] = 'nom : ' . $network['name'] . ', adresse : ' . $network['address']
- . ', affichage : ' . $network['pub'];
+ $networkings[] = $network['name'] . ' : ' . $network['address'] . ' (affichage ' . $pubs[$network['pub']] . ')';
}
- return implode(' ; ' , $networkings);
+ return implode(', ' , $networkings);
}
}
parent::__construct($wiz);
$this->settings['search_names']
= new ProfileSettingSearchNames();
- $this->settings['birthdate'] = new ProfileSettingDate();
$this->settings['nationality1']
= $this->settings['nationality2']
= $this->settings['nationality3']
/* Some fields editable under condition */
if (!S::user()->isMe($this->owner)) {
$this->settings['deathdate'] = new ProfileSettingDate(true);
- }
- if (S::user()->isMe($this->owner)) {
+ $this->settings['birthdate'] = new ProfileSettingDate(true);
+ } else {
$this->settings['yourself'] = null;
+ $this->settings['birthdate'] = new ProfileSettingDate();
}
if (S::user()->checkPerms('directory_private')
|| S::user()->isMyProfile($this->owner)) {
protected function _fetchData()
{
// Checkout all data...
- $res = XDB::query("SELECT p.nationality1, p.nationality2, p.nationality3, p.birthdate,
+ $res = XDB::query("SELECT p.nationality1, p.nationality2, p.nationality3, IF(p.birthdate = 0, '', p.birthdate) AS birthdate,
p.email_directory as email_directory, pd.promo AS promo_display,
p.freetext, p.freetext_pub, p.ax_id AS matricule_ax, pd.yourself,
p.deathdate
return array(
'id' => '0',
'jobid' => '',
- 'pub' => 'private',
+ 'pub' => 'ax',
'name' => '',
'description' => '',
'w_url' => '',
'w_address' => $address->toFormArray(),
'w_email' => '',
- 'w_email_pub' => 'private',
+ 'w_email_pub' => 'ax',
'w_email_new' => '',
'w_phone' => array(0 => $phone->toFormArray()),
'terms' => array()
return $jobs;
}
- private function cleanJob(ProfilePage &$page, $jobid, array &$job, &$success)
+ private function cleanJob(ProfilePage &$page, $jobid, array &$job, &$success, $maxPublicity)
{
if ($job['w_email'] == "new@example.org") {
$job['w_email'] = $job['w_email_new'];
if (count($job['terms'])) {
$termsid = array();
foreach ($job['terms'] as $term) {
- if (!$term['full_name']) {
+ if (!isset($term['full_name'])) {
$termsid[] = $term['jtid'];
}
}
$termsid);
$term_id_to_name = $res->fetchAllAssoc('jtid', false);
foreach ($job['terms'] as &$term) {
- if (!$term['full_name']) {
+ if (!isset($term['full_name'])) {
$term['full_name'] = $term_id_to_name[$term['jtid']];
}
}
$job['jobid'] = $res->fetchOneCell();
}
}
- $job['w_phone'] = Phone::formatFormArray($job['w_phone'], $s);
+
+ if ($maxPublicity->isVisible($job['w_email_pub'])) {
+ $job['w_email_pub'] = $maxPublicity->level();
+ }
+ $job['w_phone'] = Phone::formatFormArray($job['w_phone'], $s, $maxPublicity);
unset($job['removed']);
unset($job['new']);
$success = true;
foreach ($value as $key => $job) {
$job['name'] = trim($job['name']);
- if ($job['name'] == '' && $entreprise) {
+ if ($job['name'] == '' && $entreprise[$entr_val]->id == $key) {
$job['tmp_name'] = $entreprise[$entr_val]->name;
++$entr_val;
} else if ($job['name'] == '') {
foreach ($value as $key => &$job) {
$address = new Address($job['w_address']);
$s = $address->format();
+ $maxPublicity = new ProfileVisibility($job['pub']);
+ if ($maxPublicity->isVisible($address->pub)) {
+ $address->pub = $maxPublicity->level();
+ }
$job['w_address'] = $address->toFormArray();
- $this->cleanJob($page, $key, $job, $s);
+ $this->cleanJob($page, $key, $job, $s, $maxPublicity);
if (!$init) {
$success = ($success && $s);
}
public function save(ProfilePage &$page, $field, $value)
{
- XDB::execute("DELETE FROM profile_job
- WHERE pid = {?}",
- $page->pid());
- XDB::execute("DELETE FROM profile_job_term
- WHERE pid = {?}",
+ $deletePrivate = S::user()->isMe($page->owner) || S::admin();
+ XDB::execute('DELETE FROM pj, pjt
+ USING profile_job AS pj
+ LEFT JOIN profile_job_term AS pjt ON (pj.pid = pjt.pid AND pj.id = pjt.jid)
+ WHERE pj.pid = {?}' . (($deletePrivate) ? '' : ' AND pj.pub IN (\'public\', \'ax\')'),
$page->pid());
- Address::deleteAddresses($page->pid(), Address::LINK_JOB);
- Phone::deletePhones($page->pid(), Phone::LINK_JOB);
+ Address::deleteAddresses($page->pid(), Address::LINK_JOB, null, $deletePrivate);
+ Phone::deletePhones($page->pid(), Phone::LINK_JOB, null, $deletePrivate);
$terms_values = array();
foreach ($value as $id => &$job) {
if (isset($job['name']) && $job['name']) {
public function getText($value)
{
+ static $pubs = array('public' => 'publique', 'ax' => 'annuaire AX', 'private' => 'privé');
$jobs = array();
foreach ($value as $id => $job) {
$address = Address::formArrayToString(array($job['w_address']));
$phones = Phone::formArrayToString($job['w_phone']);
- // TODO: add jobterms here.
- $jobs[] = 'Entreprise : ' . $job['name']
- . ', description : ' . $job['description'] . ', web : ' . $job['w_url']
- . ', email : ' . $job['w_email']
- . ($phones ? ', ' . $phones : '') . ($address ? ', ' . $address : '');
+ $jobs[$id] = $job['name'];
+ $jobs[$id] .= ($job['description'] ? (', ' . $job['description']) : '');
+ $jobs[$id] .= ' (affichage ' . $pubs[$job['pub']];
+ if (count($job['terms'])) {
+ $terms = array();
+ foreach ($job['terms'] as $term) {
+ $terms[] = $term['full_name'];
+ }
+ $jobs[$id] .= ', mots-clefs : ' . implode(', ', $terms);
+ }
+ if ($job['w_url']) {
+ $jobs[$id] .= ', page perso : ' . $job['w_url'];
+ }
+ if ($address) {
+ $jobs[$id] .= ', adresse : ' . $address;
+ }
+ if ($job['w_email']) {
+ $jobs[$id] .= ', email : ' . $job['w_email'];
+ }
+ if ($phones) {
+ $jobs[$id] .= ', téléphones : ' . $phones;
+ }
+ $jobs[$id] .= ')';
}
return implode(' ; ' , $jobs);
}
{
$success = true;
if (is_null($value)) {
- $res = XDB::query("SELECT original_corpsid AS original, current_corpsid AS current,
- rankid AS rank, corps_pub AS pub
- FROM profile_corps
- WHERE pid = {?}",
+ $res = XDB::query('SELECT c.original_corpsid AS original, e.name AS originalText,
+ c.current_corpsid AS current, c.rankid AS rank, c.corps_pub AS pub
+ FROM profile_corps AS c
+ INNER JOIN profile_corps_enum AS e ON (c.original_corpsid = e.id)
+ WHERE c.pid = {?}',
$page->pid());
return $res->fetchOneAssoc();
}
public function save(ProfilePage &$page, $field, $value)
{
- XDB::execute('INSERT INTO profile_corps (original_corpsid, current_corpsid, rankid, corps_pub, pid)
- VALUES ({?}, {?}, {?}, {?}, {?})
- ON DUPLICATE KEY UPDATE original_corpsid = VALUES(original_corpsid), current_corpsid = VALUES(current_corpsid),
- rankid = VALUES(rankid), corps_pub = VALUES(corps_pub)',
- $value['original'], $value['current'], $value['rank'], $value['pub'], $page->pid());
+ if (!S::user()->isMe($page->owner)) {
+ XDB::execute('INSERT INTO profile_corps (original_corpsid, current_corpsid, rankid, corps_pub, pid)
+ VALUES ({?}, {?}, {?}, {?}, {?})
+ ON DUPLICATE KEY UPDATE original_corpsid = VALUES(original_corpsid), current_corpsid = VALUES(current_corpsid),
+ rankid = VALUES(rankid), corps_pub = VALUES(corps_pub)',
+ $value['original'], $value['current'], $value['rank'], $value['pub'], $page->pid());
+ } else {
+ XDB::execute('INSERT INTO profile_corps (current_corpsid, rankid, corps_pub, pid)
+ VALUES ({?}, {?}, {?}, {?})
+ ON DUPLICATE KEY UPDATE current_corpsid = VALUES(current_corpsid),
+ rankid = VALUES(rankid), corps_pub = VALUES(corps_pub)',
+ $value['current'], $value['rank'], $value['pub'], $page->pid());
+ }
}
public function getText($value)
{
+ static $pubs = array('public' => 'publique', 'ax' => 'annuaire AX', 'private' => 'privé');
$corpsList = DirEnum::getOptions(DirEnum::CORPS);
$rankList = DirEnum::getOptions(DirEnum::CORPSRANKS);
- return 'Corps actuel : ' . $corpsList[$value['current']] . ' , rang : ' . $corpsList[$value['rank']]
- . ' , corps d\'origine : ' . $corpsList[$value['original']] . ' , affichage : ' . $value['pub'];
+ return $corpsList[$value['current']] . ', ' . $corpsList[$value['rank']] . ' ('
+ . 'corps d\'origine : ' . $corpsList[$value['original']] . ', affichage ' . $pubs[$value['pub']] . ')';
}
}
require_once 'emails.combobox.inc.php';
fill_email_combobox($page, $this->owner);
- $res = XDB::iterator("SELECT id, name
- FROM profile_corps_enum
- ORDER BY id = 1 DESC, name");
- $page->assign('original_corps', $res->fetchAllAssoc());
+ if (!S::user()->isMe($this->owner)) {
+ $res = XDB::iterator('SELECT id, name
+ FROM profile_corps_enum
+ ORDER BY id = 1 DESC, name');
+ $page->assign('original_corps', $res->fetchAllAssoc());
+ }
$res = XDB::iterator("SELECT id, name
FROM profile_corps_enum
$success = true;
if (is_null($value)) {
$value = array();
- $res = XDB::iterRow("SELECT m.country, gc.countryFR
+ $res = XDB::iterRow("SELECT m.country, gc.country
FROM profile_mentor_country AS m
INNER JOIN geoloc_countries AS gc ON (m.country = gc.iso_3166_1_a2)
WHERE m.pid = {?}",
public function _prepare(PlPage &$page, $id)
{
- $page->assign('countryList', XDB::iterator("SELECT iso_3166_1_a2, countryFR
+ $page->assign('countryList', XDB::iterator("SELECT iso_3166_1_a2, country
FROM geoloc_countries
- ORDER BY countryFR"));
+ ORDER BY country"));
$page->assign('hrpid', $this->profile->hrpid);
}
}
public function save(ProfilePage &$page, $field, $value)
{
- Phone::deletePhones($page->pid(), Phone::LINK_PROFILE);
+ Phone::deletePhones($page->pid(), Phone::LINK_PROFILE, null, S::user()->isMe($page->owner) || S::admin());
Phone::savePhones($value, $page->pid(), Phone::LINK_PROFILE);
}
}
public function getText($value) {
- return $value;
+ static $pubs = array('public' => 'publique', 'ax' => 'annuaire AX', 'private' => 'privé');
+ return $pubs[$value];
}
}
$success = preg_match('@(\d{2})/(\d{2})/(\d{4})@', $value, $matches);
if (!$success) {
Platal::page()->trigError("Les dates doivent être au format jj/mm/aaaa");
- } else {
+ } else {
$day = (int)$matches[1];
$month = (int)$matches[2];
$year = (int)$matches[3];
if ($this->changed[$field]) {
if (!is_null($setting)) {
$changedFields[$field] = array(
- str_replace("\n", " - ", $setting->getText($this->orig[$field])),
- str_replace("\n", " - ", $setting->getText($this->values[$field])),
+ preg_replace('/(\r\n|\n|\r)/', ' - ', $setting->getText($this->orig[$field])),
+ preg_replace('/(\r\n|\n|\r)/', ' - ', $setting->getText($this->values[$field])),
);
} else {
$changedFields[$field] = array(
- str_replace("\n", " - ", $this->orig[$field]),
- str_replace("\n", " - ", $this->values[$field]),
+ preg_replace('/(\r\n|\n|\r)/', ' - ', $this->orig[$field]),
+ preg_replace('/(\r\n|\n|\r)/', ' - ', $this->values[$field]),
);
}
if (!is_null($setting)) {
global $platal;
S::logger()->log('profil', $platal->pl_self(2));
- /** If the update was made by a third party and the profile corresponds
- * to a registered user, stores both former and new text.
- * This will be daily sent to the user.
+ /** Stores all profile modifications for active users in order to:
+ * -daily notify the user in case of third party edition,
+ * -display the modification to the secretaries for verification in
+ * case of an edition made by the user.
*/
$owner = $this->profile->owner();
$user = S::user();
- if ($owner->isActive() && $owner->id() != $user->id()) {
+ if ($owner->isActive()) {
foreach ($changedFields as $field => $values) {
- XDB::execute('INSERT INTO profile_modifications (pid, uid, field, oldText, newText)
- VALUES ({?}, {?}, {?}, {?}, {?})
- ON DUPLICATE KEY UPDATE oldText = VALUES(oldText), newText = VALUES(newText)',
- $this->pid(), $user->id(), $field, $values[0], $values[1]);
+ XDB::execute('INSERT INTO profile_modifications (pid, uid, field, oldText, newText, type, timestamp)
+ VALUES ({?}, {?}, {?}, {?}, {?}, {?}, NOW())
+ ON DUPLICATE KEY UPDATE uid = VALUES(uid), oldText = IF(VALUES(type) != type, VALUES(oldText), oldText),
+ newText = VALUES(newText), type = VALUES(type), timestamp = NOW()',
+ $this->pid(), $user->id(), Profile::$descriptions[$field], $values[0], $values[1],
+ ($owner->id() == $user->id()) ? 'self' : 'third_party');
}
}
return true;
public function getText($value) {
$skills = array();
- foreach ($value as $skill) {
- $skills[] = 'Compétance : ' . $skill['text'] . ', niveau : ' . $skill['level'];
+
+ if ($this->table == 'langskill') {
+ static $levels = array(
+ 1 => 'connaissance basique',
+ 2 => 'maîtrise des bases',
+ 3 => 'maîtrise limitée',
+ 4 => 'maîtrise générale',
+ 5 => 'bonne maîtrise',
+ 6 => 'maîtrise complète'
+ );
+ foreach ($value as $skill) {
+ $skills[] = $skill['text'] . ' (' . $levels[$skill['level']] . ')';
+ }
+ } else {
+ foreach ($value as $skill) {
+ $skills[] = $skill['text'] . ' (' . $skill['level'] . ')';
+ }
}
- return implode(' ; ' , $skills);
+
+ return implode(', ' , $skills);
}
}
$nameTypes = DirEnum::getOptions(DirEnum::NAMETYPES);
$nameTypes = array_flip($nameTypes);
$res = XDB::query("SELECT a.uid, pd.promo, pnl.name AS lastname, pnf.name AS firstname, p.xorg_id AS xorgid,
- p.birthdate_ref AS birthdateRef, FIND_IN_SET('watch', a.flags) AS watch, m.hash
+ p.birthdate_ref AS birthdateRef, FIND_IN_SET('watch', a.flags) AS watch, m.hash, a.type as eduType
FROM register_marketing AS m
INNER JOIN accounts AS a ON (m.uid = a.uid)
INNER JOIN account_profiles AS ap ON (a.uid = ap.uid AND FIND_IN_SET('owner', ap.perms))
}
// Register the optional services requested by the user.
+ if ($subState->v('eduType') == 'x') {
+ $proposedServices = array('ax_letter', 'imap', 'ml_promo', 'nl');
+ } else {
+ $proposedServices = array('ax_letter', 'nl');
+ }
$services = array();
- foreach (array('ax_letter', 'imap', 'ml_promo', 'nl') as $service) {
+ foreach ($proposedServices as $service) {
if (Post::b($service)) {
$services[] = $service;
}
$res = XDB::query("SELECT r.uid, p.pid, r.forlife, r.bestalias, r.mailorg2,
r.password, r.email, r.services, r.naissance,
pnl.name AS lastname, pnf.name AS firstname,
- pd.promo, p.sex, p.birthdate_ref
+ pd.promo, p.sex, p.birthdate_ref, a.type AS eduType
FROM register_pending AS r
INNER JOIN accounts AS a ON (r.uid = a.uid)
INNER JOIN account_profiles AS ap ON (a.uid = ap.uid AND FIND_IN_SET('owner', ap.perms))
}
list($uid, $pid, $forlife, $bestalias, $emailXorg2, $password, $email, $services,
- $birthdate, $lastname, $firstname, $promo, $sex, $birthdate_ref) = $res->fetchOneRow();
+ $birthdate, $lastname, $firstname, $promo, $sex, $birthdate_ref, $eduType) = $res->fetchOneRow();
+ $isX = ($eduType == 'x');
$yearpromo = substr($promo, 1, 4);
// Prepare the template for display.
// Add the registration email address as first and only redirection.
require_once 'emails.inc.php';
$user = User::getSilentWithUID($uid);
- $redirect = new Redirect($user);
- $redirect->add_email($email);
+ if ($isX) {
+ $redirect = new Redirect($user);
+ $redirect->add_email($email);
+ } else {
+ XDB::execute('UPDATE accounts
+ SET email = {?}
+ WHERE uid = {?}', $email, $uid);
+ }
// Try to start a session (so the user don't have to log in); we will use
// the password available in Post:: to authenticate the user.
// Congratulate our newly registered user by email.
$mymail = new PlMailer('register/success.mail.tpl');
+ if ($isX) {
+ $mymail->addTo("\"{$user->fullName()}\" <{$user->forlifeEmail()}>");
+ $mymail->setSubject('Bienvenue parmi les X sur le web !');
+ } else {
+ $mymail->addTo($email);
+ $mymail->setSubject('Bienvenue sur Polytechnique.org !');
+ }
$mymail->assign('forlife', $forlife);
$mymail->assign('firstname', $firstname);
$mymail->send();
$page->assign('formulaire', 0);
require_once 'userset.inc.php';
- $view = new SearchSet(true);
+ $view = new QuickSearchSet();
$view->addMod('minifiche', 'Mini-fiches', true, array('with_score' => true, 'starts_with' => $byletter));
if (S::logged() && !Env::i('nonins')) {
$view->addMod('trombi', 'Trombinoscope', false, array('with_promo' => true, 'with_score' => true));
}
require_once 'userset.inc.php';
- $view = new SearchSet(false);
+ // Enable X.org fields for X.org admins, and AX fields for AX secretaries.
+ $view = new AdvancedSearchSet(S::admin(),
+ S::user()->checkPerms(User::PERM_EDIT_DIRECTORY));
+
if (!$view->isValid()) {
$this->form_prepare();
$page->trigError('Recherche invalide.');
$view->addMod('trombi', 'Trombinoscope', false, array('with_promo' => true));
// TODO: Reactivate when the new map is completed.
// $view->addMod('geoloc', 'Planisphère', false, array('with_annu' => 'search/adv'));
+ if (S::user()->checkPerms(User::PERM_EDIT_DIRECTORY) || S::admin()) {
+ $view->addMod('addresses', 'Adresses postales', false);
+ }
$view->apply('search/adv', $page, $model);
$nb_tot = $view->count();
if ($nb_tot > $globals->search->private_max) {
$this->form_prepare();
+ if ($model != 'addresses' && (S::user()->checkPerms(User::PERM_EDIT_DIRECTORY) || S::admin())) {
+ $page->assign('suggestAddresses', true);
+ }
$page->trigError('Recherche trop générale.');
} else if ($nb_tot == 0) {
$this->form_prepare();
pl_content_headers("text/xml");
$page->changeTpl('include/field.select.tpl', NO_SKIN);
$page->assign('name', 'country');
- $it = XDB::iterator("SELECT gc.iso_3166_1_a2 AS id, gc.countryFR AS field
+ $it = XDB::iterator("SELECT gc.iso_3166_1_a2 AS id, gc.country AS field
FROM geoloc_countries AS gc
INNER JOIN profile_mentor_country AS mp ON (mp.country = gc.iso_3166_1_a2)
INNER JOIN profile_mentor_term AS mt ON (mt.pid = mp.pid)
INNER JOIN profile_job_term_relation AS jtr ON (jtr.jtid_2 = mt.jtid)
WHERE jtr.jtid_1 = {?}
GROUP BY iso_3166_1_a2
- ORDER BY countryFR", $jtid);
+ ORDER BY country", $jtid);
$page->assign('list', $it);
}
}
return PL_NOT_FOUND;
}
- pl_content_headers("text/x-csv");
+ pl_cached_content_headers('text/x-csv', 1);
$page->changeTpl('xnetevents/csv.tpl', NO_SKIN);
$admin = may_update();
$filename = $globals->asso('diminutif') . '.csv';
}
$users = $globals->asso()->getMembersFilter(null, new UFO_Name('directory_name'))->getUsers();
- pl_content_headers("text/x-csv");
+ pl_cached_content_headers('text/x-csv', 1);
$page->changeTpl('xnetgrp/annuaire-csv.tpl', NO_SKIN);
$page->assign('users', $users);
}
function select_nat($valeur, $pad=false) {
- $res = XDB::iterRow("SELECT iso_3166_1_a2 AS id, nationalityFR AS text
+ $res = XDB::iterRow("SELECT iso_3166_1_a2 AS id, nationality AS text
FROM geoloc_countries
- WHERE nationalityFR IS NOT NULL
- ORDER BY nationalityFR");
+ WHERE nationality IS NOT NULL
+ ORDER BY nationality");
$sel = ' selected="selected"';
// on ajoute une entree vide si $pad est vrai
<a href="admin/names">Noms</a>
|
<a href="admin/networking">Networking</a>
+ |
+ <a href="admin/profile">Modifications récentes</a>
</td>
</tr>
<tr class="pair">
--- /dev/null
+{**************************************************************************}
+{* *}
+{* Copyright (C) 2003-2010 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>Modifications récentes de profil</h1>
+
+{if $updates->total() > 0}
+<script type="text/javascript">//<![CDATA[
+{literal}
+ function toggleSelection()
+ {
+ var checked = $(':checkbox.updates:checked');
+ var unchecked = $(':checkbox.updates:not(:checked)');
+ checked.removeAttr('checked');
+ unchecked.attr('checked', 'checked');
+ }
+{/literal}
+//]]></script>
+
+<form action="admin/profile" method="post">
+ {xsrf_token_field}
+ <table class="bicol" summary="liste des modifications de profil récentes">
+ <tr>
+ <th>Nom</th>
+ <th>Éléments modifiés</th>
+ <th>Liens</th>
+ <th><a href="javascript:toggleSelection()">{icon name="arrow_refresh" title="Inverser la sélection"}</a></th>
+ </tr>
+ {iterate item=update from=$updates}
+ <tr class="{cycle values="impair,pair"}">
+ <td>{$update.directory_name}</td>
+ <td class="center">{$update.field|wordwrap:80:'<br />'}</td>
+ <td class="center">
+ <a href="profile/{$update.hrpid}" class="popup2">{icon name=user_suit title="Voir le profil"}</a>
+ <a href="profile/edit/{$update.hrpid}">{icon name=user_edit title="Éditer le profil"}</a>
+ </td>
+ <td class="center"><input type="checkbox" name="checked_{$update.pid}" class="updates" /></td>
+ </tr>
+ {/iterate}
+ </table>
+ <p class="center"><input type="submit" name="checked" value="Valider" /></p>
+</form>
+{else}
+<p>Il n'y a rien à vérifier.</p>
+{/if}
+
+{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
{iterate item=valid from=$vit}
{assign var=type value=$valid->type}
-{if !t($hide_requests[$type])}
+{if !t($hide_requests[$type]) && !($valid->requireAdmin && !$isAdmin)}
<br />
<table class="bicol">
<tr>
{/foreach}
{/foreach}
-{include file="signature.mail.tpl"}
+{include file="include/signature.mail.tpl"}
''Note :'' Tu reçois cet email car tu as activé la notification automatique par email des événements que tu surveilles.\\
Tu peux changer cette option sur la [[https://www.polytechnique.org/carnet/notifs|page de configuration des notifications]].
Pour plus de renseignements sur le service de patte cassée, n'hésite pas à
consulter [[{$globals->baseurl}/emails/broken|la documentation sur le site]].
-{include file="signature.mail.tpl"}
+{include file="include/signature.mail.tpl"}
{/if}
{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
https://www.polytechnique.org/emails/redirect
-{include file="signature.mail.tpl"}
+{include file="include/signature.mail.tpl"}
---------------------------------------------------------------------------
PS : si jamais tu ne disposes plus du mot de passe te permettant
Puis cliquez sur le lien suivant pour valider cette demande :
* {$baseurl}/emails/rewrite/in/{$mail->email|replace:'@':'_'}/{$mail->hash}
-{include file="signature.mail.tpl"}
+{include file="include/signature.mail.tpl"}
{/if}
{* vim:set et sw=2 sts=2 sws=2: *}
N'hésite pas à venir découvrir ou redécouvrir les services du site grâce au [[https://www.polytechnique.org/review|tour d'horizon]].
Merci encore de la confiance que tu portes à nos services.
-{include file="signature.mail.tpl"}
+{include file="include/signature.mail.tpl"}
{/if}
{* vim:set et sw=2 sts=2 sws=2: *}
--- /dev/null
+{**************************************************************************}
+{* *}
+{* Copyright (C) 2003-2010 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 *}
+{* *}
+{**************************************************************************}
+
+<h2><a href="fusionax">Fusion des annuaires X.org - AX</a> / corps</h2>
+
+<p>
+ Il y a {$missingCorpsCount} corps manquant{if $missingCorpsCount > 1}s{/if} dans notre base{if $missingCorpsCount eq 0}.</p>{else} :
+</p>
+<ul>
+ {iterate from=$missingCorps item=corps}<li>{$corps.name}</li>{/iterate}
+</ul>{/if}
+
+<p>
+ Il y a {$missingGradeCount} grade{if $missingGradeCount > 1}s{/if} manquant{if $missingGradeCount > 1}s{/if} dans
+ notre base{if $missingGradeCount eq 0}.</p>{else} :
+</p>
+<ul>
+ {iterate from=$missingGrade item=grade}<li>{$grade.name}</li>{/iterate}
+</ul>{/if}
+
+{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
<li>Corrélation des <a href="fusionax/promo">promotions</a></li>
<li>Corrélation des <a href="fusionax/names">noms</a></li>
<li>Corrélation des <a href="fusionax/edu">formations</a></li>
+ <li>Corrélation des <a href="fusionax/corps">corps</a></li>
</ul>
<p>
<textarea cols="30" rows="4" class="valid {$prefid}_geoloc">{$address.geocodedText}</textarea>
{/if}
</div>
+{if !$isMe}<div><small><strong>Adress postale :</strong><br />{$address.postalText|nl2br}</small></div>{/if}
{if t($address.geocodedText)}
<input type="hidden" name="{$prefname}[geocodeChosen]" value="1" />
<input type="hidden" name="{$prefname}[geocodedText]" value="{$address.geocodedText}" />
-<input type="hidden" name="{$prefname}[geocodedPostalText]" value="{$address.geocodedPostalText}" />
{/if}
<input type="hidden" name="{$prefname}[accuracy]" value="{$address.accuracy}" />
<input type="hidden" name="{$prefname}[postalText]" value="{$address.postalText}" />
{/if}
Tu trouveras plus d'informations dans la [[https://www.polytechnique.org/Xorg/GoogleApps|documentation]] sur Polytechnique.org.
-{include file="signature.mail.tpl"}
+{include file="include/signature.mail.tpl"}
{/if}
{* vim:set et sw=2 sts=2 sws=2: *}
{/if}
Tu trouvera plus d'information dans la [[https://www.polytechnique.org/Xorg/GoogleApps|documentation]] sur Polytechnique.org.
-{include file="signature.mail.tpl"}
+{include file="include/signature.mail.tpl"}
{/if}
{* vim:set et sw=2 sts=2 sws=2: *}
{assign var=new value="new"|cat:$i}
{assign var=combobox value="combobox"|cat:$i}
-<tr {if $class}class="{$class}"{/if}>
+<tr{if $class} class="{$class}"{/if}{if t($divId)} id="{$divId}"{/if}>
<td class="titre">
{if $name eq "email_directory"}
Email annuaire AX
<input type="checkbox" disabled="disabled" checked="checked"/>
{icon name="flag_orange" title="Visible sur l'annuaire"}
{elseif $name neq "email"}
+ {if t($mainField)}
+ {include file="include/flags.radio.tpl" name="`$jobpref`[`$prefix`email_pub]" val=$pub
+ mainField=$mainField mainId=$mainId subField=$subField subId=$subId}
+ {else}
{include file="include/flags.radio.tpl" name="`$jobpref`[`$prefix`email_pub]" val=$pub}
{/if}
+ {/if}
</div>
{/if}
</td>
{if t($withtext)}
<a href="Xorg/FAQ?display=light#flags" class="popup_800x240">Quelle couleur ?</a>
{/if}
-{if !t($val)}{assign var=val value='private'}{/if}
+{if !t($val)}{assign var=val value='ax'}{/if}
<label><input type="radio" name="{$name}" value="public"{if $val eq 'public'} checked="checked"{/if}
- {if t($disabled)}disabled="disabled"{/if} />
+ {if t($disabled)}disabled="disabled"{/if}{if t($mainField)} onchange="updatePublicity('{$mainField}','{$mainId}','{$subField}','{$subId}')"{/if} />
{icon name="flag_green" title="site public"}
{if t($withtext)}<span class="texte">site public</span>{/if}</label>
<label><input type="radio" name="{$name}" value="ax"{if $val eq 'ax'} checked="checked"{/if}
- {if t($disabled)}disabled="disabled"{/if} />
+ {if t($disabled)}disabled="disabled"{/if}{if t($mainField)} onchange="updatePublicity('{$mainField}','{$mainId}','{$subField}','{$subId}')"{/if} />
{icon name="flag_orange" title="transmis à l'AX"}
{if t($withtext)}<span class="texte">transmis à l'AX</span>{/if}</label>
<label><input type="radio" name="{$name}" value="private"{if $val eq 'private'} checked="checked"{/if}
- {if t($disabled)}disabled="disabled"{/if} />
+ {if t($disabled)}disabled="disabled"{/if}{if t($mainField)} onchange="updatePublicity('{$mainField}','{$mainId}','{$subField}','{$subId}')"{/if} />
{icon name="flag_red" title="privé"}
{if t($withtext)}<span class="texte">privé</span>{/if}</label>
{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
<form method='post' action='{$smarty.server.REQUEST_URI}'>
{xsrf_token_field}
<table class='tinybicol' cellpadding='0' cellspacing='0'>
- {foreach from=$owners item=users key=alpha}
- {foreach from=$users item=user name=all}
- <tr>
- <td class='titre' style="width: 20%">
- {if $smarty.foreach.all.first}
- {if $alpha}{$alpha}{/if}
- {/if}
- </td>
- <td>
- {if t($user.x)}
- {if t($user.b)}{assign var=lostUsers value=true}{/if}
- {profile user=$user.x promo=false}
- {elseif t($user.x)}
- <a href="{$platal->ns}member/{$user.x}">{if $user.n|trim}{$x.n}{else}{$user.l}{/if}</a>
- {elseif t($user.n)}
- {$user.n}
- {else}
- {$user.l}
- {/if}
- <a href='{$platal->pl_self(1)}?del_owner={$user.l}&token={xsrf_token}'>{icon name=cross title='retirer modérateur'}</a>
- </td>
- </tr>
- {/foreach}
- {/foreach}
+ {include file='lists/display_list.tpl' list=$owners delete='del_owner' no_sort_key='' promo=true}
<tr class="pair">
<td class='titre'>Ajouter</td>
- <td>
+ <td colspan="2">
<input type='text' size='30' name='add_owner' />
<input type='submit' value='ajouter' />
</td>
<form method='post' action='{$smarty.server.REQUEST_URI}' enctype="multipart/form-data">
{xsrf_token_field}
<table class='bicol' cellpadding='0' cellspacing='0'>
- {foreach from=$members item=users key=alpha}
- {foreach from=$users item=user name=all}
+ {include file='lists/display_list.tpl' list=$members delete='del_member' no_sort_key='' promo=true}
<tr>
- <td class='titre' style="width: 20%">
- {if $smarty.foreach.all.first}
- {if $alpha}{$alpha}{/if}
- {/if}
- </td>
- <td>
- {if t($user.x)}
- {if t($user.b)}{assign var=lostUsers value=true}{/if}
- {profile user=$user.x promo=false}
- {elseif t($user.x)}
- <a href="{$platal->ns}member/{$user.x}">{if $user.n|trim}{$x.n}{else}{$user.l}{/if}</a>
- {elseif t($user.n)}
- {$user.n}
- {else}
- {$user.l}
- {/if}
- <a href='{$platal->pl_self(1)}?del_member={$user.l}&token={xsrf_token}'>{icon name=cross title='retirer membre'}</a>
- </td>
- </tr>
- {/foreach}
- {/foreach}
- <tr>
- <th colspan="2">Ajouter</th>
+ <th colspan="3">Ajouter</th>
</tr>
<tr class="pair">
<td class="titre">Liste</td>
- <td>
+ <td colspan="2">
<input type='text' size='40' name='add_member' />
</td>
</tr>
<tr class="pair">
<td class="titre">ou fichier(*)</td>
- <td>
+ <td colspan="2">
<input type="file" name="add_member_file" />*
</td>
</tr>
<tr class="pair">
- <td colspan="2" class="center">
+ <td colspan="3" class="center">
<input type='submit' value='ajouter' />
</td>
</tr>
--- /dev/null
+{**************************************************************************}
+{* *}
+{* Copyright (C) 2003-2010 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 *}
+{* *}
+{**************************************************************************}
+
+{assign var=lostUsers value=false}
+{foreach from=$list item=users key=sort_key}
+{foreach from=$users item=user name=all}
+<tr>
+ <td class='titre' style="width: 20%">
+ {if $smarty.foreach.all.first}
+ {if $sort_key neq 'AAAAA'}{$sort_key}{else}{$no_sort_key}{/if}
+ {/if}
+ </td>
+ <td>
+ {if t($user.hasProfile)}
+ {if t($user.lost)}{assign var=lostUsers value=true}{/if}
+ {profile user=$user.uid promo=$promo}
+ {elseif t($user.uid)}
+ {if t($user.name)}{$user.name}{else}{$user.email}{/if}{if t($promo)} (extérieur){/if}
+ {elseif t($user.name)}
+ {$user.name}
+ {else}
+ {$user.email}
+ {/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>
+ {else}
+ {icon name=null}
+ {/if}
+ <a href='{$platal->pl_self(1)}?{$delete}={$user.email}&token={xsrf_token}'>{icon name=cross title='Retirer'}</a>
+ </td>
+ {/if}
+</tr>
+{/foreach}
+{/foreach}
+
+{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
{if $owners|@count}
<table class='tinybicol' cellpadding='0' cellspacing='0'>
- {foreach from=$owners item=xs key=promo}
- {foreach from=$xs item=user name=all}
- <tr>
- <td class='titre'>
- {if $smarty.foreach.all.first}
- {if $promo}{$promo}{else}non-X{/if}
- {/if}
- </td>
- <td>
- {if $promo && $user.x}
- {if $user.b}{assign var=lostUsers value=true}{/if}
- {profile user=$user.x promo=false}
- {elseif $user.x}
- <a href="{$platal->ns}member/{$user.x}">{if $user.n|trim}{$x.n}{else}{$user.l}{/if}</a>
- {elseif $user.n}
- {$user.n}
- {else}
- {$user.l}
- {/if}
- </td>
- {if $user.p}
- <td class="right">
- {$user.p}
- </td>
- {/if}
- </tr>
- {/foreach}
- {/foreach}
+ {include file='lists/display_list.tpl' list=$owners delete=false no_sort_key='non-X' promo=$smarty.get.alpha}
</table>
{/if}
{if $members|@count}
<table class='bicol' cellpadding='0' cellspacing='0'>
{if $details.own || hasPerms('admin,groupadmin')}
- <tr><td colspan="3">
+ <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=lostUsers value=false}
- {foreach from=$members item=users key=promo}
- {foreach from=$users item=user name=all}
- <tr>
- <td class='titre' style="width: 20%">
- {if $smarty.foreach.all.first}
- {if $promo}{$promo}{else}non-X{/if}
- {/if}
- </td>
- <td>
- {if $promo && $user.x}
- {if $user.b}{assign var=lostUsers value=true}{/if}
- {profile user=$user.x promo=false}
- {elseif $user.x}
- <a href="{$platal->ns}member/{$user.x}">{if $user.n|trim}{$x.n}{else}{$user.l}{/if}</a>
- {elseif $user.n}
- {$user.n}
- {else}
- {$user.l}
- {/if}
- </td>
- {if $user.p}
- <td class="right">
- {$user.p}
- </td>
- {/if}
- </tr>
- {/foreach}
- {/foreach}
+ {include file='lists/display_list.tpl' list=$members delete=false no_sort_key='non-X' promo=$smarty.get.alpha}
</table>
-{if $lostUsers}
+{if t($lostUsers)}
<p class="smaller">
{icon name=error} Un camarade signalé par ce symbole n'a plus d'adresse de redirection et ne peut donc
plus être contacté via son adresse polytechnique.org. Si tu connais sa nouvelle adresse, tu peux nous la communiquer en
Si le lien ci-dessus ne fonctionne pas en cliquant dessus, copie le intégralement dans la barre d'adresse de ton navigateur.
En cas de difficulté, nous sommes bien entendu à ton entière disposition !
-{include file="signature.mail.tpl"}
+{include file="include/signature.mail.tpl"}
{/if}
{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
</tr>
{if $comment}
<tr>
- <td><b>Commentaire</b>
+ <td><b>Commentaire</b></td>
<td>{$comment}</td>
</tr>
{/if}
</tr>
</table>
<p>
-En cliquant sur "Valider", tu seras redirigé{if $smarty.session.sexe}e{/if} vers le site de {$pay->api->nomsite}, où il te
+En cliquant sur "Valider", tu seras redirigé{if $sex}e{/if} vers le site de {$pay->api->nomsite}, où il te
sera demandé de saisir ton numéro de carte bancaire. Lorsque le paiement aura été effectué, tu
recevras une confirmation par email.
</p>
<tr {if $hiddenaddr}style="display: none"{/if}>
<td>
<div style="margin-bottom: 0.2em" class="flags">
- {include file="include/flags.radio.tpl" name="`$prefname`[pub]" val=$address.pub}
+ {include file="include/flags.radio.tpl" name="`$prefname`[pub]" val=$address.pub mainField='addresses' mainId=$i subField='phones' subId=-1}
</div>
<div style="clear: both"></div>
<div style="float: left">
on peut {if $isMe}m'{/if}y envoyer du courrier par la poste
</label>
</div>
+ {if !t($isMe)}
+ <div>
+ <label>
+ <input type="checkbox" name="{$prefname}[deliveryIssue]" {if $address.deliveryIssue}checked="checked"{/if} />
+ n'habite pas à l'adresse indiquée
+ </label>
+ </div>
+ {else}
+ <div style="display: none"><input type="hidden" name="deliveryIssue" value="{$address.deliveryIssue}" /></div>
+ {/if}
<div>
<label>
Commentaire :
<tr class="pair" {if $hiddenaddr}style="display: none"{/if}>
<td>
{foreach from=$address.phones key=t item=tel}
- <div id="{"`$prefid`_tel_`$t`"}" style="clear: both">
- {include file="profile/phone.tpl" prefname="`$prefname`[phones]"
- prefid="`$prefid`_tel" telid=$t tel=$tel}
+ <div id="{"`$prefid`_phones_`$t`"}" style="clear: both">
+ {include file="profile/phone.tpl" prefname="`$prefname`[phones]" prefid="`$prefid`_phones" telid=$t tel=$tel
+ subField='phones' mainField='addresses' mainId=$i}
</div>
{/foreach}
{if $address.phones|@count eq 0}
- <div id="{"`$prefid`_tel_0"}" style="clear: both">
- {include file="profile/phone.tpl" prefname="`$prefname`[phones]" prefid="`$prefid`_tel" telid=0 tel=0}
+ <div id="{"`$prefid`_phones_0"}" style="clear: both">
+ {include file="profile/phone.tpl" prefname="`$prefname`[phones]" prefid="`$prefid`_phones" telid=0 tel=0
+ subField='phones' mainField='addresses' mainId=$i}
</div>
{/if}
- <div id="{$prefid}_tel_add" class="center" style="clear: both; padding-top: 4px">
- <a href="javascript:addTel('{$prefid}_tel','{$prefname}[phones]')">
+ <div id="{$prefid}_phones_add" class="center" style="clear: both; padding-top: 4px">
+ <a href="javascript:addTel('{$prefid}_phones','{$prefname}[phones]','phones','addresses','{$i}')">
{icon name=add title="Ajouter un numéro de téléphone"} Ajouter un numéro de téléphone
</a>
</div>
</div>
{/if}
<div id="tels_add" class="center" style="clear: both; padding-top: 4px;">
- <a href="javascript:addTel('tels','tels');">
+ <a href="javascript:addTel('tels','tels',null,null,null);">
{icon name=add title="Ajouter un téléphone"} Ajouter un téléphone
</a>
</div>
'''Version geoloc (refusée) :'''\\
{$geoloc|replace:"\n":"\\\\\n"}
-{include file="signature.mail.tpl"}
+{include file="include/signature.mail.tpl"}
{/if}
{* vim:set et sw=2 sts=2 sws=2: *}
<script type="text/javascript" src="javascript/jquery.jstree.js"></script>
-{assign var=jobid value="job_"|cat:$i}
+{assign var=jobid value="jobs_"|cat:$i}
{assign var=jobpref value="jobs[`$i`]"}
{assign var=sector_text value="sector_text_"|cat:$i}
{assign var=sector value="sector_"|cat:$i}
<tr>
<th colspan="2" style="text-align: right">
<div class="flags" style="float: left; text-align: left">
- {include file="include/flags.radio.tpl" name="`$jobpref`[pub]" val=$job.pub disabled=$hiddenjob}
+ {include file="include/flags.radio.tpl" name="`$jobpref`[pub]" val=$job.pub disabled=$hiddenjob
+ mainField='jobs' mainId=$i subField='w_address,w_email,w_phone' subId=-1}
</div>
Entreprise n°{$i+1} :
{if $hiddenjob}
</tr>
<tr class="pair" id="{$sector_text}" {if $hiddenjob}style="display: none"{/if}>
<td class="titre">Mots-clefs</td>
- <td class="job_terms">
+ <td class="jobs_terms">
<input type="text" class="term_search" size="35"/>
<a href="javascript:toggleJobTermsTree({$i})">{icon name="table" title="Tous les mots-clefs"}</a>
<script type="text/javascript">
{foreach from=$job.terms item=term}
addJobTerm("{$i}", "{$term.jtid}", "{$term.full_name|replace:'"':'\\"'}");
{/foreach}
- $('#job_{$i} .term_search').autocomplete(platal_baseurl + 'profile/jobterms',
+ $('#jobs_{$i} .term_search').autocomplete(platal_baseurl + 'profile/jobterms',
{ldelim}
"formatItem" : displayJobTerm,
"extraParams" : {ldelim} "jobid" : "{$i}" {rdelim},
- "width" : $('#job_{$i} .term_search').width()*2,
+ "width" : $('#jobs_{$i} .term_search').width()*2,
"onItemSelect" : selectJobTerm,
"matchSubset" : false
{rdelim});
name="{$jobpref}[w_url]" value="{$job.w_url}" />
</td>
</tr>
- <tr class="pair" {if $hiddenjob}style="display: none"{/if}>
+ <tr id="{$jobid}_w_address" class="pair" {if $hiddenjob}style="display: none"{/if}>
<td colspan="2">
<div style="float: left">
<div class="titre">Adresse</div>
<div class="flags">
- {include file="include/flags.radio.tpl" name="`$jobpref`[w_address][pub]" val=$job.w_address.pub}
+ {include file="include/flags.radio.tpl" name="`$jobpref`[w_address][pub]" val=$job.w_address.pub
+ subField='w_address' mainField='jobs' mainId=$i subId=''}
</div>
<div style="margin-top: 20px; clear: both">
{include file="geoloc/form.address.tpl" prefname="`$jobpref`[w_address]"
</tr>
{else}
{include file="include/emails.combobox.tpl" name=$jobpref|cat:'[w_email]' val=$job.w_email
- class="pair" i=$i error=$job.w_email_error prefix="w_" pub=$job.w_email_pub id=$i}
+ class="pair" divId="`$jobid`_w_email" i=$i error=$job.w_email_error prefix="w_" pub=$job.w_email_pub id=$i
+ subField='w_email' mainField='jobs' mainId=$i subId=''}
{/if}
<tr class="pair" {if $hiddenjob}style="display: none"{/if}>
<td colspan="2">
{foreach from=$job.w_phone key=t item=phone}
<div id="{"`$jobid`_w_phone_`$t`"}" style="clear: both">
- {include file="profile/phone.tpl" prefname="`$jobpref`[w_phone]" prefid="`$jobid`_w_phone" telid=$t tel=$phone}
+ {include file="profile/phone.tpl" prefname="`$jobpref`[w_phone]" prefid="`$jobid`_w_phone" telid=$t tel=$phone
+ subField='w_phone' mainField='jobs' mainId=$i}
</div>
{/foreach}
{if $job.w_phone|@count eq 0}
<div id="{"`$jobid`_w_phone_0"}" style="clear: both">
- {include file="profile/phone.tpl" prefname="`$jobpref`[w_phone]" prefid="`$jobid`_w_phone" telid=0 tel=0}
+ {include file="profile/phone.tpl" prefname="`$jobpref`[w_phone]" prefid="`$jobid`_w_phone" telid=0 tel=0
+ subField='w_phone' mainField='jobs' mainId=$i}
</div>
{/if}
<div id="{$jobid}_w_phone_add" class="center" style="clear: both; padding-top: 4px;">
- <a href="javascript:addTel('{$jobid}_w_phone','{$jobpref}[w_phone]')">
+ <a href="javascript:addTel('{$jobid}_w_phone','{$jobpref}[w_phone]','w_phone','jobs','{$i}')">
{icon name=add title="Ajouter un numéro de téléphone"} Ajouter un numéro de téléphone
</a>
</div>
<tr>
<td class="titre">Corps d'origine</td>
<td>
+ {if $isMe}
+ {$corps.originalText}
+ <input type="hidden" name="corps[original]" value="{$corps.original}" />
+ <input type="hidden" name="corps[originalText]" value="{$corps.originalText}" />
+ {else}
<select name="corps[original]">
{foreach from=$original_corps item=o_corps}
<option value="{$o_corps.id}" {if $o_corps.id eq $corps.original}selected="selected"{/if}>{$o_corps.name}</option>
{/foreach}
</select>
+ <input type="hidden" name="corps[originalText]" value="{$corps.originalText}" />
+ {/if}
</td>
</tr>
<tr>
<div>{icon name=information title="Afficher ma fiche référent"}Tu peux consulter ta <a class="popup2" href="referent/{$hrpid}">fiche référent</a> qui n'est accessible que par les X.
</div>
-{if (!$expertise)||(!($sectors|@count))}
+{if !$expertise || !t($sectors) || !($sectors|@count)}
<br /><div>
<strong>{icon name=error title="Attention"} Attention : pour figurer dans la base de données des mentors, il faut remplir la
dernière case en bas de cette page et avoir au moins un secteur d'activité de prédilection.</strong><br />
Tu peux aussi l'éditer toi-même là :
*{$globals->baseurl}/profile/edit/{$hrpid}
-{include file="signature.mail.tpl"}
+{include file="include/signature.mail.tpl"}
{/if}
</a>
</div>
<div style="float: right" class="flags">
- {include file="include/flags.radio.tpl" name="`$telpref`[pub]"
- val=$tel.pub disabled=$hiddentel}
+ {if t($mainField)}
+ {include file="include/flags.radio.tpl" name="`$telpref`[pub]" val=$tel.pub disabled=$hiddentel
+ mainField=$mainField mainId=$mainId subField=$subField subId=$telid}
+ {else}
+ {include file="include/flags.radio.tpl" name="`$telpref`[pub]" val=$tel.pub disabled=$hiddentel}
+ {/if}
</div>
<div id="{$id}_comment" style="clear: both;{if $tel.comment eq ''} display:none{/if}">
Commentaire :
Si en cliquant dessus tu n'y arrives pas, copie intégralement ce lien dans la barre d'adresse de ton navigateur.
Nous espérons que tu profiteras pleinement des services en ligne de Polytechnique.org ; s'ils te convainquent, n'oublie pas d'en parler aux camarades autour de toi !
-{include file="signature.mail.tpl"}
+{include file="include/signature.mail.tpl"}
{/if}
{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
Commence dès aujourd'hui à communiquer à tes correspondants la nouvelle adresse que tu comptes utiliser !
En nous excusant pour le désagrément occasionné,
-{include file="signature.mail.tpl"}
+{include file="include/signature.mail.tpl"}
{/if}
{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
Nous t'écrivons pour t'informer que {$firstname} {$lastname} ({$promo}), que tu avais incité{if $sex eq 'female'}e{/if} à s'inscrire à Polytechnique.org, vient à l'instant de terminer son inscription.
Merci de ta participation active à la reconnaissance de ce site !!!
-{include file="signature.mail.tpl"}
+{include file="include/signature.mail.tpl"}
{/if}
{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
<dd>
de recevoir les informations importantes de l'AX.
</dd>
+ {if $smarty.session.subState.eduType eq 'x'}
<dt><label><input type="checkbox" checked="checked" name="ml_promo" /> ta promotion</label></dt>
<dd>
de recevoir les informations plus spécifiques de ta promotion pour pouvoir participer plus facilement aux événements
<dd>
d'avoir un accès de secours aux 30 derniers jours d'emails reçus sur ton adresse Polytechnique.org.
</dd>
+ {/if}
</dl>
</td>
</tr>
{config_load file="mails.conf" section="inscription"}
{if $mail_part eq 'head'}
{from full=#from#}
-{to addr="$forlife@polytechnique.org"}
-{subject text="Bienvenue parmi les X sur le web !"}
{elseif $mail_part eq 'text'}
{$firstname}, félicitations pour ton inscription !
Tu as maintenant accès à l'annuaire en ligne, aux services de listes de
diffusion, aux infos promo, etc. N'oublie pas de mettre ta fiche-annuaire
à jour.
-{include file="signature.mail.tpl"}
+{include file="include/signature.mail.tpl"}
{/if}
{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
<h1>Recherche dans l'annuaire</h1>
+{if hasPerm('edit_directory,admin') && t($suggestAddresses)}
+<p class="center"><strong>Voulez-vous télécharger le <a href="{$globals->baseurl}/search/adv/addresses{$plset_args}">tableau des adresses postales</a> pour la recette précédente ?</strong></p>
+{/if}
+
{javascript name=jquery.form}
<script type="text/javascript">// <!--
</table>
</td>
</tr>
+ {if hasPerm('admin,edit_directory')}
+ <tr>
+ <td>Matricule AX</td>
+ <td>
+ <textarea name="schoolid_ax" rows="10" cols="12">{$smarty.request.schoolid_ax}</textarea>
+ <br />
+ <i>Entrer une liste de matricules AX (un par ligne)</i>
+ </td>
+ {/if}
{if $smarty.session.auth ge AUTH_COOKIE}
<tr>
<td colspan="2">
</table>
{/if}
+{if hasPerm('edit_directory')}
+<div class="menu_title">Administration</div>
+<div class="menu_item"><a href="admin/profile">Modifications</a></div>
+<div class="menu_item"><a href="admin/jobs">Entreprises</a></div>
+<div class="menu_item"><a href="admin/validate">Validations</a></div>
+{/if}
+
{/if}
{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *}
Nous t'écrivons pour t'informer que le télépaiement associé à l'événement '''{$evt}''' du groupe {$asso} vient d'être activé. Tu peux donc finaliser ton inscription.
Pour ceci, va simplement sur [[http://www.polytechnique.net/{$diminutif}/payment/{$payment}?montant={$topay}|cette page]].
-{include file="signature.mail.tpl"}
+{include file="include/signature.mail.tpl"}
{/if}
{* vim:set et sw=2 sts=2 sws=2: *}
{else}
{$user->fullName()} ({$user->forlifeEmail()}) vient d'être désinscrit du groupe par {$smarty.session.user->fullName()}.
{/if}
-{include file="signature.mail.tpl"}
+{include file="include/signature.mail.tpl"}
{/if}
{* vim:set et sw=2 sts=2 sws=2: *}
XDB::rawExecute('DROP TABLE IF EXISTS fusionax_import');
// Fills pid fields in all table, to avoid to many joins.
-foreach (array('fusionax_activites', 'fusionax_adresses', 'fusionax_anciens', 'fusionax_formations') as $table) {
+foreach (array('fusionax_activites', 'fusionax_adresses', 'fusionax_anciens', 'fusionax_formations', 'fusionax_formations_md') as $table) {
XDB::rawExecute("UPDATE $table AS f
INNER JOIN profiles AS p ON (f.ax_id = p.ax_id)
SET f.pid = p.pid");
XDB::rawExecute("DELETE FROM $table WHERE pid IS NULL");
}
+echo "Update timestamp.\n";
+XDB::rawExecute("UPDATE profiles AS p
+ SET p.last_change = GREATEST(COALESCE((SELECT MAX(Date_maj) FROM fusionax_anciens AS f WHERE f.pid = p.pid), '0000-00-00'),
+ COALESCE((SELECT MAX(Date_maj) FROM fusionax_activites AS f WHERE f.pid = p.pid), '0000-00-00'),
+ COALESCE((SELECT MAX(Date_maj) FROM fusionax_adresses AS f WHERE f.pid = p.pid), '0000-00-00'),
+ COALESCE((SELECT MAX(Date_maj) FROM fusionax_formations AS f WHERE f.pid = p.pid), '0000-00-00'),
+ COALESCE(p.last_change, '0000-00-00'))");
+
// Includes entreprises we do not have into profile_job_enum.
// We first retrieve AX code, then add missing compagnies.
echo "Starts jobs inclusions.\n";
// - the job is incomplete (ie no compagny name) : this is an issue,
// - the job is complete but the profile already has a job or more : this is an issue,
// - the job is complete and the the profile has no previous job : there is no issue.
-
// We delete obvious duplicates and avoid multiple joins.
XDB::rawExecute("DELETE f
FROM fusionax_activites AS f
XDB::rawExecute('DROP TABLE IF EXISTS fusionax_entreprises');
// We first update the issues table.
-XDB::rawExecute("INSERT INTO profile_merge_issues (pid, issues)
- SELECT DISTINCT(f.pid), 'job'
- FROM fusionax_activites AS f
- WHERE (f.jobid IS NULL AND NOT EXISTS (SELECT *
- FROM profile_job AS pj
- WHERE pj.pid = f.pid))
- OR (f.jobid IS NOT NULL AND EXISTS (SELECT *
- FROM profile_job AS pj
- WHERE pj.pid = f.pid))");
+XDB::rawExecute("INSERT IGNORE INTO profile_merge_issues (pid, issues)
+ SELECT DISTINCT(f.pid), 'job'
+ FROM fusionax_activites AS f
+ WHERE f.jobid IS NULL OR EXISTS (SELECT *
+ FROM profile_job AS pj
+ WHERE pj.pid = f.pid)");
// We then add new jobs.
$id = 0;
$continue = 1;
FROM fusionax_activites");
XDB::rawExecute("DELETE f
FROM fusionax_activites AS f
- INNER JOIN profile_job AS pj ON (f.pid = pj.pid AND pj.id = $id AND pj.jobid = f.jobid AND pj.description = f.description)");
+ INNER JOIN profile_job AS pj ON (f.pid = pj.pid AND pj.id = $id AND pj.description = f.description)
+ WHERE pj.jobid = f.jobid OR (pj.jobid IS NULL AND f.jobid IS NULL)");
$continue = XDB::affectedRows();
+ ++$id;
}
XDB::rawExecute('DROP TABLE IF EXISTS fusionax_activites');
// We also have to add related phones and addresses.
XDB::rawExecute('ALTER TABLE geoloc_countries DROP INDEX licensePlate');
// Updates corps.
+XDB::rawExecute("INSERT IGNORE INTO profile_corps_enum (name, abbreviation)
+ VALUES ('Ancien élève étranger', 'Z')");
+XDB::rawExecute("INSERT IGNORE INTO profile_corps_rank_enum (name, abbreviation)
+ VALUES ('Ing.ch.P.C.hon.', 'DEL1'), ('Ing.Mil.Air Retr.', 'DEL2'),
+ ('Col.hon.Tra.', 'DEL3'), ('Colonel CR', 'DEL4'),
+ ('Conseil d\'Etat', 'DEL5'), ('Commiss.Gén. Brigade aérienne', 'DEL6'),
+ ('Off. Mar. dém.', 'DEL7'), ('Maître des Requêtes', 'DEL8'),
+ ('', 'DEL9'), ('autres', 'DEL10')");
+XDB::rawExecute('UPDATE profile_corps AS pc
+ INNER JOIN fusionax_anciens AS f ON (f.pid = pc.pid)
+ INNER JOIN profile_corps_enum AS c ON (f.corps_sortie = c.abbreviation)
+ SET pc.original_corpsid = c.id');
XDB::rawExecute("INSERT IGNORE INTO profile_corps (pid, original_corpsid, current_corpsid, rankid, corps_pub)
SELECT f.pid, c.id, c.id, r.id, 'ax'
FROM fusionax_anciens AS f
INNER JOIN profile_corps_enum AS c ON (f.corps_sortie = c.abbreviation)
- INNER JOIN profile_corps_rank_enum AS r ON (f.grade = r.abbreviation)
+ INNER JOIN profile_corps_rank_enum AS r ON (f.grade = r.name)
WHERE NOT EXISTS (SELECT *
FROM profile_corps AS pc
WHERE f.pid = pc.pid AND pc.original_corpsid != 1)");
WHERE name = 'Aucun (anc. démissionnaire)'");
XDB::rawExecute("DELETE FROM profile_corps_enum
WHERE name = 'Ancien élève étranger'");
+XDB::rawExecute("UPDATE profile_corps AS c
+ INNER JOIN profile_corps_rank_enum AS r ON (c.rankid = r.id)
+ INNER JOIN profile_corps_rank_enum AS a ON (a.name = 'Aucun')
+ SET c.rankid = a.id
+ WHERE r.name LIKE 'DEL%'");
+XDB::rawExecute("DELETE FROM profile_corps_rank_enum
+ WHERE name LIKE 'DEL%'");
// Updates email_directory.
XDB::rawExecute("UPDATE profiles AS p
INNER JOIN profile_addresses AS pa ON (pa.pid = f.pid AND pa.type = 'home' AND pa.id = 0)
WHERE f.text IS NOT NULL");
-XDB::rawExecute("INSERT INTO profile_addresses (pid, type, id, pub, text)
- SELECT f.pid, 'home', IF(pa.id IS NULL , 0, MAX(pa.id) + 1), 'ax', f.text
+XDB::rawExecute("INSERT INTO profile_addresses (pid, type, id, pub, text, flags)
+ SELECT f.pid, 'home', IF(pa.id IS NULL , 0, MAX(pa.id) + 1), 'ax', f.text, 'mail'
FROM fusionax_adresses AS f
LEFT JOIN profile_addresses AS pa ON (pa.pid = f.pid AND pa.type = 'home')
WHERE f.text IS NOT NULL
// Retrieves education from AX database. This is the hardest part since AX only kept education as an unformated string.
echo "Starts educations inclusions.\n";
+// Updates master and doctorate educational fields.
+XDB::rawExecute("UPDATE profile_education AS e
+ INNER JOIN fusionax_formations_md AS f ON (f.pid = e.pid AND FIND_IN_SET('primary', e.flags))
+ SET e.program = f.field, e.fieldid = f.fieldid");
+XDB::rawExecute('DROP TABLE IF EXISTS fusionax_formations_md');
+
// Deletes empty educations.
XDB::rawExecute("DELETE FROM fusionax_formations
WHERE Intitule_formation = '' AND Intitule_diplome = '' AND Descr_formation = ''");
// Insert ids into fusionax_formations to prevent many joins.
+XDB::rawExecute('ALTER TABLE profile_education_enum ADD INDEX (name(60))');
+XDB::rawExecute('ALTER TABLE profile_education_degree_enum ADD INDEX (abbreviation(60))');
XDB::rawExecute('UPDATE fusionax_formations AS f
LEFT JOIN profile_education_enum AS pe ON (pe.name = f.Intitule_formation)
LEFT JOIN profile_education_degree_enum AS pd ON (pd.abbreviation = f.Intitule_diplome)
LEFT JOIN profile_education_field_enum AS pf ON (pf.field = f.Descr_formation)
SET f.eduid = pe.id, f.degreeid = pd.id, f.fieldid = pf.id');
+XDB::rawExecute('ALTER TABLE profile_education_enum DROP INDEX name');
+XDB::rawExecute('ALTER TABLE profile_education_degree_enum DROP INDEX abbreviation');
// Updates non complete educations.
XDB::rawExecute("UPDATE profile_education AS e
INNER JOIN fusionax_formations AS f ON (f.pid = e.pid)
FROM fusionax_formations");
XDB::rawExecute("DELETE f
FROM fusionax_formations AS f
- INNER JOIN profile_education AS pe ON (pe.pid = f.pid AND pe.id = $id AND pe.eduid = f.eduid AND pe.degreeid = f.degreeid
- AND pe.fieldid = f.fieldid AND pe.program = f.Descr_formation)");
+ INNER JOIN profile_education AS pe ON (pe.pid = f.pid AND pe.id = $id)
+ WHERE (pe.eduid = f.eduid OR (pe.eduid IS NULL AND f.eduid IS NULL))
+ AND (pe.degreeid = f.degreeid OR (pe.degreeid IS NULL AND f.degreeid IS NULL))
+ AND (pe.fieldid = f.fieldid OR (pe.fieldid IS NULL AND f.fieldid IS NULL))
+ AND (pe.program = f.Descr_formation OR (pe.program IS NULL AND f.Descr_formation IS NULL))");
$continue = XDB::affectedRows();
+ ++$id;
}
// Updates merge_issues table (eduid and degreeid should never be empty).
XDB::rawExecute("UPDATE profile_merge_issues AS pm
$globals->debug = 0; // Do not store backtraces.
+$abbreviations = array(
+ 'commandant' => 'cdt',
+ 'docteur' => 'dr',
+ 'haut' => 'ht',
+ 'haute' => 'ht',
+ 'hauts' => 'ht',
+ 'hts' => 'ht',
+ 'general' => 'gen',
+ 'gal ' => 'gen ',
+ 'grand' => 'gd',
+ 'grande' => 'gd',
+ 'grands' => 'gd',
+ 'gde ' => 'gd ',
+ 'gds ' => 'gd ',
+ 'lieutenant' => 'lt',
+ 'marechal' => 'mal',
+ 'notre dame' => 'n d',
+ 'nouveau' => 'nouv',
+ 'president' => 'pdt',
+ 'saint' => 'st',
+ 'sainte' => 'st',
+ 'saintes' => 'st',
+ 'saints' => 'st',
+ 'ste ' => 'st ',
+ 'appartement' => 'app',
+ 'apt' => 'app',
+ 'appt' => 'app',
+ 'appart' => 'app',
+ 'arrondissement'=> 'arr',
+ 'batiment' => 'bat',
+ 'escalier' => 'esc',
+ 'etage' => 'etg',
+ 'et ' => 'etg',
+ 'immeuble' => 'imm',
+ 'lieu dit' => 'ld',
+ ' lt ' => ' lt ',
+ 'porte' => 'pte',
+ 'quartier' => 'quart',
+ 'residence' => 'res',
+ 'resi' => 'res',
+ 'villa' => 'vla',
+ 'village' => 'vlge',
+ 'vil ' => 'vlge ',
+ 'allee' => 'all',
+ 'avenue' => 'av',
+ 'boulevard' => 'bd',
+ 'bld' => 'bd',
+ 'chemin' => 'ch',
+ 'chem ' => 'ch ',
+ 'che ' => 'ch ',
+ 'cours' => 'crs',
+ 'domaine' => 'dom',
+ 'doma ' => 'dom ',
+ 'faubourg' => 'fg',
+ 'fbg' => 'fg',
+ 'hameau' => 'ham',
+ 'hame ' => 'ham ',
+ 'impasse' => 'imp',
+ 'impa ' => 'imp ',
+ 'lotissement' => 'lot',
+ 'montee' => 'mte',
+ 'passage' => 'pass',
+ 'place' => 'pl',
+ 'promenade' => 'pro ',
+ 'prom ' => 'pro ',
+ 'quai' => 'qu',
+ 'rue' => 'r',
+ 'route' => 'rte',
+ ' rde ' => ' rte ',
+ ' rle ' => ' rte ',
+ 'sentier' => 'sen',
+ 'sent ' => 'sen ',
+ 'square' => 'sq',
+ 'mount' => 'mt',
+ 'road' => 'rd',
+ 'street' => 'st',
+ 'str ' => 'str',
+ 'bis' => 'b',
+ 'ter' => 't'
+);
+$patterns = array();
+$replacements = array();
+foreach ($abbreviations as $key => $abbreviation) {
+ $patterns[] = '/' . $key . '/';
+ $replacements[] = $abbreviation;
+}
+
+function check($address1, $address2)
+{
+ return $address1['short'] == $address2['short'] || $address1['short'] == $address2['long']
+ || $address1['long'] == $address2['short'] || $address1['long'] == $address2['long'];
+}
+
print "Deletes duplicated addresses. (1/3)\n";
$pids = XDB::rawFetchColumn("SELECT DISTINCT(pid)
FROM profile_addresses AS a1
$count = 0;
$it = Address::iterate(array($pid), array(Address::LINK_PROFILE), array(0));
while ($item = $it->next()) {
- $addresses[] = $item;
- $rawAddresses[] = preg_replace('/[^a-zA-Z0-9]/', '', replace_accent($item->text));
+ $addresses[$count] = $item;
+ $rawAddress = preg_replace('/[^a-z0-9]/', ' ', mb_strtolower(replace_accent($item->text)));
+ $rawAddresses[$count] = array(
+ 'long' => preg_replace('/\s+/', '', $rawAddress),
+ 'short' => preg_replace('/\s+/', '', preg_replace($patterns, $replacements, $rawAddress)),
+ );
++$count;
}
for ($i = 0; $i < $count; ++$i) {
for ($j = $i + 1; $j < $count; ++$j) {
- if ($rawAddresses[$i] == $rawAddresses[$j]) {
- $duplicates[$i] = true;
+ if (check($rawAddresses[$i], $rawAddresses[$j])) {
+ $duplicates[$j] = true;
+ $minPub = new ProfileVisibility($addresses[$j]->pub);
+ if ($minPub->isVisible($addresses[$i]->pub)) {
+ $addresses[$i]->pub = $addresses[$j]->pub;
+ }
+ if ($addresses[$j]->hasFlag('mail') && !$addresses[$i]->hasFlag('mail')) {
+ $addresses[$i]->addFlag('mail');
+ }
}
}
}
$duplicates = array();
foreach ($pids as $pid) {
$count = 0;
- Phone::iterate(array($pid), array(Phone::LINK_PROFILE), array(0));
+ $it = Phone::iterate(array($pid), array(Phone::LINK_PROFILE), array(0));
while ($item = $it->next()) {
$phones[] = $item;
++$count;
for ($i = 0; $i < $count; ++$i) {
for ($j = $i + 1; $j < $count; ++$j) {
if ($phones[$i]->search() == $phones[$j]->search()) {
- $duplicates[$i] = true;
+ $duplicates[$j] = true;
+ $minPub = new ProfileVisibility($phones[$j]->pub);
+ if ($minPub->isVisible($phones[$i]->pub)) {
+ $phones[$i]->pub = $phones[$j]->pub;
+ }
+
}
}
}
$jobid = 0;
while ($item = $it->next()) {
$address = new Address($item);
- $address->format(array(true, true));
+ $address->format(array('requireGeocoding' => true, 'stripGeocoding' => true));
$address->delete();
$address->save();
if (!($pid == $address->pid && $jobid == $address->jobid)) {
--- /dev/null
+ALTER TABLE profile_addresses MODIFY COLUMN flags SET('current','temporary','secondary','mail','cedex', 'deliveryIssue') DEFAULT NULL;
+
+-- vim:set syntax=mysql:
--- /dev/null
+ALTER TABLE profile_photos
+ ADD COLUMN last_update TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP;
+
+-- vim:set syntax=mysql:
--- /dev/null
+DROP TABLE IF EXISTS tmp_profile_modifications;
+CREATE TEMPORARY TABLE tmp_profile_modifications LIKE profile_modifications;
+INSERT INTO tmp_profile_modifications SELECT * FROM profile_modifications;
+DROP TABLE profile_modifications;
+CREATE TABLE profile_modifications (
+ pid INT(11) UNSIGNED NOT NULL DEFAULT 0,
+ uid INT(11) UNSIGNED NOT NULL DEFAULT 0,
+ field VARCHAR(60) NOT NULL,
+ oldText TEXT NOT NULL,
+ newText TEXT NOT NULL,
+ type ENUM('self', 'third_party') NOT NULL DEFAULT 'self',
+ timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
+ PRIMARY KEY (pid, field),
+ KEY uid (uid),
+ FOREIGN KEY (uid) REFERENCES accounts (uid) ON DELETE CASCADE ON UPDATE CASCADE,
+ FOREIGN KEY (pid) REFERENCES profiles (pid) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+INSERT INTO profile_modifications (pid, uid, field, oldText, newText, type)
+ SELECT pid, uid, field, oldText, newText, 'third_party'
+ FROM tmp_profile_modifications;
+DROP TABLE IF EXISTS tmp_profile_modifications;
+
+-- vim:set syntax=mysql:
--- /dev/null
+ALTER TABLE watch_profile MODIFY COLUMN field ENUM('search_names','freetext','mobile','nationality1','nationality2','nationality3','nick','networking','edus','addresses','section','binets','medals','cv','jobs','photo','corps','tels') NOT NULL DEFAULT 'search_names';
+
+UPDATE watch_profile
+ SET field = 'tels'
+ WHERE field = 'mobile';
+
+ALTER TABLE watch_profile MODIFY COLUMN field ENUM('search_names','freetext','nationality1','nationality2','nationality3','nick','networking','edus','addresses','section','binets','medals','cv','jobs','photo','corps','tels') NOT NULL DEFAULT 'search_names';
+
+-- vim:set syntax=mysql:
--- /dev/null
+ UPDATE profile_phones AS pp
+INNER JOIN profile_addresses AS pa ON (pp.pid = pa.pid AND pp.link_id = pa.id AND pa.type = 'home' AND pp.tel_type = 'address')
+ SET pp.pub = 'ax'
+ WHERE pp.pub != pa.pub AND pa.pub = 'ax' AND pp.pub = 'public';
+ UPDATE profile_phones AS pp
+INNER JOIN profile_addresses AS pa ON (pp.pid = pa.pid AND pp.link_id = pa.id AND pa.type = 'home' AND pp.tel_type = 'address')
+ SET pp.pub = 'private' WHERE pp.pub != pa.pub AND pa.pub = 'private';
+
+ UPDATE profile_phones AS pp
+INNER JOIN profile_job AS pj ON (pp.pid = pj.pid AND pp.link_id = pj.id AND pp.link_type = 'pro')
+ SET pp.pub = 'ax'
+ WHERE pp.pub != pj.pub AND pj.pub = 'ax' AND pp.pub = 'public';
+ UPDATE profile_phones AS pp
+INNER JOIN profile_job AS pj ON (pp.pid = pj.pid AND pp.link_id = pj.id AND pp.link_type = 'pro')
+ SET pp.pub = 'private'
+ WHERE pp.pub != pj.pub AND pj.pub = 'private';
+
+ UPDATE profile_addresses AS pa
+INNER JOIN profile_job AS pj ON (pa.pid = pj.pid AND pa.id = pj.id AND pa.type = 'job')
+ SET pa.pub = 'ax'
+ WHERE pa.pub != pj.pub AND pj.pub = 'ax' AND pa.pub = 'public';
+ UPDATE profile_addresses AS pa
+INNER JOIN profile_job AS pj ON (pa.pid = pj.pid AND pa.id = pj.id AND pa.type = 'job')
+ SET pa.pub = 'private'
+ WHERE pa.pub != pj.pub AND pj.pub = 'private';
+
+UPDATE profile_job
+ SET email_pub = 'ax'
+ WHERE pub != email_pub AND pub = 'ax' AND email_pub = 'public';
+UPDATE profile_job
+ SET email_pub = 'private'
+ WHERE pub = 'private';
+
+-- vim:set syntax=mysql:
--- /dev/null
+ALTER TABLE geoloc_administrativeareas ADD COLUMN nameLocal VARCHAR(255) DEFAULT NULL;
+ALTER TABLE geoloc_subadministrativeareas ADD COLUMN nameLocal VARCHAR(255) DEFAULT NULL;
+ALTER TABLE geoloc_localities ADD COLUMN nameLocal VARCHAR(255) DEFAULT NULL;
+
+ALTER TABLE geoloc_countries CHANGE COLUMN country countryEn VARCHAR(255) DEFAULT NULL;
+ALTER TABLE geoloc_countries CHANGE COLUMN countryFR country VARCHAR(255) DEFAULT NULL;
+ALTER TABLE geoloc_countries CHANGE COLUMN nationality nationalityEn VARCHAR(255) DEFAULT NULL;
+ALTER TABLE geoloc_countries CHANGE COLUMN nationalityFR nationality VARCHAR(255) DEFAULT NULL;
+ALTER TABLE geoloc_countries ADD COLUMN countryPlain VARCHAR(255) DEFAULT NULL;
+
+INSERT INTO geoloc_countries (iso_3166_1_a2, iso_3166_1_a3, iso_3166_1_num, worldRegion,
+ country, countryEn, capital, nationality,
+ licensePlate, belongsTo, phonePrefix)
+ VALUES ('AW', 'ABW', 533, 'SA', 'Aruba', 'Aruba', 'Oranjestad', NULL, 'NL', 'NL', 297),
+ ('GW', 'GNB', 624, 'AF', 'Guinée-Bissau', 'Republic of Guinea-Bissau', 'Bissau', 'Bissau-Guinéen', 'GW', NULL, 245);
+
+-- List of supported languages:
+ -- ar ARABIC -- bg BULGARIAN -- bn BENGALI -- ca CATALAN -- cs CZECH -- da DANISH -- de GERMAN -- el GREEK -- en ENGLISH -- es SPANISH -- eu BASQUE -- fi FINNISH -- fil FILIPINO -- fr FRENCH -- gl GALICIAN -- gu GUJARATI -- hi HINDI -- hr CROATIAN -- sr SERBIAN -- hu HUNGARIAN -- id INDONESIAN -- it ITALIAN -- iw HEBREW -- ja JAPANESE -- kn KANNADA -- ko KOREAN -- lt LITHUANIAN -- lv LATVIAN -- ml MALAYALAM -- mr MARATHI -- nl DUTCH -- nn NORWEGIAN NYNORSK -- no NORWEGIAN -- or ORIYA -- pl POLISH -- pt PORTUGUESE -- pt-BR PORTUGUESE (BRAZIL) -- pt-PT PORTUGUESE (PORTUGAL) -- ro ROMANIAN -- ru RUSSIAN -- sk SLOVAK -- sl SLOVENIAN -- sv SWEDISH -- ta TAMIL -- te TELUGU -- th THAI -- tr TURKISH -- uk UKRAINIAN -- vi VIETNAMESE -- zh-CN CHINESE (SIMPLIFIED) -- zh-TW CHINESE (TRADITIONAL)
+
+DROP TABLE IF EXISTS geoloc_languages;
+CREATE TABLE geoloc_languages (
+ iso_3166_1_a2 CHAR(2) NOT NULL,
+ language CHAR(5) NOT NULL,
+ country VARCHAR(255) DEFAULT NULL,
+ countryPlain VARCHAR(255) DEFAULT NULL,
+ PRIMARY KEY (iso_3166_1_a2, language),
+ FOREIGN KEY (iso_3166_1_a2) REFERENCES geoloc_countries (iso_3166_1_a2) ON DELETE CASCADE ON UPDATE CASCADE
+) ENGINE=InnoDB DEFAULT CHARSET=utf8;
+
+INSERT INTO geoloc_languages (language, iso_3166_1_a2)
+ VALUES ('ar', 'IL'), ('ar', 'JO'), ('ar', 'SD'), ('ar', 'TD'), ('ar', 'KM'), ('ar', 'DJ'), ('ar', 'LB'), ('ar', 'DZ'), ('ar', 'BH'), ('ar', 'EG'), ('ar', 'ER'), ('ar', 'IQ'), ('ar', 'KW'), ('ar', 'LY'), ('ar', 'MR'), ('ar', 'MA'), ('ar', 'OM'), ('ar', 'PS'), ('ar', 'QA'), ('ar', 'SA'), ('ar', 'SO'), ('ar', 'SY'), ('ar', 'TN'), ('ar', 'AE'),
+ ('bg', 'BG'), ('bn', 'BD'), ('bn', 'IN'), ('ca', 'ES'), ('cs', 'CZ'), ('da', 'DK'), ('de', 'AT'), ('de', 'DE'), ('de', 'LI'), ('de', 'BE'), ('de', 'LU'), ('de', 'CH'), ('el', 'GR'), ('el', 'CY'),
+ ('en', 'IN'), ('en', 'JO'), ('en', 'SD'), ('en', 'PH'), ('en', 'AG'), ('en', 'BS'), ('en', 'BW'), ('en', 'DM'), ('en', 'FJ'), ('en', 'GM'), ('en', 'GH'), ('en', 'GD'), ('en', 'GY'), ('en', 'IE'), ('en', 'JM'), ('en', 'KE'), ('en', 'KI'), ('en', 'LS'), ('en', 'LR'), ('en', 'MW'), ('en', 'MT'), ('en', 'MH'), ('en', 'MU'), ('en', 'FM'), ('en', 'NA'), ('en', 'NR'), ('en', 'NZ'), ('en', 'NG'), ('en', 'PK'), ('en', 'PG'), ('en', 'KN'), ('en', 'LC'), ('en', 'VC'), ('en', 'WS'), ('en', 'SL'), ('en', 'SB'), ('en', 'SZ'), ('en', 'TZ'), ('en', 'TO'), ('en', 'TT'), ('en', 'TV'), ('en', 'UG'), ('en', 'ZM'), ('en', 'ZW'), ('en', 'AU'), ('en', 'GB'), ('en', 'ZA'), ('en', 'BZ'), ('en', 'US'), ('en', 'HN'), ('en', 'CM'), ('en', 'RW'), ('en', 'SC'), ('en', 'CA'), ('en', 'VU'), ('en', 'PW'), ('en', 'SG'),
+ ('en', 'MO'),
+ ('es', 'BZ'), ('es', 'US'), ('es', 'MX'), ('es', 'AR'), ('es', 'CL'), ('es', 'DO'), ('es', 'NI'), ('es', 'CO'), ('es', 'PE'), ('es', 'VE'), ('es', 'EC'), ('es', 'GT'), ('es', 'CU'), ('es', 'BO'), ('es', 'SV'), ('es', 'PY'), ('es', 'CR'), ('es', 'PA'), ('es', 'AD'), ('es', 'ES'), ('es', 'UY'), ('es', 'HN'), ('es', 'GQ'),
+ ('eu', 'ES'), ('fi', 'FI'), ('fil', 'PH'),
+ ('fr', 'CM'), ('fr', 'RW'), ('fr', 'SC'), ('fr', 'CA'), ('fr', 'VU'), ('fr', 'CD'), ('fr', 'FR'), ('fr', 'MG'), ('fr', 'CI'), ('fr', 'BF'), ('fr', 'NE'), ('fr', 'SN'), ('fr', 'ML'), ('fr', 'GN'), ('fr', 'HT'), ('fr', 'BI'), ('fr', 'BJ'), ('fr', 'TG'), ('fr', 'CF'), ('fr', 'CG'), ('fr', 'GA'), ('fr', 'MC'), ('fr', 'TD'), ('fr', 'KM'), ('fr', 'DJ'), ('fr', 'LB'), ('fr', 'BE'), ('fr', 'LU'), ('fr', 'CH'), ('fr', 'GQ'),
+ ('gl', 'ES'), ('gu', 'IN'), ('hi', 'IN'), ('hr', 'HR'), ('hr', 'BA'), ('hu', 'HU'), ('id', 'ID'), ('it', 'CH'), ('it', 'IT'), ('it', 'SM'), ('it', 'VA'), ('it', 'MT'), ('iw', 'IL'), ('ja', 'JP'), ('ja', 'PW'), ('kn', 'IN'), ('ko', 'KP'), ('ko', 'KR'), ('lt', 'LT'), ('lv', 'LV'), ('ml', 'IN'), ('mr', 'IN'), ('nl', 'BE'), ('nl', 'AW'), ('nl', 'NL'), ('nl', 'SR'), ('no', 'NO'), ('nn', 'NO'), ('or', 'IN'), ('pl', 'PL'), ('pt', 'BR'), ('pt-BR', 'BR'), ('pt', 'PT'), ('pt-PT', 'PT'), ('pt', 'MZ'), ('pt', 'AO'), ('pt', 'GW'), ('pt', 'TL'), ('pt', 'CV'), ('pt', 'ST'), ('pt', 'UY'), ('pt', 'MO'), ('rm', 'CH'), ('ro', 'MD'), ('ro', 'RO'), ('ru', 'RU'), ('ru', 'BY'), ('ru', 'KZ'), ('ru', 'KG'), ('sk', 'CZ'), ('sk', 'SK'), ('sl', 'SI'), ('sr', 'BA'), ('sr', 'RS'), ('sv', 'FI'), ('sv', 'SE'), ('ta', 'IN'), ('ta', 'LK'), ('ta', 'SG'), ('te', 'IN'), ('th', 'TH'), ('tr', 'CY'), ('tr', 'TR'), ('ua', 'UA'), ('vi', 'VN'),
+ ('zh-CN', 'SG'), ('zh-CN', 'CN'), ('zh-CN', 'TW'), ('zh-CN', 'MY'), ('zh-CN', 'HK'), ('zh-CN', 'MO'), ('zh-TW', 'SG'), ('zh-TW', 'CN'), ('zh-TW', 'TW'), ('zh-TW', 'MY'), ('zh-TW', 'HK'), ('zh-TW', 'MO');
+
+-- vim:set syntax=mysql:
--- /dev/null
+ALTER TABLE geoloc_subadministrativeareas ADD COLUMN administrativearea VARCHAR(255) DEFAULT NULL;
+
+ UPDATE geoloc_subadministrativeareas AS gs
+INNER JOIN profile_addresses AS pa ON (gs.id = pa.subAdministrativeAreaId)
+ SET gs.administrativearea = pa.administrativeAreaId;
+
+-- vim:set syntax=mysql:
--- /dev/null
+ALTER TABLE group_event_participants MODIFY COLUMN paid FLOAT(10,2) NOT NULL DEFAULT 0;
+
+-- vim:set syntax=mysql:
--- /dev/null
+../../bin/connect.db.inc.php
\ No newline at end of file
--- /dev/null
+#!/usr/bin/php5
+<?php
+
+require_once 'connect.db.inc.php';
+require_once '../../classes/address.php';
+require_once '../../classes/gmapsgeocoder.php';
+require_once '../../classes/geocoder.php';
+
+$globals->debug = 0; // Do not store backtraces.
+
+$it = XDB::iterator('SELECT gl.language, gc.country, gc.iso_3166_1_a2
+ FROM geoloc_languages AS gl
+ INNER JOIN geoloc_countries AS gc ON (gl.iso_3166_1_a2 = gc.iso_3166_1_a2)');
+
+echo $it->total() . " pays à remplir.\n";
+while ($item = $it->next()) {
+ if ($item['language'] != 'fr') {
+ $address = new Address(array('text' => $item['country']));
+ $gmapsGeocoder = new GMapsGeocoder();
+ $gmapsGeocoder->getGeocodedAddress($address, $item['language'], true);
+ $country = $address->country;
+ } else {
+ $country = $item['country'];
+ }
+ $countryPlain = mb_strtoupper(replace_accent($country));
+ XDB::execute('UPDATE geoloc_languages
+ SET country = {?}, countryPlain = {?}
+ WHERE iso_3166_1_a2 = {?} AND language = {?}',
+ $country, $countryPlain, $item['iso_3166_1_a2'], $item['language']);
+ sleep(1);
+}
+
+$it = XDB::rawIterator('SELECT country, iso_3166_1_a2
+ FROM geoloc_countries');
+echo $it->total() . " pays à simplifier.\n";
+while ($item = $it->next()) {
+ XDB::execute('UPDATE geoloc_countries
+ SET countryPlain = {?}
+ WHERE iso_3166_1_a2 = {?}',
+ mb_strtoupper(replace_accent($item['country'])), $item['iso_3166_1_a2']);
+}
+
+// Fixes geocoding errors.
+XDB::rawExecute("REPLACE INTO geoloc_languages (iso_3166_1_a2, language, country, countryPlain)
+ VALUES ('FM', 'en', 'Federated States of Micronesia', 'FEDERATED STATES OF MICRONESIA'),
+ ('MH', 'en', 'Republic of the Marshall Islands', 'REPUBLIC OF THE MARSHALL ISLANDS'),
+ ('PS', 'ar', 'دولة فلسطين', 'دولة فلسطين'),
+ ('SB', 'en', 'Solomon Islands', 'SOLOMON ISLANDS'),
+ ('TW', 'zh-CN', '台湾', '台湾'),
+ ('TW', 'zh-TW', '台灣', '台灣'),
+ ('CZ', 'cs', 'Česká Republika', 'CESKA REPUBLIKA'),
+ ('CZ', 'sk', 'Česká Republika', 'CESKA REPUBLIKA'),
+ ('DO', 'es', 'República Dominicana', 'REPUBLICA DOMINICANA'),
+ ('GD', 'en', 'Grenada', 'GRENADA'),
+ ('MD', 'ro', 'Republica Moldova', 'REPUBLICA MOLDOVA'),
+ ('RU', 'ru', 'Россия', 'Россия'),
+ ('SK', 'sk', 'Slovenská Republika', 'SLOVENSKA REPUBLIKA'),
+ ('TZ', 'en', 'United Republic of Tanzania', 'UNITED REPUBLIC OF TANZANIA')");
+
+/* vim:set et sw=4 sts=4 ts=4: */
+?>
array('SELECT pa.pid, pa.countryId
FROM profile_addresses AS pa
LEFT JOIN geoloc_countries AS gc ON (pa.countryId = gc.iso_3166_1_a2)
- WHERE gc.countryFR IS NULL OR gc.countryFR = \'\''),
+ WHERE gc.country IS NULL OR gc.country = \'\''),
'missing nationalities' =>
array('SELECT p.pid, p.nationality1, p.nationality2, p.nationality3
LEFT JOIN geoloc_countries AS g1 ON (p.nationality1 = g1.iso_3166_1_a2)
LEFT JOIN geoloc_countries AS g2 ON (p.nationality2 = g2.iso_3166_1_a2)
LEFT JOIN geoloc_countries AS g3 ON (p.nationality3 = g3.iso_3166_1_a2)
- WHERE (p.nationality1 IS NOT NULL AND (g1.nationalityFR IS NULL OR g1.nationalityFR = \'\'))
- OR (p.nationality2 IS NOT NULL AND (g2.nationalityFR IS NULL OR g2.nationalityFR = \'\'))
- OR (p.nationality3 IS NOT NULL AND (g3.nationalityFR IS NULL OR g3.nationalityFR = \'\'))'),
+ WHERE (p.nationality1 IS NOT NULL AND (g1.nationality IS NULL OR g1.nationality = \'\'))
+ OR (p.nationality2 IS NOT NULL AND (g2.nationality IS NULL OR g2.nationality = \'\'))
+ OR (p.nationality3 IS NOT NULL AND (g3.nationality IS NULL OR g3.nationality = \'\'))'),
'ax_id' =>
array('SELECT pid, hrpid, ax_id, COUNT(ax_id) AS c