From: Stéphane Jacob Date: Wed, 1 Jun 2011 16:12:40 +0000 (+0200) Subject: Merge remote branch 'origin/xorg/f/geocoding' into xorg/master X-Git-Tag: xorg/1.1.2~62 X-Git-Url: http://git.polytechnique.org/?a=commitdiff_plain;h=304cdf32d7c38afbd381909545021fc44c8a0e05;hp=a3328b1eef7871d9860be82a1d1a65b1572f6880;p=platal.git Merge remote branch 'origin/xorg/f/geocoding' into xorg/master --- diff --git a/ChangeLog b/ChangeLog index fb1a927..cbc48a9 100644 --- a/ChangeLog +++ b/ChangeLog @@ -5,6 +5,14 @@ Bug/Wish: * Paiement: - #192: Displays users donations -JAC + - #1499: Fixes session user's payment display in xnet admin page -JAC + + * Profile: + - #1489: Enables automatic procecessing for secondary education -JAC + - #1497: Fixes issues with ordinary names -JAC + + * Register: + - #1501: Displays redirections in succesful registration summary -JAC * Search: - #1285: Autocompletes on internal words in university search -JAC @@ -15,6 +23,7 @@ Bug/Wish: * XnetEvent: - #1487: Removes link to event attending users to group outsiders -JAC + - #1491: Fixes participants multi-page display -JAC ================================================================================ VERSION 1.1.1 09 05 2011 diff --git a/bin/cron/registrations.php b/bin/cron/registrations.php index 91cb1ac..a2c22dc 100755 --- a/bin/cron/registrations.php +++ b/bin/cron/registrations.php @@ -5,19 +5,20 @@ require 'connect.db.inc.php'; $message = ''; -$res = XDB::iterRow("SELECT a.registration_date, a.hruid, s.email - FROM accounts AS a - INNER JOIN account_profiles AS ap ON (ap.uid = a.uid AND FIND_IN_SET('owner', ap.perms)) - INNER JOIN profile_display AS pd ON (ap.pid = pd.pid) - LEFT JOIN email_source_account AS s ON (a.uid = s.uid) +$res = XDB::iterRow("SELECT a.registration_date, a.hruid, s.email, GROUP_CONCAT(r.redirect SEPARATOR ', ') + FROM accounts AS a + INNER JOIN account_profiles AS ap ON (ap.uid = a.uid AND FIND_IN_SET('owner', ap.perms)) + INNER JOIN profile_display AS pd ON (ap.pid = pd.pid) + LEFT JOIN email_source_account AS s ON (a.uid = s.uid) + LEFT JOIN email_redirect_account AS r ON (a.uid = r.uid) WHERE a.registration_date > {?} GROUP BY a.hruid ORDER BY pd.promo", date("Ymd000000", strtotime('last Monday'))); if ($count = $res->total()) { $message .= "$count INSCRIPTIONS CONFIRMÉES CETTE SEMAINE :\n"; - while (list($date, $hruid, $email) = $res->next()) { - $message .= "$date, $hruid, $email\n"; + while (list($date, $hruid, $email, $redirect) = $res->next()) { + $message .= "$date, $hruid, $email, $redirect\n"; } } diff --git a/bin/export_sql.bash b/bin/export_sql.bash index 9b85b2a..51417c8 100755 --- a/bin/export_sql.bash +++ b/bin/export_sql.bash @@ -25,7 +25,6 @@ profile_job_term_relation \ profile_langskill_enum \ profile_medal_enum \ profile_medal_grade_enum \ -profile_name_enum \ profile_networking_enum \ profile_section_enum \ profile_skill_enum \ diff --git a/classes/direnum.php b/classes/direnum.php index 0b51cb6..a94c69b 100644 --- a/classes/direnum.php +++ b/classes/direnum.php @@ -29,9 +29,6 @@ class DirEnum * Each of these consts contains the basename of the class (its full name * being DE_$basename). */ - const NAMETYPES = 'nametypes'; - const NAMES = 'names'; - const BINETS = 'binets'; const GROUPESX = 'groupesx'; const SECTIONS = 'sections'; @@ -435,29 +432,6 @@ abstract class DE_WithSuboption extends DirEnumeration } // }}} -// {{{ class DE_NameTypes -// returns 'system' names ('lastname', 'lastname_marital', ...) -class DE_NameTypes extends DirEnumeration -{ - public $capabilities = 0x005; // self::HAS_OPTIONS | self::SAVE_IN_SESSION; - - protected $from = 'profile_name_enum'; - protected $valfield = 'type'; -} -// }}} - -// {{{ class DE_Names -// returns 'system' names ('lastname', 'lastname_marital', ...) -class DE_Names extends DirEnumeration -{ - public $capabilities = 0x005; // self::HAS_OPTIONS | self::SAVE_IN_SESSION; - - protected $from = 'profile_name_enum'; - protected $idfield = 'type'; - protected $valfield = 'name'; -} -// }}} - /** GROUPS */ // {{{ class DE_Binets diff --git a/classes/profile.php b/classes/profile.php index 9c7cc3e..b7a190c 100644 --- a/classes/profile.php +++ b/classes/profile.php @@ -273,6 +273,20 @@ class Profile implements PlExportable } } + public static function educationDuration($education) + { + switch ($education) { + case self::DEGREE_X: + return 3; + case self::DEGREE_M: + return 2; + case self::DEGREE_D: + return 3; + default: + return 0; + } + } + /** Number of years between the promotion year until the * graduation year. In standard schools it's 0, but for * Polytechnique the promo year is the entry year. @@ -446,7 +460,7 @@ class Profile implements PlExportable * profile_job, profile_langskills, profile_mentor, profile_networking, * profile_phones, profile_skills, watch_profile * *always keeps in: profile_corps, profile_display, profile_education, - * profile_medals, profile_name, profile_photos, search_name + * profile_medals, profile_*_names, profile_photos, search_name * *modifies: profiles */ public function clear() @@ -966,10 +980,9 @@ class Profile implements PlExportable IF (p.freetext_pub IN {?}, p.freetext, NULL) AS freetext, pe.entry_year, pe.grad_year, pe.promo_year, pe.program, pe.fieldid, IF ({?}, pse.text, NULL) AS section, - pn_f.name AS firstname, pn_l.name AS lastname, - IF ({?}, pn_n.name, NULL) AS nickname, - IF (pn_uf.name IS NULL, pn_f.name, pn_uf.name) AS firstname_ordinary, - IF (pn_ul.name IS NULL, pn_l.name, pn_ul.name) AS lastname_ordinary, + ppn.firstname_main AS firstname, ppn.lastname_main AS lastname, IF ({?}, pn.name, NULL) AS nickname, + IF (ppn.firstname_ordinary = \'\', ppn.firstname_main, ppn.firstname_ordinary) AS firstname_ordinary, + IF (ppn.lastname_ordinary = \'\', ppn.firstname_main, ppn.lastname_ordinary) AS lastname_ordinary, pd.yourself, pd.promo, pd.short_name, pd.public_name AS full_name, pd.directory_name, pd.public_name, pd.private_name, IF (pp.pub IN {?}, pp.display_tel, NULL) AS mobile, @@ -983,16 +996,8 @@ class Profile implements PlExportable INNER JOIN profile_display AS pd ON (pd.pid = p.pid) INNER JOIN profile_education AS pe ON (pe.pid = p.pid AND FIND_IN_SET(\'primary\', pe.flags)) LEFT JOIN profile_section_enum AS pse ON (pse.id = p.section) - INNER JOIN profile_name AS pn_f ON (pn_f.pid = p.pid - AND pn_f.typeid = ' . self::getNameTypeId('firstname', true) . ') - INNER JOIN profile_name AS pn_l ON (pn_l.pid = p.pid - AND pn_l.typeid = ' . self::getNameTypeId('lastname', true) . ') - LEFT JOIN profile_name AS pn_uf ON (pn_uf.pid = p.pid - AND pn_uf.typeid = ' . self::getNameTypeId('firstname_ordinary', true) . ') - LEFT JOIN profile_name AS pn_ul ON (pn_ul.pid = p.pid - AND pn_ul.typeid = ' . self::getNameTypeId('lastname_ordinary', true) . ') - LEFT JOIN profile_name AS pn_n ON (pn_n.pid = p.pid - AND pn_n.typeid = ' . self::getNameTypeId('nickname', true) . ') + INNER JOIN profile_public_names AS ppn ON (ppn.pid = p.pid) + LEFT JOIN profile_private_names AS pn ON (pn.pid = p.pid AND type = \'nickname\') LEFT JOIN profile_phones AS pp ON (pp.pid = p.pid AND pp.link_type = \'user\' AND tel_type = \'mobile\') LEFT JOIN profile_photos AS ph ON (ph.pid = p.pid) LEFT JOIN profile_mentor AS pm ON (pm.pid = p.pid) @@ -1134,47 +1139,46 @@ class Profile implements PlExportable } } - public static function getNameTypeId($type, $for_sql = false) - { - if (!S::has('name_types')) { - $table = XDB::fetchAllAssoc('type', 'SELECT id, type - FROM profile_name_enum'); - S::set('name_types', $table); - } else { - $table = S::v('name_types'); - } - if ($for_sql) { - return XDB::escape($table[$type]); - } else { - return $table[$type]; - } - } - public static function rebuildSearchTokens($pids, $transaction = true) { + require_once 'name.func.inc.php'; if (!is_array($pids)) { $pids = array($pids); } - $keys = XDB::iterator("(SELECT n.pid AS pid, n.name AS name, e.score AS score, e.general_type, - IF(FIND_IN_SET('public', e.flags), 'public', '') AS public - FROM profile_name AS n - INNER JOIN profile_name_enum AS e ON (n.typeid = e.id) - WHERE n.pid IN {?} AND NOT FIND_IN_SET('not_displayed', e.flags)) - UNION - (SELECT n.pid AS pid, n.particle AS name, 0 AS score, e.general_type, - IF(FIND_IN_SET('public', e.flags), 'public', '') AS public - FROM profile_name AS n - INNER JOIN profile_name_enum AS e ON (n.typeid = e.id) - WHERE n.pid IN {?} AND NOT FIND_IN_SET('not_displayed', e.flags)) - ", - $pids, $pids); + $keys = XDB::iterator("(SELECT pid, name, type, IF(type = 'nickname', 2, 1) AS score, '' AS public + FROM profile_private_names + WHERE pid IN {?}) + UNION + (SELECT pid, lastname_main, 'lastname' AS type, 10 AS score, 'public' AS public + FROM profile_public_names + WHERE lastname_main != '' AND pid IN {?}) + UNION + (SELECT pid, lastname_marital, 'lastname' AS type, 10 AS score, 'public' AS public + FROM profile_public_names + WHERE lastname_marital != '' AND pid IN {?}) + UNION + (SELECT pid, lastname_ordinary, 'lastname' AS type, 10 AS score, 'public' AS public + FROM profile_public_names + WHERE lastname_ordinary != '' AND pid IN {?}) + UNION + (SELECT pid, firstname_main, 'firstname' AS type, 10 AS score, 'public' AS public + FROM profile_public_names + WHERE firstname_main != '' AND pid IN {?}) + UNION + (SELECT pid, firstname_ordinary, 'firstname' AS type, 10 AS score, 'public' AS public + FROM profile_public_names + WHERE firstname_ordinary != '' AND pid IN {?}) + UNION + (SELECT pid, pseudonym, 'nickname' AS type, 10 AS score, 'public' AS public + FROM profile_public_names + WHERE pseudonym != '' AND pid IN {?})", + $pids, $pids, $pids, $pids, $pids, $pids, $pids); $names = array(); while ($key = $keys->next()) { if ($key['name'] == '') { continue; } - $pid = $key['pid']; - require_once 'name.func.inc.php'; + $pid = $key['pid']; $toks = split_name_for_search($key['name']); $toks = array_reverse($toks); @@ -1189,7 +1193,7 @@ class Profile implements PlExportable $token = $tok . $token; $names["$pid-$token"] = XDB::format('({?}, {?}, {?}, {?}, {?}, {?})', $token, $pid, soundex_fr($token), - $eltScore, $key['public'], $key['general_type']); + $eltScore, $key['public'], $key['type']); } } if ($transaction) { diff --git a/classes/userfilter.php b/classes/userfilter.php index be9e13b..21fc1bf 100644 --- a/classes/userfilter.php +++ b/classes/userfilter.php @@ -543,12 +543,12 @@ class UserFilter extends PlFilter static public function sortByName() { - return array(new UFO_Name(Profile::LASTNAME), new UFO_Name(Profile::FIRSTNAME)); + return array(new UFO_Name()); } static public function sortByPromo() { - return array(new UFO_Promo(), new UFO_Name(Profile::LASTNAME), new UFO_Name(Profile::FIRSTNAME)); + return array(new UFO_Promo(), new UFO_Name()); } static private function getDBSuffix($string) @@ -676,44 +676,6 @@ class UserFilter extends PlFilter return $joins; } - /** NAMES - */ - - static public function assertName($name) - { - if (!DirEnum::getID(DirEnum::NAMETYPES, $name)) { - Platal::page()->kill('Invalid name type: ' . $name); - } - } - - private $pn = array(); - public function addNameFilter($type, $variant = null) - { - $this->requireProfiles(); - if (!is_null($variant)) { - $ft = $type . '_' . $variant; - } else { - $ft = $type; - } - $sub = '_' . $ft; - self::assertName($ft); - - if (!is_null($variant) && $variant == 'other') { - $sub .= $this->option++; - } - $this->pn[$sub] = DirEnum::getID(DirEnum::NAMETYPES, $ft); - return $sub; - } - - protected function nameJoins() - { - $joins = array(); - foreach ($this->pn as $sub => $type) { - $joins['pn' . $sub] = PlSqlJoin::left('profile_name', '$ME.pid = $PID AND $ME.typeid = {?}', $type); - } - return $joins; - } - /** NAMETOKENS */ private $name_tokens = array(); diff --git a/classes/userfilter/conditions.inc.php b/classes/userfilter/conditions.inc.php index 61bfb09..e931395 100644 --- a/classes/userfilter/conditions.inc.php +++ b/classes/userfilter/conditions.inc.php @@ -583,67 +583,28 @@ class UFC_EducationField extends UserFilterCondition } } // }}} -// {{{ class UFC_Name -/** Filters users based on name - * @param $type Type of name field on which filtering is done (firstname, lastname...) - * @param $text Text on which to filter - * @param $mode Flag indicating search type (prefix, suffix, with particule...) +// {{{ class UFC_NameInitial +/** Filters users based on sort_name + * @param $initial Initial on which to filter */ -class UFC_Name extends UserFilterCondition +class UFC_NameInitial extends UserFilterCondition { - const EXACT = XDB::WILDCARD_EXACT; // 0x000 - const PREFIX = XDB::WILDCARD_PREFIX; // 0x001 - const SUFFIX = XDB::WILDCARD_SUFFIX; // 0x002 - const CONTAINS = XDB::WILDCARD_CONTAINS; // 0x003 - const PARTICLE = 0x004; - const VARIANTS = 0x008; + private $initial; - private $type; - private $text; - private $mode; - - public function __construct($type, $text, $mode) - { - $this->type = $type; - $this->text = $text; - $this->mode = $mode; - } - - private function buildNameQuery($type, $variant, $where, UserFilter $uf) + public function __construct($initial) { - $sub = $uf->addNameFilter($type, $variant); - return str_replace('$ME', 'pn' . $sub, $where); + $this->initial = $initial; } public function buildCondition(PlFilter $uf) { - $left = '$ME.name'; - if (($this->mode & self::PARTICLE) == self::PARTICLE) { - $left = 'CONCAT($ME.particle, \' \', $ME.name)'; - } - $right = XDB::formatWildcards($this->mode & self::CONTAINS, $this->text); - - $cond = $left . $right; - $conds = array($this->buildNameQuery($this->type, null, $cond, $uf)); - if (($this->mode & self::VARIANTS) != 0 && isset(Profile::$name_variants[$this->type])) { - foreach (Profile::$name_variants[$this->type] as $var) { - $conds[] = $this->buildNameQuery($this->type, $var, $cond, $uf); - } - } - return implode(' OR ', $conds); + $sub = $uf->addDisplayFilter(); + return 'SUBSTRING(pd.sort_name, 1, 1) ' . XDB::formatWildcards(XDB::WILDCARD_PREFIX, $this->initial); } public function export() { - $export = $this->buildExport($this->type); - if ($this->mode & self::VARIANTS) { - $export['search_in_variants'] = true; - } - if ($this->mode & self::PARTICLE) { - $export['search_in_particle'] = true; - } - $export['comparison'] = self::comparisonFromXDBWildcard($this->mode & 0x3); - $export['text'] = $this->text; + $export = $this->buildExport($this->initial); return $export; } } diff --git a/classes/userfilter/orders.inc.php b/classes/userfilter/orders.inc.php index ad41bb3..b64a8e8 100644 --- a/classes/userfilter/orders.inc.php +++ b/classes/userfilter/orders.inc.php @@ -36,13 +36,8 @@ abstract class UserFilterOrders case 'promo': return new UFO_Promo($export->v('grade'), $desc); - case 'lastname': case 'name': - case 'firstname': - case 'nickname': - case 'pseudonym': - return new UFO_Name($type, $export->v('variant'), - $export->b('particle'), $desc); + return new UFO_Name($desc); case 'score': case 'registration': @@ -106,43 +101,19 @@ class UFO_Promo extends PlFilterGroupableOrder // }}} // {{{ class UFO_Name /** Sorts users by name - * @param $type Type of name on which to sort (firstname...) - * @param $variant Variant of that name to use (marital, ordinary...) - * @param $particle Set to true if particles should be included in the sorting order * @param $desc If sort order should be descending */ class UFO_Name extends PlFilterGroupableOrder { - private $type; - private $variant; - private $particle; - - public function __construct($type, $variant = null, $particle = false, $desc = false) - { - parent::__construct($desc); - $this->type = $type; - $this->variant = $variant; - $this->particle = $particle; - } - protected function getSortTokens(PlFilter $uf) { - if (Profile::isDisplayName($this->type)) { - $sub = $uf->addDisplayFilter(); - $token = 'pd' . $sub . '.' . $this->type; - if ($uf->accountsRequired()) { - $account_token = Profile::getAccountEquivalentName($this->type); - return 'IFNULL(' . $token . ', a.' . $account_token . ')'; - } else { - return $token; - } + $sub = $uf->addDisplayFilter(); + $token = 'pd.sort_name'; + if ($uf->accountsRequired()) { + $account_token = Profile::getAccountEquivalentName('sort_name'); + return 'IFNULL(' . $token . ', a.' . $account_token . ')'; } else { - $sub = $uf->addNameFilter($this->type, $this->variant); - if ($this->particle) { - return 'CONCAT(pn' . $sub . '.particle, \' \', pn' . $sub . '.name)'; - } else { - return 'pn' . $sub . '.name'; - } + return $token; } } @@ -153,30 +124,12 @@ class UFO_Name extends PlFilterGroupableOrder public function getCondition($initial) { - if (Profile::isDisplayName($this->type)) { - switch ($this->type) { - case Profile::DN_PRIVATE: - case Profile::DN_SHORT: - case Profile::DN_YOURSELF: - $type = Profile::FIRSTNAME; - default: - $type = Profile::LASTNAME; - } - } else { - $type = $this->type; - } - return new UFC_Name($type, $initial, UFC_Name::PREFIX); + return new UFC_NameInitial($initial); } public function export() { - $export = $this->buildExport($this->type); - if (!is_null($this->variant)) { - $export['variant'] = $this->variant; - } - if ($this->particle) { - $export['particle'] = true; - } + $export = $this->buildExport(); return $export; } } diff --git a/htdocs/javascript/profile.js b/htdocs/javascript/profile.js index f117885..765c43d 100644 --- a/htdocs/javascript/profile.js +++ b/htdocs/javascript/profile.js @@ -77,12 +77,10 @@ function addSearchName(isFemale) while ($('#search_name_' + i).length != 0) { i++; } - $('#search_name_' + i) - .updateHtml('profile/ajax/searchname/' + i + '/' + isFemale, - function(data) { - $('#searchname').before(data); - changeNameFlag(i); - }); + $('#search_name_' + i).updateHtml('profile/ajax/searchname/' + i + '/' + isFemale, + function(data) { + $('#searchname').before(data); + }); } function removeSearchName(i, isFemale) @@ -91,34 +89,29 @@ function removeSearchName(i, isFemale) updateNameDisplay(isFemale); } -function changeNameFlag(i) -{ - $('#flag_' + i).remove(); - var typeid = $('#search_name_' + i).find('select').val(); - var type = $('#search_name_' + i).find('select :selected').text(); - if ($('[name=sn_type_' + typeid + '_' + i + ']').val() > 0) { - $('#flag_cb_' + i).after(' ' + - 'site public' + - '' + - '' + - ''); - } else { - $('#flag_cb_' + i).after(' ' + - 'site privé' + - '' + - ''); - } -} - function updateNameDisplay(isFemale) { + var lastnames = new Array('lastname_main', 'lastname_ordinary', 'lastname_marital', 'pseudonym'); + var firstnames = new Array('firstname_main', 'firstname_ordinary'); var searchnames = ''; - for (var i = 0; i < 10; i++) { + + for (var i = 0; i < 4; ++i) { + searchnames += $('.names_advanced').find('[name*=' + lastnames[i] + ']').val() + ';'; + } + searchnames += '-;' + for (var i = 0; i < 2; ++i) { + searchnames += $('.names_advanced').find('[name*=' + firstnames[i] + ']').val() + ';'; + } + searchnames += '-'; + + var has_private = false; + for (var i = 0; i < 10; ++i) { if ($('#search_name_' + i).find(':text').val()) { - searchnames += $('#search_name_' + i).find('[name*=typeid]').val() + ';'; - searchnames += $('#search_name_' + i).find(':text').val() + ';;'; + searchnames += ';' + $('#search_name_' + i).find('[name*=type]').val() + ';' + $('#search_name_' + i).find(':text').val(); + has_private = true; } } + searchnames += (has_private ? '' : ';'); $.xget('profile/ajax/buildnames/' + searchnames + '/' + isFemale, function(data){ var name = data.split(';'); @@ -127,15 +120,6 @@ function updateNameDisplay(isFemale) }); } -function toggleParticle(id) -{ - if ($('#search_name_' + id).find("[name*='[particle]']").val() == '') { - $('#search_name_' + id).find("[name*='[particle]']").val(1); - } else { - $('#search_name_' + id).find("[name*='[particle]']").val(''); - } -} - // Promotions {{{1 function togglePromotionEdition() diff --git a/include/education.func.inc.php b/include/education.func.inc.php index 9c7ab44..cb25855 100644 --- a/include/education.func.inc.php +++ b/include/education.func.inc.php @@ -28,8 +28,9 @@ function education_options($current = 0) 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.country, e.name"); + WHERE e.id = d.eduid) AND e.name != {?} + ORDER BY gc.country, e.name", + Profile::EDU_X); $country = ""; while ($arr_edu = $res->next()) { if ($arr_edu["country"] != $country) { diff --git a/include/name.func.inc.php b/include/name.func.inc.php index 1f78daf..6483449 100644 --- a/include/name.func.inc.php +++ b/include/name.func.inc.php @@ -21,211 +21,100 @@ function build_javascript_names($data, $isFemale) { - $data_array = explode(';;', $data); - $n = count($data_array); - $n--; - for ($i = 0; $i < $n; $i++) { - $searchname = explode(';', $data_array[$i]); - if (isset($search_names[$searchname[0]])) { - $search_names[$searchname[0]][] = $searchname[1]; - } else { - $search_names[$searchname[0]] = array('fullname' => $searchname[1]); - } - } + $names = array(); + foreach (explode(';-;', $data) as $key => $item) { + $names[$key] = explode(';', $item); + } + $lastnames = array( + 'lastname_main' => $names[0][0], + 'lastname_ordinary' => $names[0][1], + 'lastname_marital' => $names[0][2], + 'pseudonym' => $names[0][3] + ); + $firstnames = array( + 'firstname_main' => $names[1][0], + 'firstname_ordinary' => $names[1][1] + ); + $private_names_count = intval(count($names[2]) / 2); + $private_names = array(); + for ($i = 0; $i < $private_names_count; ++$i) { + $private_names[] = array('type' => $names[2][2 * $i], 'name' => $names[2][2 * $i + 1]); + } + + return build_first_name($firstnames) . ' ' . build_full_last_name($lastnames, $isFemale) . ';' . build_private_name($private_names); +} - $sn_types_public = build_types('public'); - $sn_types_private = build_types('private'); - $full_name = build_full_name($search_names, $sn_types_public, $isFemale); - return build_public_name($search_names, $sn_types_public, $full_name) . ';' . - build_private_name($search_names, $sn_types_private); +function build_email_alias(array $public_names) +{ + return PlUser::makeUserName(build_first_name($public_names), build_short_last_name($public_names)); } -function build_display_names(&$display_names, $search_names, $isFemale, $private_name_end = null, &$alias = null) +function build_display_names(array $public_names, array $private_names, $isFemale) { - $sn_types_public = build_types('public'); - $full_name = build_full_name($search_names, $sn_types_public, $isFemale); - $display_names['public_name'] = build_public_name($search_names, $sn_types_public, $full_name); - $display_names['private_name'] = $display_names['public_name'] . $private_name_end; - $display_names['directory_name'] = build_directory_name($search_names, $sn_types_public, $full_name); - $display_names['short_name'] = build_short_name($search_names, $sn_types_public, $alias); - $display_names['sort_name'] = build_sort_name($search_names, $sn_types_public); + $short_last_name = build_short_last_name($public_names); + $full_last_name = build_full_last_name($public_names, $isFemale); + $private_last_name_end = build_private_name($private_names); + $firstname = build_first_name($public_names); + + $display_names = array(); + $display_names['public_name'] = $firstname . ' ' . $full_last_name; + $display_names['private_name'] = $display_names['public_name'] . $private_last_name_end; + $display_names['directory_name'] = $full_last_name . ' ' . $firstname; + $display_names['short_name'] = $firstname . ' ' . $short_last_name; + $display_names['sort_name'] = $short_last_name . ' ' . $firstname; + + return $display_names; } -function build_types($pub = null) +function build_short_last_name(array $lastnames) { - if ($pub == 'public') { - $sql_pub = "AND FIND_IN_SET('public', flags)"; - } elseif ($pub == 'private') { - $sql_pub = "AND NOT FIND_IN_SET('public', flags)"; - } else { - $sql_pub = ""; - } - $sql = "SELECT id, type, name - FROM profile_name_enum - WHERE NOT FIND_IN_SET('not_displayed', flags)" . $sql_pub; - $sn_types = XDB::iterator($sql); - $types = array(); - while ($sn_type = $sn_types->next()) { - if ($pub) { - $types[$sn_type['type']] = $sn_type['id']; - } else { - $types[$sn_type['id']] = $sn_type['name']; - } - } - return $types; + return ($lastnames['lastname_ordinary'] == '') ? $lastnames['lastname_main'] : $lastnames['lastname_ordinary']; } -function build_full_name(&$search_names, &$sn_types, $isFemale) +function build_full_last_name(array $lastnames, $isFemale) { - $name = ""; - if (isset($search_names[$sn_types['lastname_ordinary']])) { - $name .= $search_names[$sn_types['lastname_ordinary']]['fullname'] . " (" - . $search_names[$sn_types['lastname']]['fullname'] . ")"; + if ($lastnames['lastname_ordinary'] != '') { + $name = $lastnames['lastname_ordinary'] . ' (' . $lastnames['lastname_main'] . ')'; } else { - $name .= $search_names[$sn_types['lastname']]['fullname']; + $name = $lastnames['lastname_main']; } - if (isset($search_names[$sn_types['lastname_marital']]) - || isset($search_names[$sn_types['pseudonym']])) { - $name .= " ("; - if (isset($search_names[$sn_types['lastname_marital']])) { - if ($isFemale) { - $name .= "Mme "; - } else { - $name .= "M "; - } - $name .= $search_names[$sn_types['lastname_marital']]['fullname']; - if (isset($search_names[$sn_types['pseudonym']])) { - $name .= ", "; - } - } - if (isset($search_names[$sn_types['pseudonym']])) { - $name .= $search_names[$sn_types['pseudonym']]['fullname']; + if ($lastnames['lastname_marital'] != '' || $lastnames['pseudonym'] != '') { + $name .= ' ('; + if ($lastnames['lastname_marital'] != '') { + $name .= ($isFemale ? 'Mme ' : 'M ') . $lastnames['lastname_marital']; + $name .= (($lastnames['pseudonym'] == '') ? '' : ', '); } - $name .= ")"; + $name .= (($lastnames['pseudonym'] == '')? '' : $lastnames['pseudonym']) . ')'; } return $name; } -function build_public_name(&$search_names, &$sn_types, $full_name) +function build_first_name(array $firstnames) { - return $search_names[$sn_types['firstname']]['fullname'] . " " . $full_name; + return ($firstnames['firstname_ordinary'] ? $firstnames['firstname_ordinary'] : $firstnames['firstname_main']); } -function build_private_name(&$search_names, &$sn_types) +function build_private_name(array $private_names) { - $name = ""; - if (isset($search_names[$sn_types['nickname']]) - || (isset($search_names[$sn_types['name_other']]) - || isset($search_names[$sn_types['name_other']]))) { - $name .= " ("; - if (isset($search_names[$sn_types['nickname']])) { - $name .= "alias " . $search_names[$sn_types['nickname']]['fullname']; - $i = 0; - while (isset($search_names[$sn_types['nickname']][$i])) { - $name .= ", " . $search_names[$sn_types['nickname']][$i]; - $i++; - } - if (isset($search_names[$sn_types['name_other']]) - || isset($search_names[$sn_types['firstname_other']])) { - $name .= ", "; - } - } - if (isset($search_names[$sn_types['firstname_other']])) { - $name .= "autres prénoms : " . $search_names[$sn_types['firstname_other']]['fullname']; - $i = 0; - while (isset($search_names[$sn_types['firstname_other']][$i])) { - $name .= ", " . $search_names[$sn_types['firstname_other']][$i]; - $i++; - } - if (isset($search_names[$sn_types['name_other']])) { - $name .= ", "; - } - } - if (isset($search_names[$sn_types['name_other']])) { - $name .= "autres noms : " . $search_names[$sn_types['name_other']]['fullname']; - $i = 0; - while (isset($search_names[$sn_types['name_other']][$i])) { - $name .= ", " . $search_names[$sn_types['name_other']][$i]; - $i++; - } - } - $name .= ")"; + if (is_null($private_names) || count($private_names) == 0) { + return ''; } - return $name; -} -function build_directory_name(&$search_names, &$sn_types, $full_name) -{ - return $full_name . " " . $search_names[$sn_types['firstname']]['fullname']; -} + static $types = array('nickname' => 'alias ', 'firstname' => 'autres prénoms : ', 'lastname' => 'autres noms : '); + $names_sorted = array('nickname' => array(), 'firstname' => array(), 'lastname' => array()); -function build_short_name(&$search_names, &$sn_types, &$alias = null) -{ - if (isset($search_names[$sn_types['lastname_ordinary']])) { - $lastname = $search_names[$sn_types['lastname_ordinary']]['fullname']; - } else { - $lastname = $search_names[$sn_types['lastname']]['fullname']; - } - if (isset($search_names[$sn_types['firstname_ordinary']])) { - $firstname = $search_names[$sn_types['firstname_ordinary']]['fullname']; - } else { - $firstname = $search_names[$sn_types['firstname']]['fullname']; - } - if ($alias) { - $alias = PlUser::makeUserName($firstname, $lastname); - } - return $firstname . " " . $lastname; -} - -function build_sort_name(&$search_names, &$sn_types) -{ - $name = ""; - if (isset($search_names[$sn_types['lastname_ordinary']])) { - $name .= $search_names[$sn_types['lastname_ordinary']]['name']; - } else { - $name .= $search_names[$sn_types['lastname']]['name']; + foreach ($private_names as $private_name) { + $names_sorted[$private_name['type']][] = $private_name['name']; } - $name .= " " . $search_names[$sn_types['firstname']]['fullname']; - return $name; -} - -function set_profile_display(&$display_names, Profile $profile) -{ - XDB::execute("UPDATE profile_display - SET public_name = {?}, private_name = {?}, - directory_name = {?}, short_name = {?}, sort_name = {?} - WHERE pid = {?}", - $display_names['public_name'], $display_names['private_name'], - $display_names['directory_name'], $display_names['short_name'], - $display_names['sort_name'], $profile->id()); - $owner = $profile->owner(); - if ($owner) { - XDB::execute('UPDATE accounts - SET full_name = {?}, directory_name = {?} - WHERE uid = {?}', - $display_names['public_name'], $display_names['directory_name'], $owner->id()); + $names_array = array(); + foreach ($names_sorted as $type => $names) { + if (count($names)) { + $names_array[] = $types[$type] . implode(', ', $names); + } } -} -function build_sn_pub($pid) -{ - $res = XDB::iterator("SELECT CONCAT(sn.particle, sn.name) AS fullname, sn.typeid, - sn.particle, sn.name, sn.id - FROM profile_name AS sn - INNER JOIN profile_name_enum AS e ON (e.id = sn.typeid) - WHERE sn.pid = {?} AND NOT FIND_IN_SET('not_displayed', e.flags) - AND FIND_IN_SET('public', e.flags) - ORDER BY NOT FIND_IN_SET('always_displayed', e.flags), e.id, sn.name", - $pid); - $sn_old = array(); - while ($old = $res->next()) { - $sn_old[$old['typeid']] = array('fullname' => $old['fullname'], - 'name' => $old['name'], - 'particle' => $old['particle'], - 'id' => $old['id']); - } - return $sn_old; + return ' (' . implode(', ', $names_array) . ')'; } /** Splits a name into tokens, as used in search_name. @@ -255,94 +144,61 @@ function compare_basename($a, $b) { return name_to_basename($a) == name_to_basename($b); } -function set_alias_names(&$sn_new, $sn_old, $pid, PlUser $user, $update_new = false, $new_alias = null) +function update_account_from_profile($uid) { - $has_new = false; - foreach ($sn_new as $typeid => $sn) { - if (isset($sn['pub']) && !is_null($sn['fullname'])) { - 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 ($sn['fullname'] == $sn_old[$typeid]['fullname'] && $sn['name'] == $sn_old[$typeid]['name']) { - XDB::execute('INSERT INTO profile_name (particle, name, typeid, pid) - VALUES ({?}, {?}, {?}, {?})', - $sn_old[$typeid]['particle'], $sn_old[$typeid]['name'], $typeid, $pid); - unset($sn_old[$typeid]); - } else { - $has_new = true; - } - } else { - if ($sn['fullname'] != '') { - XDB::execute("INSERT INTO profile_name (particle, name, typeid, pid) - VALUES ('', {?}, {?}, {?})", - $sn['fullname'], $typeid, $pid); - } - $i = 0; - while (isset($sn[$i])) { - XDB::execute("INSERT INTO profile_name (particle, name, typeid, pid) - VALUES ('', {?}, {?}, {?})", - $sn[$i], $typeid, $pid); - $i++; - } - } - } - if (count($sn_old) > 0) { - if (!$update_new) { - $has_new = true; - foreach ($sn_old as $typeid => $sn) { - XDB::execute("INSERT INTO profile_name (particle, name, typeid, pid) - VALUES ({?}, {?}, {?}, {?})", - $sn['particle'], $sn['name'], $typeid, $pid); - } - } else { - foreach ($sn_old as $typeid => $sn) { - XDB::execute("DELETE FROM profile_name - WHERE pid = {?} AND id = {?}", - $pid, $sn['id']); - } - } - } - if ($update_new) { - XDB::execute('DELETE FROM email_source_account - WHERE FIND_IN_SET(\'usage\', flags) AND uid = {?} AND type = \'alias\'', - $user->id()); - } - if ($new_alias) { - XDB::execute('INSERT INTO email_source_account (email, uid, type, flags, domain) - SELECT {?}, {?}, \'alias\', \'usage\', id - FROM email_virtual_domains - WHERE name = {?}', - $new_alias, $user->id(), $user->mainEmailDomain()); + XDB::execute("UPDATE accounts AS a + INNER JOIN account_profiles AS ap ON (ap.uid = a.uid AND FIND_IN_SET('owner', ap.perms)) + INNER JOIN profile_public_names AS ppn ON (ppn.pid = ap.pid) + INNER JOIN profile_display AS pd ON (pd.pid = ap.pid) + SET a.lastname = IF(ppn.lastname_ordinary = '', ppn.lastname_main, ppn.lastname_ordinary), + a.firstname = IF(ppn.firstname_ordinary = '', ppn.firstname_main, ppn.firstname_ordinary), + a.full_name = pd.short_name, a.directory_name = pd.directory_name + WHERE a.uid = {?}", + $uid); +} + +function update_display_names(Profile $profile, array $public_names, array $private_names = null) +{ + if (is_null($private_names)) { + $private_names = XDB::fetchAllAssoc('SELECT type, name + FROM profile_private_names + WHERE pid = {?} + ORDER BY type, id', + $profile->id()); } + $display_names = build_display_names($public_names, $private_names, $profile->isFemale()); + + XDB::execute('UPDATE profile_display + SET public_name = {?}, private_name = {?}, + directory_name = {?}, short_name = {?}, sort_name = {?} + WHERE pid = {?}', + $display_names['public_name'], $display_names['private_name'], + $display_names['directory_name'], $display_names['short_name'], + $display_names['sort_name'], $profile->id()); + + Profile::rebuildSearchTokens($profile->id(), false); - // XXX: Improve this when we optimize names handling. - // Updates accounts firt and last names. - XDB::execute('UPDATE accounts AS a - INNER JOIN account_profiles AS ap ON (ap.uid = a.uid AND FIND_IN_SET(\'owner\', ap.perms)) - INNER JOIN profile_name_enum AS le ON (le.type = \'lastname\') - INNER JOIN profile_name_enum AS ce ON (ce.type = \'lastname_ordinary\') - INNER JOIN profile_name AS l ON (ap.pid = l.pid AND le.id = l.typeid) - LEFT JOIN profile_name AS c ON (ap.pid = c.pid AND ce.id = c.typeid) - SET a.lastname = IF(c.pid IS NULL, IF(l.particle != \'\', l.name, CONCAT(l.particle, \' \', l.name)), - IF(c.particle != \'\', c.name, CONCAT(c.particle, \' \', c.name))) - WHERE a.uid = {?}', - $user->id()); + if ($profile->owner()) { + update_account_from_profile($profile->owner()->id()); + } +} - XDB::execute('UPDATE accounts AS a - INNER JOIN account_profiles AS ap ON (ap.uid = a.uid AND FIND_IN_SET(\'owner\', ap.perms)) - INNER JOIN profile_name_enum AS fe ON (fe.type = \'firstname\') - INNER JOIN profile_name_enum AS ce ON (ce.type = \'firstname_ordinary\') - INNER JOIN profile_name AS f ON (ap.pid = f.pid AND fe.id = f.typeid) - LEFT JOIN profile_name AS c ON (ap.pid = c.pid AND ce.id = c.typeid) - SET a.firstname = IF(c.pid IS NULL, f.name, c.name) - WHERE a.uid = {?}', - $user->id()); +function update_public_names($pid, array $public_names) +{ + $public_names['particles'] = new PlFlagSet(); + static $suffixes = array('main', 'marital', 'ordinary'); + foreach ($suffixes as $suffix) { + if (isset($public_names['particle_' . $suffix]) && ($public_names['particle_' . $suffix] == 1 || $public_names['particle_' . $suffix] == 'on')) { + $public_names['particles']->addFlag($suffix, 1); + } + } - Profile::rebuildSearchTokens($pid, false); - return $has_new; + XDB::execute('UPDATE profile_public_names + SET particles = {?}, lastname_main = {?}, lastname_marital = {?}, lastname_ordinary = {?}, + firstname_main = {?}, firstname_ordinary = {?}, pseudonym = {?} + WHERE pid = {?}', + $public_names['particles'], $public_names['lastname_main'], $public_names['lastname_marital'], $public_names['lastname_ordinary'], + $public_names['firstname_main'], $public_names['firstname_ordinary'], $public_names['pseudonym'], $pid); } // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: diff --git a/include/userset.inc.php b/include/userset.inc.php index 55521c7..6153836 100644 --- a/include/userset.inc.php +++ b/include/userset.inc.php @@ -245,8 +245,7 @@ class MinificheView extends MixedView && $this->params['starts_with'] != null) { $this->set->addCond( - new UFC_Name(Profile::LASTNAME, - $this->params['starts_with'], UFC_Name::PREFIX) + new UFC_NameInitial($this->params['starts_with']) ); } return parent::apply($page); diff --git a/include/validations/names.inc.php b/include/validations/names.inc.php index 4d6eb66..8590eb7 100644 --- a/include/validations/names.inc.php +++ b/include/validations/names.inc.php @@ -26,46 +26,35 @@ class NamesReq extends ProfileValidate // {{{ properties public $unique = true; - - public $sn_old; - public $sn_new; - public $display_names; - public $mail_domain; - public $old_alias; - public $new_alias; - public $sn_types; - + public $public_names; + public $old_public_names; + public $old_alias = null; + public $new_alias = null; + public $descriptions = array('lastname_main' => 'Nom patronymique', 'lastname_marital' => 'Nom marital', 'lastname_ordinary' => 'Nom usuel', 'firstname_main' => 'Prénom', 'firstname_ordinary' => 'Prénom usuel', 'pseudonym' => 'Pseudonyme (nom de plume)'); public $rules = "Refuser tout ce qui n'est visiblement pas un nom de famille (ce qui est extremement rare car à peu près n'importe quoi peut être un nom de famille)."; // }}} // {{{ constructor - public function __construct(User $_user, Profile $_profile, $_search_names, $_private_name_end) + public function __construct(User $_user, Profile $_profile, array $_public_names, array $_old_public_names) { parent::__construct($_user, $_profile, true, 'usage'); - require_once 'name.func.inc.php'; - $this->sn_types = build_types(); - $this->sn_old = build_sn_pub($this->profile->id()); - $this->sn_new = $_search_names; - $this->new_alias = true; - $this->display_names = array(); - $this->mail_domain = $this->profileOwner->mainEmailDomain(); - - build_display_names($this->display_names, $_search_names, - $this->profile->isFemale(), $_private_name_end, $this->new_alias); - foreach ($this->sn_new AS $key => &$sn) { - if (!isset($sn['pub'])) { - unset($this->sn_new[$key]); - } - } + $this->public_names = $_public_names; + $this->old_public_names = $_old_public_names; if (!is_null($this->profileOwner)) { + require_once 'name.func.inc.php'; + + $this->new_alias = build_email_alias($this->public_names); $this->old_alias = XDB::fetchOneCell('SELECT email FROM email_source_account WHERE uid = {?} AND type = \'alias\' AND FIND_IN_SET(\'usage\', flags)', $this->profileOwner->id()); - if ($this->old_alias != $this->new_alias) { + + if ($this->old_alias == $this->new_alias) { + $this->old_alias = $this->new_alias = null; + } else { $used = XDB::fetchOneCell('SELECT COUNT(uid) FROM email_source_account WHERE email = {?} AND type != \'alias_aux\'', @@ -130,11 +119,24 @@ class NamesReq extends ProfileValidate { require_once 'name.func.inc.php'; - set_profile_display($this->display_names, $this->profile); + update_public_names($this->profile->id(), $this->public_names); + update_display_names($this->profile, $this->public_names); if (!is_null($this->profileOwner)) { - set_alias_names($this->sn_new, $this->sn_old, $this->profile->id(), - $this->profileOwner, true, $this->new_alias); + if (!is_null($this->old_alias)) { + XDB::execute('DELETE FROM email_source_account + WHERE FIND_IN_SET(\'usage\', flags) AND uid = {?} AND type = \'alias\'', + $this->profileOwner->id()); + } + if (!is_null($this->new_alias)) { + XDB::execute('INSERT INTO email_source_account (email, uid, type, flags, domain) + SELECT {?}, {?}, \'alias\', \'usage\', id + FROM email_virtual_domains + WHERE name = {?}', + $this->new_alias, $this->profileOwner->id(), $this->profileOwner->mainEmailDomain()); + } + require_once 'emails.inc.php'; + fix_bestalias($this->profileOwner); // Update the local User object, to pick up the new bestalias. $this->profileOwner = User::getSilentWithUID($this->profileOwner->id()); @@ -144,6 +146,18 @@ class NamesReq extends ProfileValidate } // }}} + // {{{ function getPublicNames() + + static public function getPublicNames($pid) + { + if ($request = parent::get_typed_request($pid, 'usage')) { + return $request->public_names; + } + return false; + } + + // }}} + } // }}} diff --git a/include/webservices/manageurs.server.inc.php b/include/webservices/manageurs.server.inc.php index 5a4b18c..8eb6d9b 100644 --- a/include/webservices/manageurs.server.inc.php +++ b/include/webservices/manageurs.server.inc.php @@ -179,10 +179,7 @@ function get_nouveau_infos($method, $params) { } // We check we actually have an identification number. if(!empty($params[1])) { - $nameTypes = DirEnum::getOptions(DirEnum::NAMETYPES); - $nameTypes = array_flip($nameTypes); - - $res = XDB::query("SELECT pnl.name AS nom, pnu.name AS nom_usage, pnf.name AS prenom, + $res = XDB::query("SELECT ppn.lastname_initial AS nom, ppn.lastname_ordinary AS nom_usage, ppn.firstname_initial AS prenom, p.sex = 'female' AS femme, p.deathdate IS NOT NULL AS decede, p.birthdate, pd.promo, CONCAT(e.email, '@', d.name) AS mail FROM profiles AS p @@ -190,12 +187,9 @@ function get_nouveau_infos($method, $params) { INNER JOIN email_source_account AS s ON (s.uid = ap.uid AND FIND_IN_SET('bestalias', s.flags)) INNER JOIN email_virtual_domains AS d ON (s.domain = s.id) INNER JOIN profile_display AS pd PN (p.pid = pd.pid) - INNER JOIN profile_name AS pnl ON (p.pid = pnl.pid AND pnl.typeid = {?}) - INNER JOIN profile_name AS pnf ON (p.pid = pnf.pid AND pnf.typeid = {?}) - INNER JOIN profile_name AS pnu ON (p.pid = pnu.pid AND pnu.typeid = {?}) + INNER JOIN profile_public_names AS ppn ON (ppn.pid = p.pid) WHERE a.flags = 'bestalias' AND p.xorg_id = {?}", - $nameTypes['name_ini'], $nameTypes['lastname_ordinary'], - $nameTypes['firstname_ini'], $params[1]); + $params[1]); // $data['mail'] .= '@polytechnique.org'; diff --git a/modules/admin.php b/modules/admin.php index 0ce61e7..9778979 100644 --- a/modules/admin.php +++ b/modules/admin.php @@ -54,7 +54,8 @@ class AdminModule extends PLModule 'admin/xnet_without_group' => $this->make_hook('xnet_without_group', 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'), - 'admin/phd' => $this->make_hook('phd', AUTH_MDP, 'admin') + 'admin/phd' => $this->make_hook('phd', AUTH_MDP, 'admin'), + 'admin/add_secondary_edu' => $this->make_hook('add_secondary_edu', AUTH_MDP, 'admin') ); } @@ -816,8 +817,6 @@ class AdminModule extends PLModule $lines = explode("\n", Env::t('people')); $separator = Env::t('separator'); $promotion = Env::i('promotion'); - $nameTypes = DirEnum::getOptions(DirEnum::NAMETYPES); - $nameTypes = array_flip($nameTypes); if (Env::t('add_type') == 'promo') { $eduSchools = DirEnum::getOptions(DirEnum::EDUSCHOOLS); @@ -877,15 +876,9 @@ class AdminModule extends PLModule VALUES ({?}, {?}, {?}, {?}, {?})', $infos['hrid'], $xorgId, (isset($infos[5]) ? $infos[5] : null), $birthDate, $sex); $pid = XDB::insertId(); - XDB::execute('INSERT INTO profile_name (pid, name, typeid) - VALUES ({?}, {?}, {?}), - ({?}, {?}, {?}), - ({?}, {?}, {?}), - ({?}, {?}, {?})', - $pid, $infos[0], $nameTypes['name_ini'], - $pid, $infos[0], $nameTypes['lastname'], - $pid, $infos[1], $nameTypes['firstname_ini'], - $pid, $infos[1], $nameTypes['firstname']); + XDB::execute('INSERT INTO profile_public_names (pid, lastname_initial, lastname_main, firstname_initial, firstname_main) + VALUES ({?}, {?}, {?}, {?}, {?})', + $pid, $infos[0], $infos[0], $infos[1], $infos[1]); XDB::execute('INSERT INTO profile_display (pid, yourself, public_name, private_name, directory_name, short_name, sort_name, promo) VALUES ({?}, {?}, {?}, {?}, {?}, {?}, {?}, {?})', @@ -1893,6 +1886,115 @@ class AdminModule extends PLModule $page->assign('list', $list); $page->assign('promo', $promo); } + + function handler_add_secondary_edu($page) + { + $page->changeTpl('admin/add_secondary_edu.tpl'); + + if (!(Post::has('verify') || Post::has('add'))) { + return; + } elseif (!Post::has('people')) { + $page->trigWarning("Aucune information n'a été fournie."); + return; + } + + require_once 'name.func.inc.php'; + $lines = explode("\n", Post::t('people')); + $separator = Post::t('separator'); + $degree = Post::v('degree'); + $promotion = Post::i('promotion'); + $schoolsList = array_flip(DirEnum::getOptions(DirEnum::EDUSCHOOLS)); + $degreesList = array_flip(DirEnum::getOptions(DirEnum::EDUDEGREES)); + $edu_id = $schoolsList[Profile::EDU_X]; + $degree_id = $degreesList[$degree]; + + $res = array( + 'incomplete' => array(), + 'empty' => array(), + 'multiple' => array(), + 'already' => array(), + 'new' => array() + ); + $old_pids = array(); + $new_pids = array(); + foreach ($lines as $line) { + $line = trim($line); + $line_array = explode($separator, $line); + array_walk($line_array, 'trim'); + if (count($line_array) != 3) { + $page->trigError("La ligne « $line » est incomplète."); + $res['incomplete'][] = $line; + continue; + } + $cond = new PFC_And(new UFC_NameTokens(split_name_for_search($line_array[0]), array(), false, false, Profile::LASTNAME)); + $cond->addChild(new UFC_NameTokens(split_name_for_search($line_array[1]), array(), false, false, Profile::FIRSTNAME)); + $cond->addChild(new UFC_Promo('=', UserFilter::DISPLAY, $line_array[2])); + $uf = new UserFilter($cond); + $pid = $uf->getPIDs(); + $count = count($pid); + if ($count == 0) { + $page->trigError("La ligne « $line » ne correspond à aucun profil existant."); + $res['empty'][] = $line; + continue; + } elseif ($count > 1) { + $page->trigError("La ligne « $line » correspond à plusieurs profils existant."); + $res['multiple'][] = $line; + continue; + } else { + $count = XDB::fetchOneCell('SELECT COUNT(*) AS count + FROM profile_education + WHERE pid = {?} AND eduid = {?} AND degreeid = {?}', + $pid, $edu_id, $degree_id); + if ($count == 1) { + $res['already'][] = $line; + $old_pids[] = $pid[0]; + } else { + $res['new'][] = $line; + $new_pids[] = $pid[0]; + } + } + } + + $display = array(); + foreach ($res as $type => $res_type) { + if (count($res_type) > 0) { + $display = array_merge($display, array('--------------------' . $type . ':'), $res_type); + } + } + $page->assign('people', implode("\n", $display)); + $page->assign('promotion', $promotion); + $page->assign('degree', $degree); + + if (Post::has('add')) { + $entry_year = $promotion - Profile::educationDuration($degree); + + if (Post::b('force_addition')) { + $pids = array_unique(array_merge($old_pids, $new_pids)); + } else { + $pids = array_unique($new_pids); + + // Updates years. + XDB::execute('UPDATE profile_education + SET entry_year = {?}, grad_year = {?}, promo_year = {?} + WHERE pid IN {?} AND eduid = {?} AND degreeid = {?}', + $entry_year, $promotion, $promotion, $old_pids, $edu_id, $degree_id); + } + + // Precomputes values common to all users. + $select = XDB::format('MAX(id) + 1, pid, {?}, {?}, {?}, {?}, {?}, \'secondary\'', + $edu_id, $degree_id, $entry_year, $promotion, $promotion ); + XDB::startTransaction(); + foreach ($pids as $pid) { + XDB::execute('INSERT INTO profile_education (id, pid, eduid, degreeid, entry_year, grad_year, promo_year, flags) + SELECT ' . $select . ' + FROM profile_education + WHERE pid = {?}', + $pid); + } + XDB::commit(); + } + + } } // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8: diff --git a/modules/payment.php b/modules/payment.php index 40d5d12..bd6139b 100644 --- a/modules/payment.php +++ b/modules/payment.php @@ -163,10 +163,10 @@ class PaymentModule extends PLModule $pay->init($val, $meth); $pay->prepareform($pay); } else { - $res = XDB::iterator('SELECT timestamp, amount + $res = XDB::iterator('SELECT ts_confirmed, amount FROM payment_transactions WHERE uid = {?} AND ref = {?} - ORDER BY timestamp DESC', + ORDER BY ts_confirmed DESC', S::v('uid', -1), $ref); if ($res->total()) { @@ -186,8 +186,7 @@ class PaymentModule extends PLModule $ref); $sum = 0; foreach ($donations as $d) { - $amount = $d['amount']; - $sum += trim(strtr(substr($amount, 0, strpos($amount, 'EUR')), ',', '.')); + $sum += $d['amount']; } $page->assign('donations', $donations); @@ -195,7 +194,7 @@ class PaymentModule extends PLModule } } - $val = floor($val) . '.' . substr(floor(($val - floor($val)) * 100 + 100), 1); + $val = floor($val*100)/100; $page->assign('montant', $val); $page->assign('comment', Env::v('comment')); @@ -246,8 +245,7 @@ class PaymentModule extends PLModule if (Env::v('vads_currency') != '978') { cb_erreur("monnaie autre que l'euro"); } - $amount = ((float)Env::i('vads_amount')) / 100; - $montant = sprintf("%.02f EUR", $amount); + $montant = ((float)Env::i('vads_amount')) / 100; /* on extrait le code de retour */ if (Env::v('vads_result') != '00') { @@ -255,10 +253,10 @@ class PaymentModule extends PLModule } /* on fait l'insertion en base de donnees */ - XDB::execute('INSERT INTO payment_transactions (id, uid, ref, fullref, amount, pkey, comment, display) - VALUES ({?}, {?}, {?}, {?}, {?}, {?}, {?}, {?})', + XDB::execute('INSERT INTO payment_transactions (id, method_id, uid, ref, fullref, ts_confirmed, amount, pkey, comment, status, display) + VALUES ({?}, 2, {?}, {?}, {?}, NOW(), {?}, {?}, {?}, "confirmed", {?})', Env::v('vads_trans_date'), $user->id(), $ref, Env::v('vads_order_id'), $montant, '', Env::v('vads_order_info'), Env::i('vads_order_info2')); - echo "Paiement stored.\n"; + echo "Payment stored.\n"; // We check if it is an Xnet payment and then update the related ML. $res = XDB::query('SELECT eid, asso_id @@ -319,10 +317,11 @@ class PaymentModule extends PLModule /* reference complete de la commande */ $fullref = Env::s('cm'); /* montant de la transaction */ - $montant_nb = Env::s('amt'); + $montant = Env::s('amt'); /* devise */ - $montant_dev = Env::s('cc'); - $montant = "$montant_nb $montant_dev"; + if (Env::s('cc') != 'EUR') { + cb_erreur("monnaie autre que l'euro"); + } /* on extrait le code de retour */ if ($status != "Completed") { @@ -353,8 +352,8 @@ class PaymentModule extends PLModule } /* on fait l'insertion en base de donnees */ - XDB::execute("INSERT INTO payment_transactions (id, uid, ref, fullref, amount, pkey, comment, display) - VALUES ({?}, {?}, {?}, {?}, {?}, {?}, {?}, '?})", + XDB::execute("INSERT INTO payment_transactions (id, method_id, uid, ref, fullref, ts_confirmed, amount, pkey, comment, status, display) + VALUES ({?}, 1, {?}, {?}, {?}, NOW(), {?}, {?}, {?}, 'confirmed', {?})", $no_transaction, $user->id(), $ref, $fullref, $montant, $clef, Env::v('comment'), Get::i('display')); // We check if it is an Xnet payment and then update the related ML. @@ -462,7 +461,7 @@ class PaymentModule extends PLModule foreach($tit as $foo) { $pid = $foo['id']; if (may_update()) { - $res = XDB::query('SELECT p.uid, IF(p.timestamp = \'0000-00-00\', 0, p.timestamp) AS date, p.comment, p.amount + $res = XDB::query('SELECT p.uid, IF(p.ts_confirmed = \'0000-00-00\', 0, p.ts_confirmed) AS date, p.comment, p.amount FROM payment_transactions AS p INNER JOIN accounts AS a ON (a.uid = p.uid) LEFT JOIN account_profiles AS ap ON (ap.uid = p.uid AND FIND_IN_SET(\'owner\', ap.perms)) @@ -472,11 +471,11 @@ class PaymentModule extends PLModule $trans[$pid] = User::getBulkUsersWithUIDs($res->fetchAllAssoc(), 'uid', 'user'); $sum = 0; foreach ($trans[$pid] as $i => $t) { - $sum += strtr(substr($t['amount'], 0, strpos($t['amount'], 'EUR')), ',', '.'); - $trans[$pid][$i]['amount'] = str_replace('EUR', '€', $t['amount']); + $sum += $t['amount']; + $trans[$pid][$i]['amount'] = $t['amount']; } $trans[$pid][] = array('limit' => true, - 'amount' => strtr($sum, '.', ',') . ' €'); + 'amount' => $sum); } $res = XDB::iterRow("SELECT e.eid, e.short_name, e.intitule, ep.nb, ei.montant, ep.paid FROM group_events AS e @@ -497,15 +496,10 @@ class PaymentModule extends PLModule $event[$pid]['paid'] = $paid; } } - $res = XDB::query('SELECT amount + $res = XDB::query('SELECT SUM(amount) AS sum_amount FROM payment_transactions - WHERE id = {?} AND uid = {?}', $pid, S::v('uid')); - $montants = $res->fetchColumn(); - - foreach ($montants as $m) { - $p = strtr(substr($m, 0, strpos($m, 'EUR')), ',', '.'); - $event[$pid]['paid'] += trim($p); - } + WHERE ref = {?} AND uid = {?}', $pid, S::v('uid')); + $event[$pid]['paid'] = $res->fetchOneCell(); } $page->register_modifier('decode_comment', 'decode_comment'); $page->assign('trans', $trans); @@ -521,10 +515,10 @@ class PaymentModule extends PLModule $pid = substr($pid, 0, strlen($pid) - 4); } - $res = XDB::fetchAllAssoc('SELECT uid, IF(timestamp = \'0000-00-00\', 0, timestamp) AS date, comment, amount + $res = XDB::fetchAllAssoc('SELECT uid, IF(ts_confirmed = \'0000-00-00\', 0, ts_confirmed) AS date, comment, amount FROM payment_transactions WHERE ref = {?} - ORDER BY timestamp', + ORDER BY ts_confirmed', $pid); if (is_null($res)) { pl_redirect('payment'); @@ -538,12 +532,12 @@ class PaymentModule extends PLModule fputcsv($csv, array('Date', 'Nom', 'Prénom', 'Sexe', 'Promotion', 'Email', 'Commentaire', 'Montant'), ';'); foreach ($users as $item) { $user = $item['user']; - $sum += strtr(substr($item['amount'], 0, strpos($item['amount'], 'EUR')), ',', '.'); + $sum += $item['amount']; fputcsv($csv, array(format_datetime($item['date'], '%d/%m/%y'), $user->lastName(), $user->firstName(), ($user->isFemale()) ? 'F' : 'M', $user->promo(), $user->ForlifeEmail(), - $item['comment'], str_replace('EUR', '€', $item['amount'])), ';'); + $item['comment'], strtr($item['amount'],'.',',').' €' ), ';'); } - fputcsv($csv, array(date('d/m/y'), 'Total', '', '', '' , '', '', strtr($sum, '.', ',') . ' €'), ';'); + fputcsv($csv, array(date('d/m/y'), 'Total', '', '', '' , '', '', strtr($sum,'.',',').' €'), ';'); fclose($csv); exit; @@ -928,7 +922,11 @@ class PaymentLogsImporter extends CSVImporter { $this->result = array(); foreach ($this->data as $line) { $a = $this->makeAssoc($line, $insert_relation); + // convert date $a['date'] = preg_replace('/([0-9]{2})\/([0-9]{2})\/([0-9]{4}).*/', '\3-\2-\1', $a['date']); + $a['date'] = preg_replace('/T.*/','', $a['date']); + + // convert money $a['amount'] = str_replace(',', '.', $a['amount']); $a['commission'] = str_replace(',', '.', $a['commission']); $this->result[] = $a; diff --git a/modules/profile.php b/modules/profile.php index c464e94..2327016 100644 --- a/modules/profile.php +++ b/modules/profile.php @@ -48,7 +48,6 @@ class ProfileModule extends PLModule 'javascript/education.js' => $this->make_hook('education_js', AUTH_COOKIE), 'javascript/grades.js' => $this->make_hook('grades_js', AUTH_COOKIE), 'profile/medal' => $this->make_hook('medal', AUTH_PUBLIC), - 'profile/name_info' => $this->make_hook('name_info', AUTH_PUBLIC), 'referent' => $this->make_hook('referent', AUTH_COOKIE), 'referent/country' => $this->make_hook('ref_country', AUTH_COOKIE, 'user', NO_AUTH), @@ -69,7 +68,6 @@ class ProfileModule extends PLModule 'admin/trombino' => $this->make_hook('admin_trombino', AUTH_MDP, 'admin'), 'admin/corps_enum' => $this->make_hook('admin_corps_enum', AUTH_MDP, 'admin'), 'admin/corps_rank' => $this->make_hook('admin_corps_rank', AUTH_MDP, 'admin'), - 'admin/names' => $this->make_hook('admin_names', AUTH_MDP, 'admin'), ); } @@ -116,19 +114,6 @@ class ProfileModule extends PLModule exit; } - function handler_name_info($page) - { - pl_content_headers("text/html"); - $page->changeTpl('profile/name_info.tpl', SIMPLE); - $res = XDB::iterator("SELECT name, explanations, - FIND_IN_SET('public', flags) AS public, - FIND_IN_SET('has_particle', flags) AS has_particle - FROM profile_name_enum - WHERE NOT FIND_IN_SET('not_displayed', flags) - ORDER BY NOT FIND_IN_SET('public', flags)"); - $page->assign('types', $res); - } - function handler_networking($page, $mid) { $res = XDB::query("SELECT icon @@ -495,14 +480,11 @@ class ProfileModule extends PLModule function handler_ajax_searchname($page, $id, $isFemale) { pl_content_headers("text/html"); - $page->changeTpl('profile/general.searchname.tpl', NO_SKIN); - $res = XDB::query("SELECT id, name, FIND_IN_SET('public', flags) AS pub - FROM profile_name_enum - WHERE NOT FIND_IN_SET('not_displayed', flags) - AND NOT FIND_IN_SET('always_displayed', flags)"); - $page->assign('sn_type_list', $res->fetchAllAssoc()); + $page->changeTpl('profile/general.private_name.tpl', NO_SKIN); + $page->assign('other_names', array('nickname' => 'Surnom', 'firstname' => 'Autre prénom', 'lastname' => 'Autre nom')); + $page->assign('new_name', true); $page->assign('isFemale', $isFemale); - $page->assign('i', $id); + $page->assign('id', $id); } function handler_ajax_buildnames($page, $data, $isFemale) @@ -715,17 +697,6 @@ class ProfileModule extends PLModule break; } } - function handler_admin_names($page, $action = 'list', $id = null) { - $page->setTitle('Administration - Types de noms'); - $page->assign('title', 'Gestion des types de noms'); - $table_editor = new PLTableEditor('admin/names', 'profile_name_enum', 'id', true); - $table_editor->describe('name', 'Nom', true); - $table_editor->describe('explanations', 'Explications', true); - $table_editor->describe('type', 'Type', true); - $table_editor->describe('flags', 'Flags', true); - $table_editor->describe('score', 'Score', true); - $table_editor->apply($page, $action, $id); - } function handler_admin_binets($page, $action = 'list', $id = null) { $page->setTitle('Administration - Binets'); $page->assign('title', 'Gestion des binets'); diff --git a/modules/profile/general.inc.php b/modules/profile/general.inc.php index 6c29940..6eef643 100644 --- a/modules/profile/general.inc.php +++ b/modules/profile/general.inc.php @@ -21,12 +21,14 @@ class ProfileSettingSearchNames implements ProfileSetting { - private $private_name_end; - private $search_names; - private $name_types; + private function diff($pid, array $old, array $new) + { + $diff = false; + foreach ($old as $field => $name) { + $diff = $diff || ($name != $new[$field]); + } - public function __construct() { - $this->name_types = DirEnum::getOptions(DirEnum::NAMES); + return $diff; } private function matchWord($old, $new, $newLen) @@ -36,174 +38,84 @@ class ProfileSettingSearchNames implements ProfileSetting && ($i + $newLen == strlen($old) || $old{$i + $newLen} == ' '); } - private function prepareField($value) + private function prepare(ProfilePage $page, array &$new_value) { - return name_to_basename($value); - } + $initial_value = XDB::fetchOneAssoc('SELECT lastname_main, firstname_main + FROM profile_public_names + WHERE pid = {?}', + $page->pid()); - private function prepare(ProfilePage $page, $field, $value, $init, &$success) - { $success = true; - $ini = $this->prepareField($init); - $new = $this->prepareField($value); - $newLen = strlen($new); - $success = $this->matchWord($ini, $new, $newLen) - || ($field == 'lastname' && $new == 'DE ' . $ini); - if (!$success) { - $field = strtolower($field); - Platal::page()->trigError("Le " . $this->name_types[$field] . " que tu as choisi (" . $value . - ") est trop loin de ton " . $this->name_types[$field] . " initial (" . $init . ")."); - } - return $success ? $value : $init; - } + foreach ($initial_value as $field => $name) { + $initial = name_to_basename($name); + $new = name_to_basename($new_value[$field]); - /* Removes duplicated entries for the fields that do not allow them. */ - private function clean($value) - { - $single_types = XDB::fetchAllAssoc('id', - 'SELECT id, 0 - FROM profile_name_enum - WHERE NOT FIND_IN_SET(\'allow_duplicates\', flags)'); - - foreach ($value as $key => $item) { - if (isset($single_types[$item['typeid']])) { - if ($single_types[$item['typeid']] === true) { - unset($value[$key]); - } else { - $single_types[$item['typeid']] = true; - } + if (!($this->matchWord($initial, $new, strlen($new)) + || ($field == 'lastname_main' && $new == 'DE ' . $initial))) { + $new_value[$field . '_error'] = true; + $success = false; + Platal::page()->trigError('Le nom choisi (' . $new . ') est trop loin de sa valeur initiale (' . $initial . ').'); } } - return $value; + return $success; } public function value(ProfilePage $page, $field, $value, &$success) { - $success = true; - $success_tmp = true; + $success = true; if (is_null($value)) { - $sn_all = XDB::iterator("SELECT CONCAT(sn.particle, sn.name) AS name, - sn.particle, sn.typeid, e.type, e.name AS type_name, - FIND_IN_SET('has_particle', e.flags) AS has_particle, - FIND_IN_SET('always_displayed', e.flags) AS always_displayed, - FIND_IN_SET('public', e.flags) AS pub - FROM profile_name AS sn - INNER JOIN profile_name_enum AS e ON (e.id = sn.typeid) - WHERE sn.pid = {?} AND NOT FIND_IN_SET('not_displayed', e.flags) - ORDER BY NOT FIND_IN_SET('always_displayed', e.flags), e.id, sn.name", - $page->pid()); - - $sn_types = XDB::iterator("SELECT id, type, name, - FIND_IN_SET('has_particle', flags) AS has_particle - FROM profile_name_enum - WHERE NOT FIND_IN_SET('not_displayed', flags) - AND FIND_IN_SET('always_displayed', flags) - ORDER BY id"); + $request = NamesReq::getPublicNames($page->pid()); - $value = array(); - $sn = $sn_all->next(); - while ($sn_type = $sn_types->next()) { - if ($sn_type['id'] == $sn['typeid']) { - $value[] = $sn; - if ($sn) { - $sn = $sn_all->next(); - } - } else { - $value[] = array('name' => '', - 'particle' => '', - 'typeid' => $sn_type['id'], - 'type' => $sn_type['type'], - 'type_name' => $sn_type['name'], - 'has_particle' => $sn_type['has_particle'], - 'always_displayed' => 1, - 'pub' => 1); + if (!$request) { + $value['public_names'] = XDB::fetchOneAssoc('SELECT particles, lastname_main, lastname_marital, lastname_ordinary, + firstname_main, firstname_ordinary, pseudonym + FROM profile_public_names + WHERE pid = {?}', + $page->pid()); + + $flags = new PlFlagSet($value['public_names']['particles']); + unset($value['public_names']['particles']); + static $suffixes = array('main', 'marital', 'ordinary'); + + foreach ($suffixes as $suffix) { + $value['public_names']['particle_' . $suffix] = $flags->hasFlag($suffix); } - } - if ($sn) { - do { - $value[] = $sn; - } while ($sn = $sn_all->next()); - } - $namesRequest = ProfileValidate::get_typed_requests($page->pid(), 'usage'); - if (count($namesRequest) > 0) { + } else { + $value['public_names'] = $request; Platal::page()->assign('validation', true); } - $value = $this->clean($value); + + $value['private_names'] = XDB::fetchAllAssoc('SELECT type, name + FROM profile_private_names + WHERE pid = {?} + ORDER BY type, id', + $page->pid()); } else { - require_once 'name.func.inc.php'; - - $value = $this->clean($value); - $res = XDB::query("SELECT s.particle, s.name - FROM profile_name AS s - INNER JOIN profile_name_enum AS e ON (e.id = s.typeid) - WHERE s.pid = {?} AND (e.type = 'lastname' OR e.type = 'firstname') - ORDER BY e.type = 'firstname'", - $page->pid()); - $res = $res->fetchAllAssoc(); - $initial = array(); - $initial['lastname'] = $res[0]['particle'] . $res[0]['name']; - $initial['firstname'] = $res[1]['name']; - $sn_types = build_types(); - $this->search_names = array(); - foreach ($value as &$sn) { - $sn['name'] = trim($sn['name']); - if (S::user()->isMe($page->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; - } - if ($sn['pub']) { - if (isset($sn['particle']) && ($sn['particle'] != '')) { - // particle is before first blank - list($particle, $name) = explode(' ', $sn['name'], 2); - $particle = trim($particle) . ' '; - if (!$name) { - // particle is before first quote - list($particle, $name) = explode('\'', $sn['name'], 2); - $particle = trim($particle); - if (!$name) { - // actually there is no particle - $particle = ''; - $name = $sn['name']; - } - } - } else { - $particle = ''; - $name = $sn['name']; - } - } - if ($sn['name'] != '') { - if ($sn['pub']) { - $this->search_names[$sn['typeid']] = array('fullname' => $sn['name'], - 'name' => $name, - 'particle' => $particle, - 'pub' => $sn['pub']); - } else { - if (isset($this->search_names[$sn['typeid']])) { - $this->search_names[$sn['typeid']][] = $sn['name']; - } else { - $this->search_names[$sn['typeid']] = array('fullname' => $sn['name']); - } - $sn['type_name'] = $sn_types[$sn['typeid']]; - } + foreach ($value['public_names'] as $key => $name) { + $value['public_names'][$key] = trim($name); + } + foreach ($value['private_names'] as $key => $name) { + $value['private_names'][$key]['name'] = trim($name['name']); + if ($value['private_names'][$key]['name'] == '') { + unset($value['private_names'][$key]); } } - $res = XDB::query("SELECT public_name, private_name - FROM profile_display - WHERE pid = {?}", - $page->pid()); - list($public_name, $private_name) = $res->fetchOneRow(); - if ($success) { - $sn_types_private = build_types('private'); - $this->private_name_end = build_private_name($this->search_names, $sn_types_private); - $private_name = $public_name . $this->private_name_end; + + if (S::user()->isMe($page->owner)) { + $success = $this->prepare($page, $value['public_names']); } - Platal::page()->assign('public_name', $public_name); - Platal::page()->assign('private_name', $private_name); } + require_once 'name.func.inc.php'; + $public_name = build_first_name($value['public_names']) . ' ' . build_full_last_name($value['public_names'], $page->profile->isFemale()); + $private_name_end = build_private_name($value['private_names']); + $private_name = $public_name . $private_name_end; + + Platal::page()->assign('public_name', $public_name); + Platal::page()->assign('private_name', $private_name); + return $value; } @@ -211,36 +123,57 @@ class ProfileSettingSearchNames implements ProfileSetting { require_once 'name.func.inc.php'; - $sn_old = build_sn_pub($page->pid()); - XDB::execute("DELETE FROM s - USING profile_name AS s - INNER JOIN profile_name_enum AS e ON (s.typeid = e.id) - WHERE s.pid = {?} AND NOT FIND_IN_SET('not_displayed', e.flags)", - $page->pid()); - $has_new = set_alias_names($this->search_names, $sn_old, $page->pid(), $page->owner); + $old = XDB::fetchOneAssoc('SELECT lastname_main, lastname_marital, lastname_ordinary, + firstname_main, firstname_ordinary, pseudonym + FROM profile_public_names + WHERE pid = {?}', + $page->pid()); - // Only requires validation if modification in public names - if ($has_new) { - $new_names = new NamesReq(S::user(), $page->profile, $this->search_names, $this->private_name_end); + if ($has_diff = $this->diff($page->pid(), $old, $value['public_names'])) { + $new_names = new NamesReq(S::user(), $page->profile, $value['public_names'], $old); $new_names->submit(); - Platal::page()->trigWarning('La demande de modification de tes noms a bien été prise en compte.' . - ' Tu recevras un email dès que ces changements auront été effectués.'); + Platal::page()->assign('validation', true); + Platal::page()->trigWarning('La demande de modification des noms a bien été prise en compte.' . + ' Un email sera envoyé dès que ces changements auront été effectués.'); + } + + XDB::execute('DELETE FROM profile_private_names + WHERE pid = {?}', + $page->pid()); + $values = array(); + $nickname = $lastname = $firstname = 0; + foreach ($value['private_names'] as $name) { + $values[] = XDB::format('({?}, {?}, {?}, {?})', $page->pid(), $name['type'], $$name['type']++, $name['name']); + } + if (count($values)) { + XDB::rawExecute('INSERT INTO profile_private_names (pid, type, id, name) + VALUES ' . implode(',', $values)); + } + + if ($has_diff) { + update_display_names($page->profile, $old, $value['private_names']); } else { - $display_names = array(); - build_display_names($display_names, $this->search_names, - $page->profile->isFemale(), $this->private_name_end); - set_profile_display($display_names, $page->profile); + update_display_names($page->profile, $value['public_names'], $value['private_names']); } } public function getText($value) { - $names = array(); - foreach ($value as $name) { - if ($name['name'] != '') { - $names[] = mb_strtolower($name['type_name']) . ' : ' . $name['name']; + $public_names = array(); + foreach ($value['public_names'] as $name) { + if ($name != '') { + $public_names[] = $name; } } - return implode(', ' , $names); + + if (count($value['private_names'])) { + $private_names = array(); + foreach ($value['private_names'] as $name) { + $private_names[] = $name['name']; + } + return 'noms publics : ' . implode(', ' , $public_names) . ', noms privés : ' . implode(', ' , $private_names);; + } + + return 'noms publics : ' . implode(', ' , $public_names); } } @@ -265,7 +198,7 @@ class ProfileSettingEdu implements ProfileSetting $value = array(); $value = XDB::fetchAllAssoc("SELECT eduid, degreeid, fieldid, grad_year, program FROM profile_education - WHERE pid = {?} AND !FIND_IN_SET('primary', flags) + WHERE pid = {?} AND !(FIND_IN_SET('primary', flags) OR FIND_IN_SET('secondary', flags)) ORDER BY id", $page->pid()); } else if (!is_array($value)) { @@ -296,10 +229,11 @@ class ProfileSettingEdu implements ProfileSetting public function save(ProfilePage $page, $field, $value) { XDB::execute("DELETE FROM profile_education - WHERE pid = {?} AND !FIND_IN_SET('primary', flags)", + WHERE pid = {?} AND !(FIND_IN_SET('primary', flags) OR FIND_IN_SET('secondary', flags))", $page->pid()); + $schoolsList = DirEnum::getOptions(DirEnum::EDUSCHOOLS); foreach ($value as $eduid=>&$edu) { - if ($edu['eduid'] != '') { + if ($edu['eduid'] != '' && $schoolsList[$edu['eduid']] != Profile::EDU_X) { $fieldId = ($edu['fieldid'] == 0) ? null : $edu['fieldid']; XDB::execute("INSERT INTO profile_education SET id = {?}, pid = {?}, eduid = {?}, degreeid = {?}, @@ -368,8 +302,8 @@ class ProfileSettingMainEdu implements ProfileSetting $value = array(); $value = XDB::fetchAllAssoc("SELECT degreeid, fieldid, promo_year, program FROM profile_education - WHERE pid = {?} AND FIND_IN_SET('primary', flags) - ORDER BY degreeid", + WHERE pid = {?} AND (FIND_IN_SET('primary', flags) OR FIND_IN_SET('secondary', flags)) + ORDER BY NOT FIND_IN_SET('primary', flags), degreeid", $page->pid()); foreach ($value as &$item) { @@ -394,7 +328,7 @@ class ProfileSettingMainEdu implements ProfileSetting $fieldId = ($item['fieldid'] == 0) ? null : $item['fieldid']; XDB::execute("UPDATE profile_education SET fieldid = {?}, program = {?} - WHERE pid = {?} AND FIND_IN_SET('primary', flags) AND degreeid = {?}", + WHERE pid = {?} AND (FIND_IN_SET('primary', flags) OR FIND_IN_SET('secondary', flags)) AND degreeid = {?}", $fieldId, $item['program'], $page->pid(), $item['degreeid']); } } @@ -795,13 +729,9 @@ class ProfilePageGeneral extends ProfilePage ORDER BY name"); $page->assign('network_list', $res->fetchAllAssoc()); - $res = XDB::query("SELECT public_name, private_name - FROM profile_display - WHERE pid = {?}", - $this->pid()); - $res = $res->fetchOneRow(); - $page->assign('public_name', $res[0]); - $page->assign('private_name', $res[1]); + $page->assign('lastnames', array('main' => 'Nom patronymique', 'marital' => 'Nom marital', 'ordinary' => 'Nom usuel')); + $page->assign('firstnames', array('firstname_main' => 'Prénom', 'firstname_ordinary' => 'Prénom usuel', 'pseudonym' => 'Pseudonyme (nom de plume)')); + $page->assign('other_names', array('nickname' => 'Surnom', 'firstname' => 'Autre prénom', 'lastname' => 'Autre nom')); $page->assign('isFemale', $this->profile->isFemale() ? 1 : 0); } } diff --git a/modules/register.php b/modules/register.php index 3a4279a..16d02a7 100644 --- a/modules/register.php +++ b/modules/register.php @@ -49,9 +49,7 @@ class RegisterModule extends PLModule } if ($hash) { - $nameTypes = DirEnum::getOptions(DirEnum::NAMETYPES); - $nameTypes = array_flip($nameTypes); - $res = XDB::query("SELECT a.uid, a.hruid, pnl.name AS lastname, pnf.name AS firstname, p.xorg_id AS xorgid, + $res = XDB::query("SELECT a.uid, a.hruid, ppn.lastname_initial AS lastname, ppn.firstname_initial AS firstname, p.xorg_id AS xorgid, pd.promo, pe.promo_year AS yearpromo, pde.degree AS edu_type, p.birthdate_ref AS birthdateRef, FIND_IN_SET('watch', a.flags) AS watch, m.hash, a.type FROM register_marketing AS m @@ -61,10 +59,9 @@ class RegisterModule extends PLModule INNER JOIN profile_display AS pd ON (p.pid = pd.pid) INNER JOIN profile_education AS pe ON (pe.pid = p.pid AND FIND_IN_SET('primary', pe.flags)) INNER JOIN profile_education_degree_enum AS pde ON (pde.id = pe.degreeid) - INNER JOIN profile_name AS pnl ON (p.pid = pnl.pid AND pnl.typeid = {?}) - INNER JOIN profile_name AS pnf ON (p.pid = pnf.pid AND pnf.typeid = {?}) + INNER JOIN profile_public_names AS ppn ON (ppn.pid = p.pid) WHERE m.hash = {?} AND a.state = 'pending'", - $nameTypes['name_ini'], $nameTypes['firstname_ini'], $hash); + $hash); if ($res->numRows() == 1) { $subState->merge($res->fetchOneRow()); @@ -281,25 +278,21 @@ class RegisterModule extends PLModule return PL_FORBIDDEN; } - $nameTypes = DirEnum::getOptions(DirEnum::NAMETYPES); - $nameTypes = array_flip($nameTypes); - // Retrieve the pre-registration information using the url-provided // authentication token. $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, pe.promo_year, + ppn.lastname_initial, ppn.firstname_initial, pe.promo_year, pd.promo, p.sex, p.birthdate_ref, a.type 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)) INNER JOIN profiles AS p ON (p.pid = ap.pid) - INNER JOIN profile_name AS pnl ON (p.pid = pnl.pid AND pnl.typeid = {?}) - INNER JOIN profile_name AS pnf ON (p.pid = pnf.pid AND pnf.typeid = {?}) + INNER JOIN profile_public_names AS ppn ON (ppn.pid = p.pid) INNER JOIN profile_display AS pd ON (p.pid = pd.pid) INNER JOIN profile_education AS pe ON (pe.pid = p.pid AND FIND_IN_SET('primary', pe.flags)) WHERE hash = {?} AND hash != 'INSCRIT' AND a.state = 'pending'", - $nameTypes['name_ini'], $nameTypes['firstname_ini'], $hash); + $hash); if (!$hash || $res->numRows() == 0) { $page->kill("

