function handler_add_accounts($page, $action = null, $promo = null) { require_once 'name.func.inc.php'; $page->changeTpl('admin/add_accounts.tpl'); if (Env::has('add_type') && Env::has('people')) { static $titles = array('male' => 'M', 'female' => 'MLLE'); $lines = explode("\n", Env::t('people')); $separator = Env::t('separator'); $promotion = Env::i('promotion'); if (Env::t('add_type') == 'promo') { $eduSchools = DirEnum::getOptions(DirEnum::EDUSCHOOLS); $eduSchools = array_flip($eduSchools); $eduDegrees = DirEnum::getOptions(DirEnum::EDUDEGREES); $eduDegrees = array_flip($eduDegrees); switch (Env::t('edu_type')) { case 'X': $degreeid = $eduDegrees[Profile::DEGREE_X]; $entry_year = $promotion; $grad_year = $promotion + 3; $promo = 'X' . $promotion; $hrpromo = $promotion; $type = 'x'; break; case 'M': $degreeid = $eduDegrees[Profile::DEGREE_M]; $grad_year = $promotion; $entry_year = $promotion - 2; $promo = 'M' . $promotion; $hrpromo = $promo; $type = 'master'; break; case 'D': $degreeid = $eduDegrees[Profile::DEGREE_D]; $grad_year = $promotion; $entry_year = $promotion - 3; $promo = 'D (en cours)'; $hrpromo = 'D' . $promotion; $type = 'phd'; break; default: $page->killError("La formation n'est pas reconnue : " . Env::t('edu_type') . '.'); } $best_domain = XDB::fetchOneCell('SELECT id FROM email_virtual_domains WHERE name = {?}', User::$sub_mail_domains[$type] . Platal::globals()->mail->domain); XDB::startTransaction(); foreach ($lines as $line) { if ($infos = self::formatNewUser($page, $line, $separator, $hrpromo, 6)) { $sex = self::formatSex($page, $infos[3], $line); $lastname = capitalize_name($infos[0]); $firstname = capitalize_name($infos[1]); if (!is_null($sex)) { $fullName = build_full_name($firstname, $lastname); $directoryName = build_directory_name($firstname, $lastname); $sortName = build_sort_name($firstname, $lastname); $birthDate = self::formatBirthDate($infos[2]); if ($type == 'x') { if ($promotion < 1996 && preg_match('/^[0-9]{8}$/', $infos[4])) { /* Allow using Xorg ID for old promotions, to allow fixing typos in names */ $xorgId = $infos[4]; $year = intval(substr($xorgId, 0, 4)); if ($year != $promotion) { $page->trigError("La ligne {$line} n'a pas été ajoutée car le matricule Xorg n'a pas la date correspondant à la promotion."); continue; } } else { $xorgId = Profile::getXorgId($infos[4]); } } elseif (isset($infos[4])) { $xorgId = trim($infos[4]); } else { $xorgId = 0; } if (is_null($xorgId)) { $page->trigError("La ligne {$line} n'a pas été ajoutée car le matricule École est mal renseigné."); continue; } XDB::execute('INSERT INTO profiles (hrpid, xorg_id, ax_id, birthdate_ref, sex, title) VALUES ({?}, {?}, {?}, {?}, {?}, {?})', $infos['hrid'], $xorgId, isset($infos[5]) ? $infos[5] : null, $birthDate, $sex, $titles[$sex]); $pid = XDB::insertId(); XDB::execute('INSERT INTO profile_public_names (pid, lastname_initial, lastname_main, firstname_initial, firstname_main) VALUES ({?}, {?}, {?}, {?}, {?})', $pid, $lastname, $lastname, $firstname, $firstname); XDB::execute('INSERT INTO profile_display (pid, yourself, public_name, private_name, directory_name, short_name, sort_name, promo) VALUES ({?}, {?}, {?}, {?}, {?}, {?}, {?}, {?})', $pid, $firstname, $fullName, $fullName, $directoryName, $fullName, $sortName, $promo); XDB::execute('INSERT INTO profile_education (id, pid, eduid, degreeid, entry_year, grad_year, promo_year, flags) VALUES (100, {?}, {?}, {?}, {?}, {?}, {?}, \'primary\')', $pid, $eduSchools[Profile::EDU_X], $degreeid, $entry_year, $grad_year, $promotion); XDB::execute('INSERT INTO accounts (hruid, type, is_admin, state, full_name, directory_name, sort_name, display_name, lastname, firstname, sex, best_domain) VALUES ({?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?})', $infos['hrid'], $type, 0, 'pending', $fullName, $directoryName, $sortName, $firstname, $lastname, $firstname, $sex, $best_domain); $uid = XDB::insertId(); XDB::execute('INSERT INTO account_profiles (uid, pid, perms) VALUES ({?}, {?}, {?})', $uid, $pid, 'owner'); Profile::rebuildSearchTokens($pid, false); } } } XDB::commit(); } else { if (Env::t('add_type') == 'account') { $type = Env::t('type'); $newAccounts = array(); foreach ($lines as $line) { if ($infos = self::formatNewUser($page, $line, $separator, $type, 4)) { $sex = self::formatSex($page, $infos[3], $line); if (!is_null($sex)) { $lastname = capitalize_name($infos[0]); $firstname = capitalize_name($infos[1]); $fullName = build_full_name($firstname, $lastname); $directoryName = build_directory_name($firstname, $lastname); $sortName = build_sort_name($firstname, $lastname); XDB::execute('INSERT INTO accounts (hruid, type, is_admin, state, email, full_name, directory_name, sort_name, display_name, lastname, firstname, sex) VALUES ({?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?})', $infos['hrid'], $type, 0, 'pending', $infos[2], $fullName, $directoryName, $sortName, $firstname, $lastname, $firstname, $sex); $newAccounts[$infos['hrid']] = $fullName; } } } if (!empty($newAccounts)) { $page->assign('newAccounts', $newAccounts); } } else { if (Env::t('add_type') == 'ax_id') { $type = 'x'; foreach ($lines as $line) { $infos = explode($separator, $line); if (sizeof($infos) > 3 || sizeof($infos) < 2) { $page->trigError("La ligne {$line} n'a pas été ajoutée : mauvais nombre de champs."); continue; } $infos = array_map('trim', $infos); if (sizeof($infos) == 3) { // Get human readable ID with first name and last name $hrid = User::makeHrid($infos[1], $infos[0], $promotion); $user = User::getSilent($hrid); $axid = $infos[2]; } else { // The first column is the hrid, possibly without the promotion $user = User::getSilent($infos[0] . '.' . $promotion); if (is_null($user)) { $user = User::getSilent($infos[0]); } $axid = $infos[1]; } if (!$axid) { $page->trigError("La ligne {$line} n'a pas été ajoutée : matricule AX vide."); continue; } if (is_null($user)) { $page->trigError("La ligne {$line} n'a pas été ajoutée : aucun compte trouvé."); continue; } $profile = $user->profile(); if ($profile->ax_id) { $page->trigError("Le profil " . $profile->hrpid . " a déjà l'ID AX " . $profile->ax_id); continue; } XDB::execute('UPDATE profiles SET ax_id = {?} WHERE pid = {?}', $axid, $profile->id()); } } } } $errors = $page->nb_errs(); if ($errors == 0) { $page->trigSuccess("L'opération a été effectuée avec succès."); } else { $page->trigSuccess('L\'opération a été effectuée avec succès, sauf pour ' . ($errors == 1 ? 'l\'erreur signalée' : "les {$errors} erreurs signalées") . ' ci-dessus.'); } } else { if (Env::has('add_type')) { $res = XDB::query('SELECT type FROM account_types'); $page->assign('account_types', $res->fetchColumn()); $page->assign('add_type', Env::s('add_type')); } } }
/** Import de l'annuaire de l'AX depuis l'export situé dans le home de jacou */ function handler_import($page, $action = 'index', $file = '') { global $globals; if ($action == 'index') { $page->changeTpl('fusionax/import.tpl'); return; } // toutes les actions sont faites en ajax en utilisant jquery header('Content-type: text/javascript; charset=utf-8'); // log des actions $report = array(); $modulepath = realpath(dirname(__FILE__) . '/fusionax/') . '/'; $spoolpath = realpath(dirname(__FILE__) . '/../spool/fusionax/') . '/'; if ($action == 'launch') { if ($file == '') { $report[] = 'Nom de fichier non renseigné.'; } elseif (!file_exists(dirname(__FILE__) . '/../spool/fusionax/' . $file)) { $report[] = 'Le fichier ne se situe pas au bon endroit.'; } else { // séparation de l'archive en fichiers par tables $file = $spoolpath . $file; // Split export into specialised files exec('grep "^AD" ' . $file . ' > ' . $spoolpath . 'Adresses.txt'); exec('grep "^AN" ' . $file . ' > ' . $spoolpath . 'Anciens.txt'); exec('grep "^FO.[0-9]\\{4\\}[MD][0-9]\\{3\\}.Etudiant" ' . $file . ' > ' . $spoolpath . 'Formations_MD.txt'); exec('grep "^FO.[0-9]\\{4\\}[MD][0-9]\\{3\\}.Doct. de" ' . $file . ' >> ' . $spoolpath . 'Formations_MD.txt'); exec('grep "^FO" ' . $file . ' > ' . $spoolpath . 'Formations.txt'); exec('grep "^AC" ' . $file . ' > ' . $spoolpath . 'Activites.txt'); exec('grep "^EN" ' . $file . ' > ' . $spoolpath . 'Entreprises.txt'); exec($modulepath . 'formation.pl'); exec('mv -f ' . $spoolpath . 'Formations_out.txt ' . $spoolpath . 'Formations.txt'); exec('mv -f ' . $spoolpath . 'Formations_MD_out.txt ' . $spoolpath . 'Formations_MD.txt'); $report[] = 'Fichier parsé.'; $report[] = 'Import dans la base en cours...'; XDB::execute("UPDATE profiles\n SET ax_id = NULL\n WHERE ax_id = ''"); $next = 'integrateSQL'; } } elseif ($action == 'integrateSQL') { // intégration des données dans la base MySQL // liste des fichiers sql à exécuter $filesSQL = array(0 => 'Activites.sql', 1 => 'Adresses.sql', 2 => 'Anciens.sql', 3 => 'Formations.sql', 4 => 'Entreprises.sql', 5 => 'Formations_MD.sql'); if ($file != '') { // récupère le contenu du fichier sql $queries = explode(';', file_get_contents($modulepath . $filesSQL[$file])); $db = mysqli_init(); $db->options(MYSQLI_OPT_LOCAL_INFILE, true); $db->real_connect($globals->dbhost, $globals->dbuser, $globals->dbpwd, $globals->dbdb); $db->autocommit(true); $db->set_charset($globals->dbcharset); foreach ($queries as $q) { if (trim($q)) { // coupe le fichier en requêtes individuelles if (substr($q, 0, 2) == '--') { // affiche les commentaires dans le report $lines = explode("\n", $q); $l = $lines[0]; $report[] = addslashes($l); } // exécute la requête $res = $db->query(str_replace('{?}', $spoolpath, $q)); if ($res === false) { throw new XDBException($q, $db->error); } } } $db->close(); // trouve le prochain fichier à exécuter $nextfile = $file + 1; } else { $nextfile = 0; } if ($nextfile > 5) { // tous les fichiers ont été exécutés, on passe à l'étape suivante $next = 'adds1920'; } else { // on passe au fichier suivant $next = 'integrateSQL/' . $nextfile; } } elseif ($action == 'adds1920') { // Adds promotion 1920 from AX db. $report[] = 'Ajout de la promotion 1920'; $res = XDB::iterator('SELECT prenom, Nom_complet, ax_id FROM fusionax_anciens WHERE promotion_etude = 1920;'); $eduSchools = DirEnum::getOptions(DirEnum::EDUSCHOOLS); $eduSchools = array_flip($eduSchools); $eduDegrees = DirEnum::getOptions(DirEnum::EDUDEGREES); $eduDegrees = array_flip($eduDegrees); $degreeid = $eduDegrees[Profile::DEGREE_X]; $entry_year = 1920; $grad_year = 1923; $promo = 'X1920'; $hrpromo = '1920'; $sex = 'male'; $xorgId = 19200000; $type = 'x'; while ($new = $res->next()) { $firstname = $new['prenom']; $lastname = $new['Nom_complet']; $ax_id = $new['ax_id']; $hrid = User::makeHrid($firstname, $lastname, $hrpromo); $res1 = XDB::query('SELECT COUNT(*) FROM accounts WHERE hruid = {?}', $hrid); $res2 = XDB::query('SELECT COUNT(*) FROM profiles WHERE hrpid = {?}', $hrid); if (is_null($hrid) || $res1->fetchOneCell() > 0 || $res2->fetchOneCell() > 0) { $report[] = $ax_id . ' non ajouté'; } $fullName = $firstname . ' ' . $lastname; $directoryName = $lastname . ' ' . $firstname; ++$xorgId; XDB::execute('INSERT INTO profiles (hrpid, xorg_id, ax_id, sex) VALUES ({?}, {?}, {?}, {?})', $hrid, $xorgId, $ax_id, $sex); $pid = XDB::insertId(); XDB::execute('INSERT INTO profile_public_names (pid, lastname_initial, firstname_initial, lastname_main, firstname_main) VALUES ({?}, {?}, {?}, {?}, {?})', $pid, $lastname, $firstname, $lastname, $firstname); XDB::execute('INSERT INTO profile_display (pid, yourself, public_name, private_name, directory_name, short_name, sort_name, promo) VALUES ({?}, {?}, {?}, {?}, {?}, {?}, {?}, {?})', $pid, $firstname, $fullName, $fullName, $directoryName, $fullName, $directoryName, $promo); XDB::execute('INSERT INTO profile_education (pid, eduid, degreeid, entry_year, grad_year, flags) VALUES ({?}, {?}, {?}, {?}, {?}, {?})', $pid, $eduSchools[Profile::EDU_X], $degreeid, $entry_year, $grad_year, 'primary'); XDB::execute('INSERT INTO accounts (hruid, type, is_admin, state, full_name, directory_name, display_name, lastname, firstname, sex) VALUES ({?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, {?})', $hrid, $type, 0, 'pending', $fullName, $directoryName, $firstname, $lastname, $firstname, $sex); $uid = XDB::insertId(); XDB::execute('INSERT INTO account_profiles (uid, pid, perms) VALUES ({?}, {?}, {?})', $uid, $pid, 'owner'); } $report[] = 'Promo 1920 ajoutée.'; $next = 'view'; } elseif ($action == 'view') { XDB::execute('CREATE OR REPLACE ALGORITHM=MERGE VIEW fusionax_xorg_anciens AS SELECT p.pid, p.ax_id, pd.promo, pd.private_name, pd.public_name, pd.sort_name, pd.short_name, pd.directory_name FROM profiles AS p INNER JOIN profile_display AS pd ON (pd.pid = p.pid)'); $next = 'clean'; } elseif ($action == 'clean') { // nettoyage du fichier temporaire //exec('rm -Rf ' . $spoolpath); $report[] = 'Import finit.'; } foreach ($report as $t) { // affiche les lignes de report echo "\$('#fusionax').append('" . $t . "<br/>');\n"; } if (isset($next)) { // lance le prochain script s'il y en a un echo "\$.getScript('fusionax/import/" . $next . "');"; } // exit pour ne pas afficher la page template par défaut exit; }
function handler_admin_member_new($page, $email = null) { global $globals; $page->changeTpl('xnetgrp/membres-add.tpl'); $page->addJsLink('xnet_members.js'); if (is_null($email)) { return; } S::assert_xsrf_token(); $suggest_account_activation = false; // FS#703 : $_GET is urldecoded twice, hence // + (the data) => %2B (in the url) => + (first decoding) => ' ' (second decoding) // Since there can be no spaces in emails, we can fix this with : $email = str_replace(' ', '+', $email); $is_valid_email = isvalid_email($email); // X not registered to main site. if (Env::v('x') && Env::i('userid') && $is_valid_email) { $user = User::getSilentWithUID(Env::i('userid')); if (!$user) { $page->trigError('Utilisateur invalide.'); return; } // User has an account but is not yet registered. if ($user->state == 'pending') { // Add email in account table. XDB::query('UPDATE accounts SET email = {?} WHERE uid = {?} AND email IS NULL', $email, $user->id()); // Add email for marketing if required. if (Env::v('marketing')) { $market = Marketing::get($user->uid, $email); if (!$market) { $market = new Marketing($user->uid, $email, 'group', $globals->asso('nom'), Env::v('marketing_from'), S::v('uid')); $market->add(); } } } elseif (Env::v('broken')) { // Add email for broken if required. $valid = new BrokenReq(S::user(), $user, $email, 'Groupe : ' . $globals->asso('nom')); $valid->submit(); } } else { $user = User::getSilent($email); // Wrong email and no user: failure. if (is_null($user) && (!$is_valid_email || !User::isForeignEmailAddress($email))) { $page->trigError('« <strong>' . $email . '</strong> » n\'est pas une adresse email valide.'); return; } // Deals with xnet accounts. if (is_null($user) || $user->type == 'xnet') { // User is of type xnet. There are 3 possible cases: // * the email is not known yet: we create a new account and // propose to send an email to the user so he can activate // his account, // * the email is known but the user was not contacted in order to // activate yet: we propose to send an email to the user so he // can activate his account, // * the email is known and the user was already contacted or has // an active account: nothing to be done. list($mbox, $domain) = explode('@', strtolower($email)); $hruid = User::makeHrid($mbox, $domain, 'ext'); // User might already have an account (in another group for example). $user = User::getSilent($hruid); // If the user has no account yet, creates new account: build names from email address. if (empty($user)) { require_once 'name.func.inc.php'; $parts = explode('.', $mbox); if (count($parts) == 1) { $lastname = $display_name = capitalize_name($mbox); $firstname = ''; } else { $display_name = $firstname = capitalize_name($parts[0]); $lastname = capitalize_name(implode(' ', array_slice($parts, 1))); } $full_name = build_full_name($firstname, $lastname); $directory_name = build_directory_name($firstname, $lastname); $sort_name = build_sort_name($firstname, $lastname); XDB::execute('INSERT INTO accounts (hruid, display_name, full_name, directory_name, sort_name, firstname, lastname, email, type, state) VALUES ({?}, {?}, {?}, {?}, {?}, {?}, {?}, {?}, \'xnet\', \'disabled\')', $hruid, $display_name, $full_name, $directory_name, $sort_name, $firstname, $lastname, $email); $user = User::getSilent($hruid); } $suggest_account_activation = $this->suggest($user); } } if ($user) { // First check if the user used to be in this group. XDB::rawExecute('DELETE FROM group_former_members WHERE remember AND DATE_SUB(NOW(), INTERVAL 1 YEAR) > unsubsciption_date'); $former_member = XDB::fetchOneCell('SELECT remember FROM group_former_members WHERE uid = {?} AND asso_id = {?}', $user->id(), $globals->asso('id')); if ($former_member === 1) { $page->trigError($user->fullName() . ' est un ancien membre du groupe qui ne souhaite pas y revenir. S\'il souhaite revenir dans le groupe, il faut qu\'il en fasse la demande sur la page d\'accueil du groupe.'); return; } elseif (!is_null($former_member) && Post::i('force_continue') == 0) { $page->trigWarning($user->fullName() . ' est un ancien membre du groupe qui s\'est récemment désinscrit. Malgré cela, si tu penses qu\'il souhaite revenir, cliquer sur « Ajouter » l\'ajoutera bien au groupe cette fois.'); $page->assign('force_continue', 1); return; } Group::subscribe($globals->asso('id'), $user->id()); $this->removeSubscriptionRequest($user->id()); if ($user->isActive() && $user->bestEmail()) { $mailer = new PlMailer('xnetgrp/forced-subscription.mail.tpl'); $mailer->addTo($user->bestEmail()); $mailer->assign('group', $globals->asso('nom')); $mailer->assign('anim', S::user()->fullname()); $mailer->assign('diminutif', $globals->asso('diminutif')); $mailer->send(); } // Check if the group has more than 1000 members, if so, disable the "send mail" function. $full_count = XDB::fetchOneCell('SELECT COUNT(*) FROM group_members WHERE asso_id = {?}', $globals->asso('id')); if ($full_count > 999) { XDB::execute("UPDATE groups\n SET disable_mails = 1\n WHERE id = {?}", $globals->asso('id')); } if ($suggest_account_activation) { pl_redirect('member/suggest/' . $user->login() . '/' . $email . '/' . $globals->asso('nom')); } else { pl_redirect('member/' . $user->login()); } } }