From 0e1dfbadefc72cc5aa6614351ee395d205d9eaea Mon Sep 17 00:00:00 2001 From: =?utf8?q?St=C3=A9phane=20Jacob?= Date: Tue, 24 May 2011 15:45:51 +0200 Subject: [PATCH] Simplifies profile names handling. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Stéphane Jacob --- bin/export_sql.bash | 1 - classes/direnum.php | 26 -- classes/profile.php | 84 +++--- htdocs/javascript/profile.js | 58 ++--- include/name.func.inc.php | 376 +++++++++------------------ include/validations/names.inc.php | 72 ++--- include/webservices/manageurs.server.inc.php | 12 +- modules/admin.php | 14 +- modules/profile.php | 37 +-- modules/profile/general.inc.php | 285 ++++++++------------ modules/register.php | 19 +- templates/admin/index.tpl | 2 - templates/include/form.valid.names.tpl | 12 +- templates/profile/general.private_name.tpl | 44 ++++ templates/profile/general.public_names.tpl | 57 ++++ templates/profile/general.searchname.tpl | 65 ----- templates/profile/general.tpl | 10 +- upgrade/1.1.2/03_names.sql | 106 ++++++++ upgrade/1.1.2/README | 4 + 19 files changed, 561 insertions(+), 723 deletions(-) create mode 100644 templates/profile/general.private_name.tpl create mode 100644 templates/profile/general.public_names.tpl delete mode 100644 templates/profile/general.searchname.tpl create mode 100644 upgrade/1.1.2/03_names.sql create mode 100644 upgrade/1.1.2/README diff --git a/bin/export_sql.bash b/bin/export_sql.bash index 2ecc94f..ac2d9b7 100755 --- a/bin/export_sql.bash +++ b/bin/export_sql.bash @@ -27,7 +27,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 1962d28..16cdb25 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'; @@ -433,29 +430,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 177155a..988c1c6 100644 --- a/classes/profile.php +++ b/classes/profile.php @@ -427,7 +427,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() @@ -947,10 +947,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, @@ -964,16 +963,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) @@ -1115,47 +1106,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); @@ -1170,7 +1160,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/htdocs/javascript/profile.js b/htdocs/javascript/profile.js index d4899ec..2057e69 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/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/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 fa56a3c..60d18fa 100644 --- a/include/webservices/manageurs.server.inc.php +++ b/include/webservices/manageurs.server.inc.php @@ -174,10 +174,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 @@ -185,12 +182,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..2318b3f 100644 --- a/modules/admin.php +++ b/modules/admin.php @@ -816,8 +816,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 +875,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 ({?}, {?}, {?}, {?}, {?}, {?}, {?}, {?})', diff --git a/modules/profile.php b/modules/profile.php index 4ee5fb9..0ad1a74 100644 --- a/modules/profile.php +++ b/modules/profile.php @@ -47,7 +47,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), @@ -68,7 +67,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'), ); } @@ -115,19 +113,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 @@ -490,14 +475,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) @@ -710,17 +692,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..08b09ca 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); } } @@ -795,13 +728,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/templates/admin/index.tpl b/templates/admin/index.tpl index fbb6ad3..42d066d 100644 --- a/templates/admin/index.tpl +++ b/templates/admin/index.tpl @@ -162,8 +162,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/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/upgrade/1.1.2/03_names.sql b/upgrade/1.1.2/03_names.sql new file mode 100644 index 0000000..9c04c51 --- /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/README b/upgrade/1.1.2/README new file mode 100644 index 0000000..818e00d --- /dev/null +++ b/upgrade/1.1.2/README @@ -0,0 +1,4 @@ +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'; -- 2.1.4