ff3e33d4418437de52ac186e4ea45078cf573017
2 /***************************************************************************
3 * Copyright (C) 2003-2007 Polytechnique.org *
4 * http://opensource.polytechnique.org/ *
6 * This program is free software; you can redistribute it and/or modify *
7 * it under the terms of the GNU General Public License as published by *
8 * the Free Software Foundation; either version 2 of the License, or *
9 * (at your option) any later version. *
11 * This program is distributed in the hope that it will be useful, *
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
14 * GNU General Public License for more details. *
16 * You should have received a copy of the GNU General Public License *
17 * along with this program; if not, write to the Free Software *
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *
20 ***************************************************************************/
23 * @brief Module to merge data from AX database
25 * Module to import data from another database of alumni that had
26 * different schemas. The organization that used this db is called AX
27 * hence the name of this module.
29 * Datas are stored in an external server and you need a private key
30 * to connect to their server.
32 class FusionAxModule
extends PLModule
{
34 /// path ok private key file to connect to AX server
37 function __construct()
39 $this->ax_xorg_rsa_key
=
40 dirname(__FILE__
).'/../configs/ax_xorg_rsa.pem';
46 'fusionax' => $this->make_hook('index', AUTH_MDP
, 'admin'),
47 'fusionax/import' => $this->make_hook('import', AUTH_MDP
,'admin'),
48 'fusionax/ids' => $this->make_hook('ids', AUTH_MDP
, 'admin'),
49 'fusionax/misc' => $this->make_hook('misc', AUTH_MDP
, 'admin'),
54 function handler_index(&$page)
57 $page->changeTpl('fusionax/index.tpl');
58 $page->assign('xorg_title','Polytechnique.org - Fusion des annuaires');
59 if (isset($globals->fusionax
) &&
60 isset($globals->fusionax
->LastUpdate
)) {
63 date("d-m-Y",$globals->fusionax
->LastUpdate
));
67 /** Import de l'annuaire de l'AX depuis l'export situé sur leur serveur */
68 function handler_import(&$page, $action = 'index', $fileSQL = '')
70 if ($action == 'index') {
71 $page->changeTpl('fusionax/import.tpl');
72 $page->addJsLink('jquery.js');
74 if (isset($globals->fusionax
) &&
75 isset($globals->fusionax
->LastUpdate
)) {
78 "le ".date("d/m/Y à H:i",$globals->fusionax
->LastUpdate
));
80 if (!file_exists($this->ax_xorg_rsa_key
)) {
83 $this->ax_xorg_rsa_key
);
88 // toutes les actions sont faites en ajax en utilisant jquery
89 header("Content-type: text/javascript; charset=utf-8");
94 // création d'un fichier temporaire si nécessaire
95 if (Env
::has('tmpdir')) {
96 $tmpdir = Env
::v('tmpdir');
98 $tmpdir = tempnam('/tmp', 'fusionax');
101 chmod($tmpdir, 0700);
102 // copie la clef d'authentification (paire de clef RSA dont la
103 // partie publique est sur polytechniciens.com)
105 $this->ax_xorg_rsa_key
,
106 $tmpdir.'/ax_xorg_rsa'))
107 $report[] = 'Impossible de copier la clef pour se logger '.
109 chmod($tmpdir.'/ax_xorg_rsa', 0600);
112 $modulepath = realpath(dirname(__FILE__
).'/fusionax/').'/';
116 if ($action == 'launch') {
117 // lancement : connexion en ssh et récupération du fichier depuis
118 // polyechniciens.com, décompression de l'archive et séparation en
119 // fichiers par tables
120 exec($modulepath.'import-ax.sh', $report);
121 $report[] = utf8_decode('Récupération du fichier terminé.');
122 $report[] = 'Import dans la base en cours...';
123 $next = 'integrateSQL';
124 } else if ($action == 'integrateSQL') {
125 // intégration des données dans la base MySQL
126 // liste des fichiers sql à exécuter
133 if ($fileSQL != '') {
134 // récupère le contenu du fichier sql
135 $queries = explode(';',file_get_contents($modulepath.$fileSQL));
136 foreach ($queries as $q) if (trim($q)) {
137 // coupe le fichier en requêtes individuelles
138 if (substr($q,0,2) == '--') {
139 // affiche les commentaires dans le report
140 $lines = explode("\n",$q);
142 $report[] = addslashes(utf8_decode($l));
144 // exécute la requête
147 // trouve le prochain fichier à exécuter
148 $trans = array_flip($filesSQL);
149 $nextfile = $trans[$fileSQL] +
1;
153 if (!isset($filesSQL[$nextfile])) {
154 // tous les fichiers ont été exécutés, on passe à l'étape
158 // on passe au fichier suivant
159 $next = 'integrateSQL/'.$filesSQL[$nextfile];
161 } else if ($action == 'clean') {
162 // nettoyage du fichier temporaire
164 exec("rm -rf $tmpdir", $report);
165 $report[] = 'Fin de l\'import';
167 // met à jour la date de dernier import
168 $globals->change_dynamic_config(
169 array('LastUpdate' => time()),
174 foreach($report as $t)
175 // affiche les lignes de report
176 echo "$('#fusionax_import').append('".utf8_encode($t)."<br/>');\n";
178 // lance le prochain script s'il y en a un
179 echo "$.getScript('fusionax/import/".$next."?tmpdir=".
180 urlencode($tmpdir)."');";
182 // exit pour ne pas afficher la page template par défaut
186 /** Lier les identifiants d'un ancien dans les deux annuaires
187 * @param user_id identifiant dans l'annuaire X.org
188 * @param matricule_ax identifiant dans l'annuaire de l'AX
189 * @return 0 si la liaison a échoué, 1 sinon
191 private static function link_by_ids($user_id, $matricule_ax)
194 UPDATE fusionax_import AS i
195 INNER JOIN fusionax_xorg_anciens AS u
197 u.matricule_ax = i.id_ancien,
198 i.user_id = u.user_id,
199 i.date_match_id = NOW()
201 i.id_ancien = {?} AND u.user_id = {?} AND (
202 u.matricule_ax != {?} OR u.matricule_ax IS NULL OR
203 i.user_id != {?} OR i.user_id IS NULL)",
211 return XDB
::affectedRows() / 2;
214 /** Recherche automatique d'anciens à lier entre les deux annuaires
215 * @param limit nombre d'anciens à trouver au max
216 * @param sure si true, ne trouve que des anciens qui sont quasi sûrs
217 * @return un XOrgDBIterator sur les entrées avec display_name, promo,
218 * user_id, id_ancien et display_name_ax
220 private static function find_easy_to_link($limit = 10, $sure = false
)
222 $easy_to_link = XDB
::iterator("
224 xorg.display_name, xorg.promo, xorg.user_id, ax.id_ancien,
225 CONCAT(ax.prenom,' ',ax.nom_complet,' (X ',ax.promotion_etude,')')
227 COUNT(*) AS nbMatches
228 FROM fusionax_anciens AS ax
229 INNER JOIN fusionax_import AS i ON (
230 i.id_ancien = ax.id_ancien AND i.user_id IS NULL)
231 LEFT JOIN fusionax_xorg_anciens AS xorg ON (
232 xorg.matricule_ax IS NULL AND
233 ax.Nom_complet = xorg.nom AND
234 ax.prenom = xorg.prenom AND
235 xorg.promo = ax.promotion_etude)
236 GROUP BY xorg.user_id
238 xorg.user_id IS NOT NULL AND
240 ".($limit?
('LIMIT '.$limit):''));
241 if ($easy_to_link->total() > 0 ||
$sure) {
242 return $easy_to_link;
244 return XDB
::iterator("
246 xorg.display_name, xorg.promo, xorg.user_id, ax.id_ancien,
247 CONCAT(ax.prenom,' ',ax.nom_complet,' (X ',ax.promotion_etude,')')
249 COUNT(*) AS nbMatches
250 FROM fusionax_anciens AS ax
251 INNER JOIN fusionax_import AS i ON (
252 i.id_ancien = ax.id_ancien AND i.user_id IS NULL)
253 LEFT JOIN fusionax_xorg_anciens AS xorg ON (
254 xorg.matricule_ax IS NULL AND
255 (ax.Nom_complet = xorg.nom
256 OR ax.Nom_complet LIKE CONCAT(xorg.nom,' %')
257 OR ax.Nom_complet LIKE CONCAT(xorg.nom,'-%')
258 OR ax.Nom_usuel = xorg.nom
259 OR xorg.nom LIKE CONCAT('% ',ax.Nom_complet)) AND
260 xorg.promo < ax.promotion_etude + 2 AND
261 xorg.promo > ax.promotion_etude - 2)
262 GROUP BY xorg.user_id
264 xorg.user_id IS NOT NULL AND
266 ".($limit?
('LIMIT '.$limit):''));
269 /** Module de mise en correspondance les ids */
270 function handler_ids(
274 $matricule_ax = null
)
277 $page->addJsLink('jquery.js');
281 'Polytechnique.org - Fusion - Mise en correspondance simple');
282 if ($part == 'missingInAX')
284 // locate all persons from this database that are not in AX's
285 $page->changeTpl('fusionax/idsMissingInAx.tpl');
286 $missingInAX = XDB
::iterator("SELECT
287 u.promo, u.user_id, u.display_name
288 FROM fusionax_xorg_anciens AS u
289 WHERE u.matricule_ax IS NULL
291 $page->assign('missingInAX', $missingInAX);
294 if ($part == 'missingInXorg')
296 // locate all persons from AX's database that are not here
297 $page->changeTpl('fusionax/idsMissingInXorg.tpl');
298 $missingInXorg = XDB
::iterator("SELECT
299 a.promotion_etude AS promo,
300 CONCAT(a.prenom, ' ',a.Nom_usuel) AS display_name,
303 INNER JOIN fusionax_anciens AS a USING (id_ancien)
304 WHERE fusionax_import.user_id IS NULL
306 $page->assign('missingInXorg', $missingInXorg);
311 FusionAxModule
::link_by_ids($user_id,$matricule_ax);
314 if ($part == 'linknext')
316 $linksToDo = FusionAxModule
::find_easy_to_link(10);
317 while ($l = $linksToDo->next())
319 FusionAxModule
::link_by_ids($l['user_id'],$l['id_ancien']);
321 pl_redirect('fusionax/ids#autolink');
323 if ($part == 'linkall')
325 $linksToDo = FusionAxModule
::find_easy_to_link(0);
326 while ($l = $linksToDo->next())
328 FusionAxModule
::link_by_ids($l['user_id'],$l['id_ancien']);
332 $page->changeTpl('fusionax/ids.tpl');
333 $missingInAX = XDB
::query(
335 FROM fusionax_xorg_anciens AS u
336 WHERE u.matricule_ax IS NULL');
339 $page->assign('nbMissingInAX', $missingInAX->fetchOneCell());
341 $missingInXorg = XDB
::query(
343 FROM fusionax_import AS i
344 WHERE i.user_id IS NULL');
349 $missingInXorg->fetchOneCell());
351 $easyToLink = FusionAxModule
::find_easy_to_link(10);
352 if ($easyToLink->total() > 0)
354 $page->assign('easyToLink', $easyToLink);
359 function handler_misc(&$page)
361 $page->changeTpl('fusionax/misc.tpl');
363 $deceasedErrorsSql = XDB
::query(
364 'SELECT COUNT(*) FROM fusionax_deceased');
365 $page->assign('deceasedErrors',$deceasedErrorsSql->fetchOneCell());
366 $page->assign('deceasedMissingInXorg',XDB
::iterator(
368 d.user_id,d.id_ancien,d.nom,d.prenom,d.promo,d.deces_ax,
369 CONCAT(d.prenom, " ", d.nom) AS display_name
370 FROM fusionax_deceased AS d
371 WHERE d.deces_xorg = "0000-00-00"
373 $page->assign('deceasedMissingInAX',XDB
::iterator(
375 d.user_id,d.id_ancien,d.nom,d.prenom,d.promo,d.deces_xorg,
376 CONCAT(d.prenom, " ", d.nom) AS display_name
377 FROM fusionax_deceased AD d
378 WHERE d.deces_ax = "0000-00-00"
380 $page->assign('deceasedDifferent',XDB
::iterator(
382 d.user_id,d.id_ancien,d.nom,d.prenom,d.promo,
383 d.deces_ax,d.deces_xorg,
384 CONCAT(d.prenom, " ", d.nom) AS display_name
385 FROM fusionax_deceased AS d
386 WHERE d.deces_xorg != "0000-00-00" AND d.deces_ax != "0000-00-00"
391 // vim:set et sw=4 sts=4 sws=4 foldmethod=marker enc=utf-8:?>