From: Florent Bruneau Date: Thu, 2 Dec 2010 21:06:05 +0000 (+0100) Subject: Merge remote branch 'origin/xorg/1.0.2/master' into xorg/master X-Git-Tag: xorg/1.1.0~258 X-Git-Url: http://git.polytechnique.org/?a=commitdiff_plain;h=34c0246248ed6e3c6a372c89b359ce038bb95bc8;hp=f336915bd25f046ed90b4d7e144384d7242adc97;p=platal.git Merge remote branch 'origin/xorg/1.0.2/master' into xorg/master --- diff --git a/bin/formatAddresses.php b/bin/formatAddresses.php new file mode 100755 index 0000000..a32a17a --- /dev/null +++ b/bin/formatAddresses.php @@ -0,0 +1,52 @@ +#!/usr/bin/php5 -q +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: +?> diff --git a/bin/lists.rpc.py b/bin/lists.rpc.py index c456f35..e9529ae 100755 --- a/bin/lists.rpc.py +++ b/bin/lists.rpc.py @@ -137,7 +137,7 @@ class BasicAuthXMLRPCRequestHandler(SimpleXMLRPCRequestHandler): % (PLATAL_DOMAIN, uid, md5)) if res: name, forlife, perms = res - if vhost != PLATAL_DOMAIN: + if vhost != PLATAL_DOMAIN and perms != 'admin': res = mysql_fetchone ("""SELECT m.uid, IF(m.perms = 'admin', 'admin', 'lists') FROM group_members AS m INNER JOIN groups AS g ON (m.asso_id = g.id) diff --git a/classes/address.php b/classes/address.php index c3c0dea..f05e2f8 100644 --- a/classes/address.php +++ b/classes/address.php @@ -49,6 +49,238 @@ class Address 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; @@ -74,19 +306,19 @@ class Address 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(); @@ -105,7 +337,7 @@ class Address 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) { @@ -141,11 +373,194 @@ class Address return ($this->flags != null && $this->flags->hasFlag($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) + { + if (array_key_exists($needle, $haystack)) { + $success = true; + $length -= (strlen($needle) - strlen($haystack[$needle])); + return $haystack[$needle]; + } + 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); + } + // 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); + + // Search for country. + $countries = DirEnum::getOptions(DirEnum::COUNTRIES); + $countries = array_map('replace_accent', $countries); + $countries = array_map('strtoupper', $countries); + $count = count($arrayText); + if (in_array(strtoupper($address->country), Address::$formattings)) { + $text = call_user_func(array($this, 'formatPostalAddress' . Address::$formattings[strtoupper($address->country)]), $arrayText); + } elseif (array_key_exists($arrayText[$count - 1], Address::$formattings)) { + $text = call_user_func(array($this, 'formatPostalAddress' . Address::$formattings[$arrayText[$count - 1]]), $arrayText); + } elseif (!in_array($arrayText[$count - 1], $countries)) { + $text = $this->formatPostalAddressFR($arrayText); + } else { + $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) { @@ -174,6 +589,9 @@ class Address } $this->geocodeChosen = null; $this->phones = Phone::formatFormArray($this->phones, $this->error); + if ($format['postalText']) { + $this->formatPostalAddress(); + } return !$this->error; } @@ -203,7 +621,6 @@ class Address ); if (!is_null($this->geocodedText)) { $address['geocodedText'] = $this->geocodedText; - $address['geocodedPostalText'] = $this->geocodedPostalText; $address['geocodeChosen'] = $this->geocodeChosen; } @@ -211,7 +628,7 @@ class Address $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); @@ -231,11 +648,12 @@ class Address } 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; @@ -260,7 +678,7 @@ class 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); diff --git a/classes/gmapsgeocoder.php b/classes/gmapsgeocoder.php index 8347026..edae5c5 100644 --- a/classes/gmapsgeocoder.php +++ b/classes/gmapsgeocoder.php @@ -64,7 +64,6 @@ class GMapsGeocoder extends Geocoder { public function stripGeocodingFromAddress(Address &$address) { $address->geocodedText = null; - $address->geocodedPostalText = null; $address->geoloc_choice = null; $address->countryId = null; $address->country = null; @@ -96,7 +95,6 @@ class GMapsGeocoder extends Geocoder { // 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. @@ -107,7 +105,6 @@ class GMapsGeocoder extends Geocoder { $parameters = array( 'key' => $globals->geocoder->gmaps_key, 'sensor' => 'false', // The queried address wasn't obtained from a GPS sensor. - 'hl' => 'fr', // Output langage. 'oe' => 'utf8', // Output encoding. 'output' => 'json', // Output format. 'gl' => 'fr', // Location preferences (addresses are in France by default). @@ -246,7 +243,6 @@ class GMapsGeocoder extends Geocoder { 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/"), @@ -274,57 +270,10 @@ class GMapsGeocoder extends Geocoder { 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); - } - - // 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]; - } - if ($count + ($wordLength = strlen($word)) <= 38) { - $postalText .= (($count == 0) ? '' : ' ') . $word; - $count += (($count == 0) ? 0 : 1) + $wordLength; - } else { - $postalText .= "\n" . $word; - $count = strlen($word); - } - } - } else { - $postalText .= $line; - } - } - return $postalText; } // Trims the name of the real country if it contains an ISO 3166-1 non-country diff --git a/classes/phone.php b/classes/phone.php index 948894f..5ca75ee 100644 --- a/classes/phone.php +++ b/classes/phone.php @@ -67,7 +67,7 @@ class Phone // The following fields are the fields of the form in the profile edition. private $type = 'fixed'; public $display = ''; - private $pub = 'private'; + private $pub = 'ax'; public $comment = ''; private $error = false; diff --git a/classes/user.php b/classes/user.php index 854c848..6a3be38 100644 --- a/classes/user.php +++ b/classes/user.php @@ -813,7 +813,7 @@ class User extends PlUser XDB::execute('UPDATE log_last_sessions SET id = {?} WHERE uid = {?}', - $newuser->id()); + $lastSession, $newuser->id()); XDB::execute('DELETE FROM accounts WHERE uid = {?}', $this->id()); diff --git a/htdocs/javascript/profile.js b/htdocs/javascript/profile.js index 32efb1f..a1c5eb2 100644 --- a/htdocs/javascript/profile.js +++ b/htdocs/javascript/profile.js @@ -331,11 +331,10 @@ function validGeoloc(prefid, id, geoloc) { 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); diff --git a/include/profilefields.inc.php b/include/profilefields.inc.php index 559686d..056b01b 100644 --- a/include/profilefields.inc.php +++ b/include/profilefields.inc.php @@ -202,8 +202,12 @@ class Job } $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)); + } + } } } diff --git a/include/validations.inc.php b/include/validations.inc.php index d5678bd..3698105 100644 --- a/include/validations.inc.php +++ b/include/validations.inc.php @@ -598,7 +598,8 @@ abstract class ProfileValidate extends Validate { $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()) { diff --git a/modules/admin.php b/modules/admin.php index d98ef4e..bfba590 100644 --- a/modules/admin.php +++ b/modules/admin.php @@ -1467,15 +1467,19 @@ class AdminModule extends PLModule Phone::deletePhones(0, Phone::LINK_COMPANY, $id); Address::deleteAddresses(null, Address::LINK_COMPANY, $id); if (Env::has('change')) { - XDB::execute('UPDATE profile_job - SET jobid = {?} - WHERE jobid = {?}', - Env::i('newJobId'), $id); - XDB::execute('DELETE FROM profile_job_enum - WHERE id = {?}', - $id); - - $page->trigSuccess("L'entreprise a bien été remplacée."); + if (Env::has('newJobId') && Env::i('newJobId') > 0) { + XDB::execute('UPDATE profile_job + SET jobid = {?} + WHERE jobid = {?}', + Env::i('newJobId'), $id); + XDB::execute('DELETE FROM profile_job_enum + WHERE id = {?}', + $id); + + $page->trigSuccess("L'entreprise a bien été remplacée."); + } else { + $page->trigError("L'entreprise n'a pas été remplacée car l'identifiant fourni n'est pas valide."); + } } else { XDB::execute('UPDATE profile_job_enum SET name = {?}, acronym = {?}, url = {?}, email = {?}, @@ -1490,7 +1494,7 @@ class AdminModule extends PLModule '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(); diff --git a/modules/profile.php b/modules/profile.php index 0cc0f35..508e568 100644 --- a/modules/profile.php +++ b/modules/profile.php @@ -318,6 +318,8 @@ class ProfileModule extends PLModule $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)) { diff --git a/modules/profile/general.inc.php b/modules/profile/general.inc.php index bc8582d..fadbbce 100644 --- a/modules/profile/general.inc.php +++ b/modules/profile/general.inc.php @@ -522,7 +522,6 @@ class ProfilePageGeneral extends ProfilePage parent::__construct($wiz); $this->settings['search_names'] = new ProfileSettingSearchNames(); - $this->settings['birthdate'] = new ProfileSettingDate(); $this->settings['nationality1'] = $this->settings['nationality2'] = $this->settings['nationality3'] @@ -544,9 +543,10 @@ class ProfilePageGeneral extends ProfilePage /* 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)) { @@ -562,7 +562,7 @@ class ProfilePageGeneral extends ProfilePage 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 diff --git a/modules/profile/jobs.inc.php b/modules/profile/jobs.inc.php index 723370b..da10f88 100644 --- a/modules/profile/jobs.inc.php +++ b/modules/profile/jobs.inc.php @@ -49,13 +49,13 @@ class ProfileSettingJob implements ProfileSetting 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() @@ -202,7 +202,7 @@ class ProfileSettingJob implements ProfileSetting $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'] == '') { @@ -312,10 +312,11 @@ class ProfileSettingCorps implements ProfileSetting { $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(); } @@ -324,11 +325,19 @@ class ProfileSettingCorps implements ProfileSetting 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) @@ -384,10 +393,12 @@ class ProfilePageJobs extends ProfilePage 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($page->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 diff --git a/modules/profile/page.inc.php b/modules/profile/page.inc.php index ec70a0e..651bb38 100644 --- a/modules/profile/page.inc.php +++ b/modules/profile/page.inc.php @@ -194,7 +194,7 @@ class ProfileSettingDate extends ProfileNoSave $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]; diff --git a/modules/register/register.inc.php b/modules/register/register.inc.php index de4eb8d..bf186a1 100644 --- a/modules/register/register.inc.php +++ b/modules/register/register.inc.php @@ -198,9 +198,9 @@ function finishRegistration($subState) global $globals; $hash = rand_url_id(12); - XDB::execute('INSERT INTO register_pending (uid, forlife, bestalias, mailorg2, password, - email, date, relance, naissance, hash, services) - VALUES ({?}, {?}, {?}, {?}, {?}, {?}, NOW(), 0, {?}, {?}, {?})', + XDB::execute('INSERT IGNORE INTO register_pending (uid, forlife, bestalias, mailorg2, password, + email, date, relance, naissance, hash, services) + VALUES ({?}, {?}, {?}, {?}, {?}, {?}, NOW(), 0, {?}, {?}, {?})', $subState->i('uid'), $subState->s('forlife'), $subState->s('bestalias'), $subState->s('emailXorg2'), $subState->s('password'), $subState->s('email'), $subState->s('birthdate'), $hash, implode(',', $subState->v('services'))); diff --git a/modules/xnetgrp.php b/modules/xnetgrp.php index 56fd3b7..d5a27c7 100644 --- a/modules/xnetgrp.php +++ b/modules/xnetgrp.php @@ -193,7 +193,7 @@ class XnetGrpModule extends PLModule flags={?} WHERE id={?}", Post::v('nom'), Post::v('diminutif'), - Post::v('cat'), Post::i('dom'), + Post::v('cat'), (Post::i('dom') == 0) ? null : Post::i('dom'), Post::v('descr'), $site, Post::v('mail'), Post::v('resp'), Post::v('forum'), Post::v('mail_domain'), diff --git a/templates/geoloc/form.address.tpl b/templates/geoloc/form.address.tpl index 2ef9f3c..544eed0 100644 --- a/templates/geoloc/form.address.tpl +++ b/templates/geoloc/form.address.tpl @@ -42,10 +42,10 @@ {/if} +{if !$isMe}
Adress postale :
{$address.postalText|nl2br}
{/if} {if t($address.geocodedText)} - {/if} diff --git a/templates/include/flags.radio.tpl b/templates/include/flags.radio.tpl index 4ea1998..b20df9d 100644 --- a/templates/include/flags.radio.tpl +++ b/templates/include/flags.radio.tpl @@ -22,7 +22,7 @@ {if t($withtext)} Quelle couleur ? {/if} -{if !t($val)}{assign var=val value='private'}{/if} +{if !t($val)}{assign var=val value='ax'}{/if} + {if !t($isMe)} +
+ +
+ {else} +
+ {/if}