Cette adresse n'existe pas, ou plus, sur le serveur.

Causes probables :

diff --git a/modules/xnetevents.php b/modules/xnetevents.php index 45767f5..edee012 100644 --- a/modules/xnetevents.php +++ b/modules/xnetevents.php @@ -151,16 +151,11 @@ class XnetEventsModule extends PLModule $e['topay'] += $m['nb'] * $m['montant']; } - $query = XDB::query( - "SELECT amount + $montant = XDB::fetchOneCell( + "SELECT SUM(amount) as sum_amount FROM payment_transactions AS t WHERE ref = {?} AND uid = {?}", $e['paiement_id'], S::v('uid')); - $montants = $query->fetchColumn(); - - foreach ($montants as $m) { - $p = strtr(substr($m, 0, strpos($m, 'EUR')), ',', '.'); - $e['paid'] += trim($p); - } + $e['paid'] += $montant; make_event_date($e); @@ -635,8 +630,7 @@ class XnetEventsModule extends PLModule GROUP BY p.uid', $evt['eid']); $ofs = Env::i('offset'); - $tot = (is_null($evt['nb_tot']) ? $evt['nb'] : $evt['nb_tot']); - $nbp = ceil($tot / NB_PER_PAGE); + $nbp = ceil($evt['user_count'] / NB_PER_PAGE); if ($nbp > 1) { $links = array(); if ($ofs) { diff --git a/modules/xnetevents/xnetevents.inc.php b/modules/xnetevents/xnetevents.inc.php index cc95c4d..c60b938 100644 --- a/modules/xnetevents/xnetevents.inc.php +++ b/modules/xnetevents/xnetevents.inc.php @@ -27,7 +27,7 @@ function get_event_detail($eid, $item_id = false, $asso_id = null) if (is_null($asso_id)) { $asso_id = $globals->asso('id'); } - $evt = XDB::fetchOneAssoc('SELECT SUM(nb) AS nb_tot, COUNT(DISTINCT ep.uid) AS nb, e.*, + $evt = XDB::fetchOneAssoc('SELECT SUM(nb) AS nb_tot, COUNT(DISTINCT ep.uid) AS nb, e.*, SUM(IF(nb > 0, 1, 0)) AS user_count, IF(e.deadline_inscription, e.deadline_inscription >= LEFT(NOW(), 10), 1) AS inscr_open, @@ -80,16 +80,12 @@ function get_event_detail($eid, $item_id = false, $asso_id = null) $evt['notify_payment'] = $evt['notify_payment'] || $m['notify_payment']; } - $montants = XDB::fetchColumn('SELECT amount + $montant = XDB::fetchOneCell('SELECT SUM(amount) AS sum_amount FROM payment_transactions AS t WHERE ref = {?} AND uid = {?}', $evt['paiement_id'], S::v('uid')); - $evt['telepaid'] = 0; - foreach ($montants as $m) { - $p = strtr(substr($m, 0, strpos($m, 'EUR')), ',', '.'); - $evt['paid'] += trim($p); - $evt['telepaid'] += trim($p); - } + $evt['telepaid'] = $montant; + $evt['paid'] += $montant; $evt['organizer'] = User::getSilent($evt['uid']); make_event_date($evt); @@ -102,7 +98,7 @@ function get_event_detail($eid, $item_id = false, $asso_id = null) // }}} // {{{ function get_event_participants() -function get_event_participants(&$evt, $item_id, array $tri = array(), $limit = null) +function get_event_participants(&$evt, $item_id, array $tri = array(), $limit = null, $offset = 0) { global $globals; @@ -117,7 +113,7 @@ function get_event_participants(&$evt, $item_id, array $tri = array(), $limit = WHERE ep.eid = {?} AND nb > 0 ' . $append . ' GROUP BY ep.uid', $eid); $uf = new UserFilter(new PFC_True(), $tri); - $users = User::getBulkUsersWithUIDs($uf->filter(array_keys($query), new PlLimit($count, $offset))); + $users = User::getBulkUsersWithUIDs($uf->filter(array_keys($query), new PlLimit($limit, $offset))); $tab = array(); foreach ($users as $user) { $uid = $user->id(); @@ -137,14 +133,11 @@ function get_event_participants(&$evt, $item_id, array $tri = array(), $limit = $u['adminpaid'] = $u['paid']; $u['montant'] = 0; if ($money && $pay_id) { - $montants = XDB::fetchColumn('SELECT amount + $montant = XDB::fetchOneCell('SELECT SUM(amount) FROM payment_transactions AS t WHERE ref = {?} AND uid = {?}', $pay_id, $uid); - foreach ($montants as $m) { - $p = strtr(substr($m, 0, strpos($m, "EUR")), ",", "."); - $u['paid'] += trim($p); - } + $u['paid'] += $montant; } $u['telepayment'] = $u['paid'] - $u['adminpaid']; $res_ = XDB::iterator('SELECT ep.nb, ep.item_id, ei.montant diff --git a/modules/xnetgrp.php b/modules/xnetgrp.php index 4b5e9f6..41fe737 100644 --- a/modules/xnetgrp.php +++ b/modules/xnetgrp.php @@ -970,10 +970,10 @@ class XnetGrpModule extends PLModule list($lastname, $firstname) = str_replace(array('-', ' ', "'"), '%', array(Env::t('nom'), Env::t('prenom'))); $cond = new PFC_And(new PFC_Not(new UFC_Registered())); if (!empty($lastname)) { - $cond->addChild(new UFC_Name(Profile::LASTNAME, $lastname, UFC_Name::CONTAINS)); + $cond->addChild(new UFC_NameTokens($lastname, array(), false, false, Profile::LASTNAME)); } if (!empty($firstname)) { - $cond->addChild(new UFC_Name(Profile::FIRSTNAME, $firstname, UFC_Name::CONTAINS)); + $cond->addChild(new UFC_NameTokens($firstname, array(), false, false, Profile::FIRSTNAME)); } if (Env::t('promo')) { $cond->addChild(new UFC_Promo('=', UserFilter::DISPLAY, Env::t('promo'))); diff --git a/templates/admin/add_secondary_edu.tpl b/templates/admin/add_secondary_edu.tpl new file mode 100644 index 0000000..7616d46 --- /dev/null +++ b/templates/admin/add_secondary_edu.tpl @@ -0,0 +1,72 @@ +{**************************************************************************} +{* *} +{* Copyright (C) 2003-2011 Polytechnique.org *} +{* http://opensource.polytechnique.org/ *} +{* *} +{* This program is free software; you can redistribute it and/or modify *} +{* it under the terms of the GNU General Public License as published by *} +{* the Free Software Foundation; either version 2 of the License, or *} +{* (at your option) any later version. *} +{* *} +{* This program is distributed in the hope that it will be useful, *} +{* but WITHOUT ANY WARRANTY; without even the implied warranty of *} +{* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *} +{* GNU General Public License for more details. *} +{* *} +{* You should have received a copy of the GNU General Public License *} +{* along with this program; if not, write to the Free Software *} +{* Foundation, Inc., *} +{* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *} +{* *} +{**************************************************************************} + +

Ajout de formations secondaires

+ +
+ + + + + + + + + + + + + +
+ Promotion : + + +
+ Formation : + + - + +
+ Forcer l'ajout :
(en cas de formation du même niveau préexistante) +
+ +
+ + + + + + + + + + +
NomPrénomPromotion principale
+ +

+ Séparateur : +

+      +

+
+ +{* vim:set et sws=2 sts=2 sw=2 enc=utf-8: *} diff --git a/templates/admin/index.tpl b/templates/admin/index.tpl index fbb6ad3..7132a26 100644 --- a/templates/admin/index.tpl +++ b/templates/admin/index.tpl @@ -116,9 +116,11 @@ - Promotions + Formations Doctorants +   |   + Ajout de formation @@ -162,8 +164,6 @@   |   Sections   |   - Noms -   |   Networking   |   Modifications récentes diff --git a/templates/include/form.valid.names.tpl b/templates/include/form.valid.names.tpl index 57383a7..2e33212 100644 --- a/templates/include/form.valid.names.tpl +++ b/templates/include/form.valid.names.tpl @@ -29,16 +29,16 @@ Nouvel alias : {$valid->new_alias} -{foreach from=$valid->sn_new item=sn key=typeid} +{foreach from=$valid->public_names item=name key=type} - *{$valid->sn_types.$typeid} : - {$sn.name} + *{$valid->descriptions.$type} : + {$name} {/foreach} -{foreach from=$valid->sn_old item=sn key=typeid} +{foreach from=$valid->old_public_names item=name key=type} - †{$valid->sn_types.$typeid} : - {$sn.name} + †{$valid->descriptions.$type} : + {$name} {/foreach} diff --git a/templates/payment/index.tpl b/templates/payment/index.tpl index 1b40c17..69b0bc7 100644 --- a/templates/payment/index.tpl +++ b/templates/payment/index.tpl @@ -167,8 +167,8 @@ function payment_submit(form) DateMontant {iterate from=$transactions item=t} - {$t.timestamp|date_format} - {$t.amount|replace:'EUR':'€'} + {$t.ts_confirmed|date_format} + {$t.amount|replace:'.':','} € {/iterate} @@ -187,7 +187,7 @@ function payment_submit(form) {foreach from=$donations item=d} {$d.name} - {$d.amount|replace:'EUR':'€'} + {$d.amount|replace:'.':','} € {/foreach} diff --git a/templates/payment/xnet.tpl b/templates/payment/xnet.tpl index 89dddb1..1ab4219 100644 --- a/templates/payment/xnet.tpl +++ b/templates/payment/xnet.tpl @@ -139,7 +139,7 @@ il suffit de cliquer sur le titre de la colonne concernée. {$p.user->promo()} {$p.comment|comment_decode} - {$p.amount} + {$p.amount|replace:'.':','} € {elseif $smarty.foreach.people.first} @@ -148,7 +148,7 @@ il suffit de cliquer sur le titre de la colonne concernée. {else} Total - {$p.amount} + {$p.amount|replace:'.':','} € {/if} {/foreach} diff --git a/templates/profile/general.private_name.tpl b/templates/profile/general.private_name.tpl new file mode 100644 index 0000000..15dbeda --- /dev/null +++ b/templates/profile/general.private_name.tpl @@ -0,0 +1,44 @@ +{**************************************************************************} +{* *} +{* Copyright (C) 2003-2011 Polytechnique.org *} +{* http://opensource.polytechnique.org/ *} +{* *} +{* This program is free software; you can redistribute it and/or modify *} +{* it under the terms of the GNU General Public License as published by *} +{* the Free Software Foundation; either version 2 of the License, or *} +{* (at your option) any later version. *} +{* *} +{* This program is distributed in the hope that it will be useful, *} +{* but WITHOUT ANY WARRANTY; without even the implied warranty of *} +{* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *} +{* GNU General Public License for more details. *} +{* *} +{* You should have received a copy of the GNU General Public License *} +{* along with this program; if not, write to the Free Software *} +{* Foundation, Inc., *} +{* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *} +{* *} +{**************************************************************************} + +{assign var=type value=$name.type} + + + {icon name="flag_red" title="site privé"}{if !t($new_name)} {$other_names.$type}{else} + + {/if} + + + {if !t($new_name)}{/if} + + + + {icon name=cross title="Supprimer ce nom"} + + + +{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *} diff --git a/templates/profile/general.public_names.tpl b/templates/profile/general.public_names.tpl new file mode 100644 index 0000000..adbdb12 --- /dev/null +++ b/templates/profile/general.public_names.tpl @@ -0,0 +1,57 @@ +{**************************************************************************} +{* *} +{* Copyright (C) 2003-2011 Polytechnique.org *} +{* http://opensource.polytechnique.org/ *} +{* *} +{* This program is free software; you can redistribute it and/or modify *} +{* it under the terms of the GNU General Public License as published by *} +{* the Free Software Foundation; either version 2 of the License, or *} +{* (at your option) any later version. *} +{* *} +{* This program is distributed in the hope that it will be useful, *} +{* but WITHOUT ANY WARRANTY; without even the implied warranty of *} +{* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *} +{* GNU General Public License for more details. *} +{* *} +{* You should have received a copy of the GNU General Public License *} +{* along with this program; if not, write to the Free Software *} +{* Foundation, Inc., *} +{* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *} +{* *} +{**************************************************************************} + +{foreach from=$lastnames key=suffix item=description} +{assign var=type value="lastname_"|cat:$suffix} +{assign var=error value=$type|cat:"_error"} +{assign var=particle value="particle_"|cat:$suffix} + + + {icon name="flag_green" title="site public"} {$description} + + + + + + + + +{/foreach} + +{foreach from=$firstnames key=type item=description} +{assign var=error value=$type|cat:"_error"} + + + {icon name="flag_green" title="site public"} {$description} + + + + + + +{/foreach} + +{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *} diff --git a/templates/profile/general.searchname.tpl b/templates/profile/general.searchname.tpl deleted file mode 100644 index 8ede1d9..0000000 --- a/templates/profile/general.searchname.tpl +++ /dev/null @@ -1,65 +0,0 @@ -{**************************************************************************} -{* *} -{* Copyright (C) 2003-2011 Polytechnique.org *} -{* http://opensource.polytechnique.org/ *} -{* *} -{* This program is free software; you can redistribute it and/or modify *} -{* it under the terms of the GNU General Public License as published by *} -{* the Free Software Foundation; either version 2 of the License, or *} -{* (at your option) any later version. *} -{* *} -{* This program is distributed in the hope that it will be useful, *} -{* but WITHOUT ANY WARRANTY; without even the implied warranty of *} -{* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *} -{* GNU General Public License for more details. *} -{* *} -{* You should have received a copy of the GNU General Public License *} -{* along with this program; if not, write to the Free Software *} -{* Foundation, Inc., *} -{* 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *} -{* *} -{**************************************************************************} - - - - - - - {if $sn.pub}{icon name="flag_green" title="site public"} - {else}{icon name="flag_red" title="site privé"}{/if} -   - {if t($sn_type_list)} - - {foreach from=$sn_type_list item=sn_type} - - {/foreach} - {else} - {$sn.type_name} - - - - - {/if} - - - - - - {if $sn.has_particle} - {/if} - - {if !$sn.always_displayed} - {icon name=cross title="Supprimer ce nom"} - {/if} - - - -{* vim:set et sw=2 sts=2 sws=2 enc=utf-8: *} diff --git a/templates/profile/general.tpl b/templates/profile/general.tpl index e23aec5..f0ddda7 100644 --- a/templates/profile/general.tpl +++ b/templates/profile/general.tpl @@ -65,16 +65,14 @@ Gestion des noms, prénoms, surnoms... Ils déterminent la façon dont {if $isMe}ton{else}son{/if} nom apparaît sur les annuaires - en ligne et papier et ta fiche apparaitra quand on cherche un de ces noms. Pour plus - d'explications sur l'icône suivante - {icon name="information" title="Plus d'infos"}.
+ en ligne et papier et ta fiche apparaitra quand on cherche un de ces noms.
Si un de tes noms commence par une particule, coche la case en bout de ligne.
- {foreach from=$search_names item=sn key=id} - {include file="profile/general.searchname.tpl" i=$id sn=$sn - class="names_advanced" style="display: none" error_name=$errors.search_names} + {include file="profile/general.public_names.tpl" names=$search_names.public_names} + {foreach from=$search_names.private_names key=id item=name} + {include file="profile/general.private_name.tpl"} {/foreach} diff --git a/templates/xnetevents/admin.tpl b/templates/xnetevents/admin.tpl index 4ed095d..c27462d 100644 --- a/templates/xnetevents/admin.tpl +++ b/templates/xnetevents/admin.tpl @@ -97,7 +97,7 @@ Ils ont payé mais ont oublié de s'inscrire : {icon name=vcard title="vcard"} {icon name=email title="email"} - {$m.amount} + {$m.amount|replace:'.':','} € {/foreach} diff --git a/upgrade/1.0.1/13_payments.sql b/upgrade/1.0.1/13_payments.sql index 6252fbd..0196b9a 100644 --- a/upgrade/1.0.1/13_payments.sql +++ b/upgrade/1.0.1/13_payments.sql @@ -55,26 +55,6 @@ CREATE TABLE payment_reconcilations ( comments text NOT NULL ) ENGINE=InnoDB, CHARSET=utf8; -ALTER TABLE payment_transactions ADD method_id INTEGER DEFAULT NULL AFTER id; # NULL if not initiated from the site -ALTER TABLE payment_transactions CHANGE timestamp ts_confirmed DATETIME DEFAULT NULL; # NULL = not confirmed -ALTER TABLE payment_transactions ADD ts_initiated DATETIME DEFAULT NULL AFTER ts_confirmed; # NULL = not initiated -ALTER TABLE payment_transactions CHANGE amount amount_tmp VARCHAR(15); -ALTER TABLE payment_transactions ADD amount DECIMAL(9,2) NOT NULL AFTER amount_tmp; # only local currency allowed (EUR) -ALTER TABLE payment_transactions ADD commission DECIMAL(9,2) DEFAULT NULL AFTER amount; -ALTER TABLE payment_transactions ADD status ENUM('confirmed','pending','canceled') NOT NULL DEFAULT 'pending'; -ALTER TABLE payment_transactions ADD recon_id INTEGER DEFAULT NULL; # NULL = not reconciliated -UPDATE payment_transactions SET method_id = 0 WHERE length(id)=7; -UPDATE payment_transactions SET method_id = 1 WHERE length(id)=15 OR length(id)=17; -UPDATE payment_transactions SET method_id = 2 WHERE length(id)=14; -UPDATE payment_transactions SET status = 'confirmed'; -UPDATE payment_transactions SET amount=CONVERT(REPLACE(REPLACE(amount_tmp," EUR",""),",","."),DECIMAL(9,2)); -ALTER TABLE payment_transactions ADD KEY method_id (method_id); -ALTER TABLE payment_transactions ADD KEY ref (ref); -# ALTER TABLE payment_transactions ADD UNIQUE KEY fullref (fullref); -#fullref dupliqués : -#select t1.* from payment_transactions as t1 join payment_transactions as t2 using(fullref) group by(t1.id) having count(*)!=1 order by fullref; -ALTER TABLE payment_transactions DROP amount_tmp; - DROP TABLE IF EXISTS payment_transfers; CREATE TABLE payment_transfers ( id INTEGER PRIMARY KEY auto_increment, diff --git a/upgrade/1.1.2/02_payments.sql b/upgrade/1.1.2/02_payments.sql index 64359f7..99332d3 100644 --- a/upgrade/1.1.2/02_payments.sql +++ b/upgrade/1.1.2/02_payments.sql @@ -1,4 +1,25 @@ -ALTER TABLE payments MODIFY COLUMN flags SET('unique', 'old', 'donation') NOT NULL DEFAULT ''; +ALTER TABLE payment_transactions ADD method_id INTEGER DEFAULT NULL AFTER id; # NULL if not initiated from the site +ALTER TABLE payment_transactions CHANGE timestamp ts_confirmed DATETIME DEFAULT NULL; # NULL = not confirmed +ALTER TABLE payment_transactions ADD ts_initiated DATETIME DEFAULT NULL AFTER ts_confirmed; # NULL = not initiated +ALTER TABLE payment_transactions CHANGE amount amount_tmp VARCHAR(15); +ALTER TABLE payment_transactions ADD amount DECIMAL(9,2) NOT NULL AFTER amount_tmp; # only local currency allowed (EUR) +ALTER TABLE payment_transactions ADD commission DECIMAL(9,2) DEFAULT NULL AFTER amount; +ALTER TABLE payment_transactions ADD status ENUM('confirmed','pending','canceled') NOT NULL DEFAULT 'pending'; +ALTER TABLE payment_transactions ADD recon_id INTEGER DEFAULT NULL; # NULL = not reconciliated +UPDATE payment_transactions SET method_id = 0 WHERE length(id)=7; +UPDATE payment_transactions SET method_id = 1 WHERE length(id)=15 OR length(id)=17; +UPDATE payment_transactions SET method_id = 2 WHERE length(id)=14; +UPDATE payment_transactions SET status = 'confirmed'; +UPDATE payment_transactions SET amount=CONVERT(REPLACE(REPLACE(amount_tmp," EUR",""),",","."),DECIMAL(9,2)); +ALTER TABLE payment_transactions ADD KEY method_id (method_id); +ALTER TABLE payment_transactions ADD KEY ref (ref); +# ALTER TABLE payment_transactions ADD UNIQUE KEY fullref (fullref); +#fullref dupliqués : +#select t1.* from payment_transactions as t1 join payment_transactions as t2 using(fullref) group by(t1.id) having count(*)!=1 order by fullref; +ALTER TABLE payment_transactions DROP amount_tmp; + ALTER TABLE payment_transactions ADD COLUMN display BOOL NOT NULL DEFAULT FALSE; +ALTER TABLE payments MODIFY COLUMN flags SET('unique', 'old', 'donation') NOT NULL DEFAULT ''; -- vim:set syntax=mysql: + diff --git a/upgrade/1.1.2/03_names.sql b/upgrade/1.1.2/03_names.sql new file mode 100644 index 0000000..1f4ac25 --- /dev/null +++ b/upgrade/1.1.2/03_names.sql @@ -0,0 +1,106 @@ +DROP TABLE IF EXISTS profile_public_names; +CREATE TABLE IF NOT EXISTS profile_public_names ( + pid INT(11) UNSIGNED NOT NULL DEFAULT 0, + particles SET('initial', 'main', 'marital', 'ordinary') NOT NULL DEFAULT '', + lastname_initial VARCHAR(255) NOT NULL DEFAULT '', + lastname_main VARCHAR(255) NOT NULL DEFAULT '', + lastname_marital VARCHAR(255) NOT NULL DEFAULT '', + lastname_ordinary VARCHAR(255) NOT NULL DEFAULT '', + firstname_initial VARCHAR(255) NOT NULL DEFAULT '', + firstname_main VARCHAR(255) NOT NULL DEFAULT '', + firstname_ordinary VARCHAR(255) NOT NULL DEFAULT '', + pseudonym VARCHAR(255) NOT NULL DEFAULT '', + PRIMARY KEY (pid), + FOREIGN KEY (pid) REFERENCES profiles (pid) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +DROP TABLE IF EXISTS profile_private_names; +CREATE TABLE IF NOT EXISTS profile_private_names ( + pid INT(11) UNSIGNED NOT NULL DEFAULT 0, + type ENUM('lastname', 'firstname', 'nickname') NOT NULL DEFAULT 'nickname', + id TINYINT(2) UNSIGNED NOT NULL DEFAULT 0 COMMENT 'id of the name among those sharing the same pid / general_type', + name VARCHAR(255) NOT NULL DEFAULT '', + PRIMARY KEY (pid, type, id), + FOREIGN KEY (pid) REFERENCES profiles (pid) ON DELETE CASCADE ON UPDATE CASCADE +) ENGINE=InnoDB DEFAULT CHARSET=utf8; + +-- Initiates profile_public_names. +INSERT INTO profile_public_names (pid) + SELECT pid + FROM profiles; + +-- Insert lastnames. + UPDATE profile_public_names AS ppn +INNER JOIN profile_name AS pn ON (pn.pid = ppn.pid) +INNER JOIN profile_name_enum AS pne ON (pn.typeid = pne.id) + SET ppn.lastname_initial = IF(pn.particle = '', pn.name, CONCAT(pn.particle, ' ', pn.name)), + ppn.particles = IF(pn.particle = '', '', 'initial') + WHERE pne.type = 'name_ini'; + UPDATE profile_public_names AS ppn +INNER JOIN profile_name AS pn ON (pn.pid = ppn.pid) +INNER JOIN profile_name_enum AS pne ON (pn.typeid = pne.id) + SET ppn.lastname_main = IF(pn.particle = '', pn.name, CONCAT(pn.particle, ' ', pn.name)), + ppn.particles = IF(pn.particle = '', ppn.particles, CONCAT_WS(',', ppn.particles, 'main')) + WHERE pne.type = 'lastname'; +UPDATE profile_public_names + SET particles = TRIM(BOTH ',' FROM particles); + UPDATE profile_public_names AS ppn +INNER JOIN profile_name AS pn ON (pn.pid = ppn.pid) +INNER JOIN profile_name_enum AS pne ON (pn.typeid = pne.id) + SET ppn.lastname_marital = IF(pn.particle = '', pn.name, CONCAT(pn.particle, ' ', pn.name)), + ppn.particles = IF(pn.particle = '', ppn.particles, CONCAT_WS(',', ppn.particles, 'marital')) + WHERE pne.type = 'lastname_marital'; +UPDATE profile_public_names + SET particles = TRIM(BOTH ',' FROM particles); + UPDATE profile_public_names AS ppn +INNER JOIN profile_name AS pn ON (pn.pid = ppn.pid) +INNER JOIN profile_name_enum AS pne ON (pn.typeid = pne.id) + SET ppn.lastname_ordinary = IF(pn.particle = '', pn.name, CONCAT(pn.particle, ' ', pn.name)), + ppn.particles = IF(pn.particle = '', ppn.particles, CONCAT_WS(',', ppn.particles, 'ordinary')) + WHERE pne.type = 'lastname_ordinary'; +UPDATE profile_public_names + SET particles = TRIM(BOTH ',' FROM particles); + +-- Insert other names. + UPDATE profile_public_names AS ppn +INNER JOIN profile_name AS pn ON (pn.pid = ppn.pid) +INNER JOIN profile_name_enum AS pne ON (pn.typeid = pne.id) + SET ppn.firstname_initial = pn.name + WHERE pne.type = 'firstname_ini'; + UPDATE profile_public_names AS ppn +INNER JOIN profile_name AS pn ON (pn.pid = ppn.pid) +INNER JOIN profile_name_enum AS pne ON (pn.typeid = pne.id) + SET ppn.firstname_main = pn.name + WHERE pne.type = 'firstname'; + UPDATE profile_public_names AS ppn +INNER JOIN profile_name AS pn ON (pn.pid = ppn.pid) +INNER JOIN profile_name_enum AS pne ON (pn.typeid = pne.id) + SET ppn.firstname_ordinary = pn.name + WHERE pne.type = 'firstname_other'; + UPDATE profile_public_names AS ppn +INNER JOIN profile_name AS pn ON (pn.pid = ppn.pid) +INNER JOIN profile_name_enum AS pne ON (pn.typeid = pne.id) + SET ppn.pseudonym = pn.name + WHERE pne.type = 'pseudonym'; + +-- Insert privates names. +INSERT INTO profile_private_names (pid, type, id, name) + SELECT pn.pid, 'nickname', 0, pn.name + FROM profile_name AS pn + INNER JOIN profile_name_enum AS pne ON (pn.typeid = pne.id) + WHERE pne.type = 'nickname'; +INSERT INTO profile_private_names (pid, type, id, name) + SELECT pn.pid, 'lastname', 0, pn.name + FROM profile_name AS pn + INNER JOIN profile_name_enum AS pne ON (pn.typeid = pne.id) + WHERE pne.type = 'name_other'; +INSERT INTO profile_private_names (pid, type, id, name) + SELECT pn.pid, 'firstname', 0, pn.name + FROM profile_name AS pn + INNER JOIN profile_name_enum AS pne ON (pn.typeid = pne.id) + WHERE pne.type = 'firstname_other'; + +DROP TABLE IF EXISTS profile_name; +DROP TABLE IF EXISTS profile_name_enum; + +-- vim:set syntax=mysql: diff --git a/upgrade/1.1.2/04_education.sql b/upgrade/1.1.2/04_education.sql new file mode 100644 index 0000000..9249af7 --- /dev/null +++ b/upgrade/1.1.2/04_education.sql @@ -0,0 +1,57 @@ +-- Adds secondary education. + +ALTER TABLE profile_education MODIFY COLUMN flags SET('primary', 'secondary', 'completed') NOT NULL DEFAULT ''; + + UPDATE profile_education AS pe +INNER JOIN profile_education_enum AS pen ON (pe.eduid = pen.id) + SET pe.flags = IF(pe.flags = '', 'secondary', 'secondary,completed') + WHERE pen.abbreviation = 'X' AND NOT FIND_IN_SET('primary', flags); + +-- Updates secondary education details. + +UPDATE profile_education + SET degreeid = 33 + WHERE FIND_IN_SET('secondary', flags) AND (degreeid = 4 OR degreeid = 6); + +UPDATE profile_education + SET degreeid = 5 + WHERE FIND_IN_SET('secondary', flags) AND degreeid IS NULL; + +UPDATE profile_education + SET promo_year = grad_year + WHERE FIND_IN_SET('secondary', flags); + +-- Removes duplicates. + DELETE e1 + FROM profile_education AS e1 +INNER JOIN profile_education AS e2 ON (e1.pid = e2.pid AND e1.degreeid = e2.degreeid AND e1.id < e2.id + AND FIND_IN_SET('secondary', e1.flags) AND FIND_IN_SET('secondary', e2.flags)) + WHERE e1.fieldid IS NULL AND e1.program IS NULL; + DELETE e1 + FROM profile_education AS e1 +INNER JOIN profile_education AS e2 ON (e1.pid = e2.pid AND e1.degreeid = e2.degreeid AND e1.id > e2.id + AND FIND_IN_SET('secondary', e1.flags) AND FIND_IN_SET('secondary', e2.flags)) + WHERE e1.fieldid IS NULL AND e1.program IS NULL; + +-- Updates secondary education ids. + UPDATE profile_education AS e1 +LEFT JOIN profile_education AS e2 ON (e1.pid = e2.pid AND e1.degreeid = e2.degreeid AND e1.id != e2.id AND FIND_IN_SET('secondary', e2.flags)) + SET e1.id = 101 + WHERE FIND_IN_SET('secondary', e1.flags) AND e1.degreeid = 33 AND e2.pid IS NULL; + + UPDATE profile_education AS e1 +INNER JOIN profile_education AS e2 ON (e1.pid = e2.pid AND e1.degreeid = e2.degreeid AND e1.id > e2.id) + SET e1.id = 101, e2.id = 102 + WHERE FIND_IN_SET('secondary', e1.flags) AND FIND_IN_SET('secondary', e2.flags) AND e1.degreeid = 33; + + UPDATE profile_education AS e1 +LEFT JOIN profile_education AS e2 ON (e1.pid = e2.pid AND e2.degreeid = 33 AND FIND_IN_SET('secondary', e2.flags)) + SET e1.id = 101 + WHERE FIND_IN_SET('secondary', e1.flags) AND e1.degreeid = 5 AND e2.pid IS NULL; + + UPDATE profile_education AS e1 +INNER JOIN profile_education AS e2 ON (e1.pid = e2.pid AND e2.degreeid = 33) + SET e1.id = 102 + WHERE FIND_IN_SET('secondary', e1.flags) AND FIND_IN_SET('secondary', e2.flags) AND e1.degreeid = 5; + +-- vim:set syntax=mysql: diff --git a/upgrade/1.1.2/README b/upgrade/1.1.2/README index 5cbee98..03f5fe5 100644 --- a/upgrade/1.1.2/README +++ b/upgrade/1.1.2/README @@ -1,3 +1,8 @@ +Check that the following queries return the same results before updating: +SELECT COUNT(*), COUNT(DISTINCT(pid)) FROM profile_name AS pn INNER JOIN profile_name_enum AS pne ON (pn.typeid = pne.id) WHERE pne.type = 'nickname'; +SELECT COUNT(*), COUNT(DISTINCT(pid)) FROM profile_name AS pn INNER JOIN profile_name_enum AS pne ON (pn.typeid = pne.id) WHERE pne.type = 'name_other'; +SELECT COUNT(*), COUNT(DISTINCT(pid)) FROM profile_name AS pn INNER JOIN profile_name_enum AS pne ON (pn.typeid = pne.id) WHERE pne.type = 'firstname_other'; + Once all sql/php scripts have be run, run retrieve_address_tables.sh and finally xx_retrieve_geocoding.sql. Then "./formatAddresses.php -g -t g -r e" will format the last ungeocoded addresses. diff --git a/upgrade/1.1.2/names.php b/upgrade/1.1.2/names.php new file mode 100755 index 0000000..b6d74d3 --- /dev/null +++ b/upgrade/1.1.2/names.php @@ -0,0 +1,162 @@ +#!/usr/bin/php5 +debug = 0; // Do not store backtraces. + +$options = getopt('', array('perform-updates::')); +if (isset($options['perform-updates']) && $options['perform-updates'] == 'YES') { + $perform_updates = true; +} else { + $perform_updates = false; +} + +$other_data = XDB::rawFetchOneCell("SELECT COUNT(*) + FROM profile_name AS pn + INNER JOIN profile_name_enum AS pne ON (pn.typeid = pne.id) + WHERE pne.type = 'name_other' OR pne.type = 'firstname_other'"); +if ($other_data) { + print "Update this script to take 'name_other' and 'firstname_other' into account."; + exit(); +} else { + $aliases = XDB::fetchAllAssoc('pid', "SELECT pid, name + FROM profile_private_names + WHERE type = 'nickname'"); +} + +// This contains a firstname and a lastname, both can be either main or ordinary. +function update_main($data, $string, &$update) +{ + $matches = explode(' ', $string); + $count = count($matches); + $i = 0; + + for (; $i < $count + 1; ++$i) { + $firstname = implode(' ', array_slice($matches, 0, $i + 1)); + $lastname = implode(' ', array_slice($matches, $i + 1)); + if ($firstname == $data['firstname_main'] || $firstname == $data['firstname_ordinary']) { + if ($lastname == $data['lastname_ordinary']) { + return true; + } + if ($lastname != $data['lastname_main'] && $lastname != $data['lastname_ordinary']) { + $update[] = XDB::format('lastname_ordinary = {?}', $lastname); + return true; + } + return false; + } + if ($lastname == $data['lastname_main'] || $lastname == $data['lastname_ordinary']) { + if ($firstname != $data['firstname_main'] && $firstname != $data['firstname_ordinary']) { + $update[] = XDB::format('firstname_ordinary = {?}', $firstname); + } + if ($lastname == $data['lastname_ordinary']) { + return true; + } + return false; + } + } + return false; +} + +// This is detected by a starting 'M/Mme'. But it can also include a pseudonym. +function update_marital($data, $string, &$update) +{ + preg_match('/^([^,]+)(?:, (.*))?$/', $string, $matches); + if ($matches[1] != $data['lastname_marital']) { + $update[] = XDB::format('lastname_marital = {?}', $matches[1]); + } + if (count($matches) == 3 && $matches[2] != $data['pseudonym']) { + $update[] = XDB::format('pseudonym = {?}', $matches[2]); + } +} + +function update_private($data, $string, $pid, &$aliases, $perform_updates) +{ + // We here assume there are no other last/firstnames as there do not seem to be any in the db. + $string = substr($string, 1, strlen($string) - 2); + $string = substr($string, 6, strlen($string) - 6); + + if (!isset($aliases[$pid])) { + if ($perform_updates) { + XDB::execute("INSERT INTO profile_private_names (pid, type, id, name) + VALUES ({?}, 'nickname', 0, {?})", + $pid, $string); + } else { + print $string . ' (alias for pid ' . $pid . ")\n"; + } + } elseif ($aliases[$pid] != $string) { + if ($perform_updates) { + XDB::execute('UPDATE profile_private_names + SET name = {?} + WHERE pid = {?} AND name = {?}', + $string, $pid, $aliases[$pid]); + } else { + print $string . ' (new alias for pid ' . $pid . ' replacing ' . $aliases[$pid] . ")\n"; + } + + } +} + +// This can either be a main name or a pseudonym. +function update_plain($data, $string, &$update, $has_ordinary) +{ + $string = substr($string, 1, strlen($string) - 2); + if ($string == $data['lastname_main']) { + return true; + } + + if ($string != $data['pseudonym']) { + if ($has_ordinary) { + $update[] = XDB::format('pseudonym = {?}', $string); + } else { + $update[] = XDB::format('lastname_main = {?}', $string); + } + return true; + } + return false; +} + +$res = XDB::rawIterator('SELECT pd.pid, pd.private_name, pn.lastname_main, pn.lastname_marital, pn.lastname_ordinary, + pn.firstname_main, pn.firstname_ordinary, pn.pseudonym + FROM profile_display AS pd + INNER JOIN profile_public_names AS pn ON (pd.pid = pn.pid)'); + +$pattern = '/^([^\(\)]+)(?: (\([^\(\)]+\)))?(?: (\([^\(\)]+\)))?(?: (\([^\(\)]+\)))?$/'; +while ($data = $res->next()) { + preg_match($pattern, $data['private_name'], $matches); + $has_ordinary = false; + + $count = count($matches); + $update = array(); + $has_ordinary = update_main($data, $matches[1], $update); + for ($i = 2; $i < $count; ++$i) { + if (preg_match('/^\((?:M|Mme) (.+)\)$/', $matches[$i], $pieces)) { + update_marital($data, $pieces[1], $update); + } elseif (preg_match('/^\((?:alias|autres prénoms :|autres noms :) .+\)$/', $matches[$i], $pieces)) { + update_private($data, $matches[$i], $data['pid'], $aliases, $perform_updates); + } else { + $has_ordinary = update_plain($data, $matches[$i], $update, $has_ordinary); + } + } + + if (count($update)) { + $set = implode(', ', $update); + if ($perform_updates) { + XDB::rawExecute('UPDATE profile_public_names + SET ' . $set . ' + WHERE pid = ' . $data['pid']); + } else { + print $set . ' (for pid ' . $data['pid'] . ")\n"; + } + } +} + +if ($perform_updates) { + print "\nUpdates done.\n"; +} else { + print "\nIf this seems correct, relaunch this script with option --perform-updates=YES.\n"; +} + +/* vim:set et sw=4 sts=4 ts=4: */ +?>