From 57b5cea4f53d21d281022fde96a666af06592893 Mon Sep 17 00:00:00 2001
From: "Committo,Ergo:sum" <esj@rezo.net>
Date: Mon, 4 Dec 2006 06:32:24 +0000
Subject: [PATCH] =?UTF-8?q?T=C3=A2che=20#685,=20suite=20[7952],=20Deux=20a?=
 =?UTF-8?q?vanc=C3=A9es=20(perte=20de=20la=208002=20d'origine=20plus=20une?=
 =?UTF-8?q?=20nouveaut=C3=A9s).?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

1. Les pièces jointes à un article ou une rubrique sont importées sous forme de documents distants. Il faut donc donner l'URL du site d'où provient la sauvegarde dans le menu demandant la fusion.

2. Identification de chaque article de la sauvegarde avec un article de la base installée, s'ils ont meme titre et si leurs rubriques mères ont été identifées.

A noter qu'on pourrait comparer les deux dates de mise à jour pour décider de quand meme écrire les champs de la sauvegarde si sa version de l'article est plus récénte. Allant plus loin, on pourrait utiliser la table des versions pour décider quel est plus récent de chaque champ, et offrir ainsi une véritable ''synchronisation'' entre 2 sites fonctionnant en miroir. A approfondir.
---
 ecrire/exec/admin_tech.php   |   4 +
 ecrire/exec/import_all.php   |  41 ++++---
 ecrire/inc/import.php        |  21 ++--
 ecrire/inc/import_1_3.php    |   9 +-
 ecrire/inc/import_insere.php | 219 ++++++++++++++++++++++++-----------
 5 files changed, 200 insertions(+), 94 deletions(-)

diff --git a/ecrire/exec/admin_tech.php b/ecrire/exec/admin_tech.php
index 022fc5822e..72f8bb4b6b 100644
--- a/ecrire/exec/admin_tech.php
+++ b/ecrire/exec/admin_tech.php
@@ -145,6 +145,10 @@ echo "</table>";
 	echo  "<p><input name='insertion' type='radio' />&nbsp;",
 	  _L('Fusionner la base actuelle et la sauvegarde'),
 	  '</p>';
+	echo  "<p>",
+	  _L("Eventuellement, URL du site d'origine&nbsp;:"),
+	  "<input name='url_site' type='texte' />",
+	  '</p>';
 	fin_cadre_relief();
 
 	echo "\n</p><div align='right'><input class='fondo' type='submit' value='",
diff --git a/ecrire/exec/import_all.php b/ecrire/exec/import_all.php
index 9fbae317cf..0a295ffdee 100644
--- a/ecrire/exec/import_all.php
+++ b/ecrire/exec/import_all.php
@@ -116,39 +116,43 @@ function exec_import_all_dist()
 	// precaution inutile I think (esj)
 	list($my_date) = spip_fetch_array(spip_query("SELECT UNIX_TIMESTAMP(maj) AS d FROM spip_meta WHERE nom='debut_restauration'"), SPIP_NUM);
 
-	if ($my_date) {
-
-		global $trans;
-		if ($request['insertion'] == 'passe2') {
-			include_spip('inc/import_insere');
-			$trans = translate_init($request);
-		} else $trans = array();
-
-		$res = import_tables($request, $dir);
-	}
+	$res = $my_date ? import_all_milieu($request, $dir) : '';
 
 	echo $res, "</body></html>\n";
 
-	if ($request['insertion'] == 'on') {
+	if ($request['insertion'] == 'on' AND $res) {
 			$request['insertion'] = 'passe2';
+			if ($request['url_site']
+			AND substr($request['url_site'],-1) != '/')
+				$request['url_site'] .= '/';
 			import_all_debut($request);
-			redirige_par_entete('./');
-	} else if ($request['insertion']) 
-			spip_query("DROP TABLE spip_translate");
-	  
+			$res = import_all_milieu($request, $dir);
+	}
+ 
 	if ($charset = $GLOBALS['meta']['charset_restauration']) {
 			ecrire_meta('charset', $charset);
 			ecrire_metas();
 	}
 
 	detruit_restaurateur();
-	import_all_fin();
+	import_all_fin($request);
 	include_spip('inc/rubriques');
 	calculer_rubriques();
 
 	if (!$res) ecrire_acces();	// Mise a jour du fichier htpasswd
 }
 
+function import_all_milieu($request, $dir)
+{
+	global $trans;
+	if ($request['insertion'] == 'passe2') {
+		include_spip('inc/import_insere');
+		$trans = translate_init($request);
+	} else $trans = array();
+
+	return import_tables($request, $dir);
+}
+
 // http://doc.spip.org/@import_all_debut
 function import_all_debut($request) {
 	ecrire_meta("request_restauration", serialize($request));
@@ -158,7 +162,7 @@ function import_all_debut($request) {
 }
 
 // http://doc.spip.org/@import_all_fin
-function import_all_fin() {
+function import_all_fin($request) {
 
 	effacer_meta("charset_restauration");
 	effacer_meta("charset_insertion");
@@ -169,6 +173,9 @@ function import_all_fin() {
 	effacer_meta('version_archive_restauration');
 	effacer_meta('tag_archive_restauration');
 	ecrire_metas();
+	if ($request['insertion'] == 'passe2') 
+		spip_query("DROP TABLE spip_translate");
+	 
 }
 
 // http://doc.spip.org/@import_queldir
diff --git a/ecrire/inc/import.php b/ecrire/inc/import.php
index a06e0a97f4..bb0d605664 100644
--- a/ecrire/inc/import.php
+++ b/ecrire/inc/import.php
@@ -121,9 +121,6 @@ function import_debut($f, $gz='fread') {
 			return $r;
 		}
 	}
-	// improbable: fichier correct avant debut_admin et plus apres
-	import_all_fin();
-	die(_T('info_erreur_restauration'));
 }
 
 // on conserve ce tableau pour faire des translations
@@ -180,7 +177,8 @@ function import_tables($request, $dir) {
 
 	if ($request['insertion']=='on') {
 		include_spip('inc/import_insere');
-		$request['init'] = (!$abs_pos) ? 'insere_1_init' : 'insere_2_init';		$request['boucle'] = 'import_insere';
+		$request['init'] = (!$abs_pos) ? 'insere_1_init' : 'insere_1bis_init';
+		$request['boucle'] = 'import_insere';
 	} elseif ($request['insertion']=='passe2') {
 		$request['init'] = 'insere_2_init';
 		$request['boucle'] = 'import_translate';
@@ -205,6 +203,8 @@ function import_tables($request, $dir) {
 
 	if ($abs_pos==0) {
 		list($tag, $r, $charset) = import_debut($file, $gz);
+	// improbable: fichier correct avant debut_admin et plus apres
+		if (!$tag) return !($import_ok = true);
 // tag ouvrant du Dump:
 // 'SPIP' si fait par spip, nom de la base source si fait par  phpmyadmin
 		$version_archive = $r['version_archive'];
@@ -230,18 +230,25 @@ function import_tables($request, $dir) {
 	flush();
 
 	$oldtable ='';
+	$cpt = 0;
+	$pos = $abs_pos;
 	while ($table = $fimport($file, $request, $gz)) {
 	  // memoriser pour pouvoir reprendre en cas d'interrupt,
 	  // mais pas d'ecriture sur fichier, ca ralentit trop
 		ecrire_meta("status_restauration", "$abs_pos");
 		if ($oldtable != $table) {
-			spip_log("Restauration de $table (commence en $abs_pos)");
+			if ($oldtable) spip_log("$cpt entrees");
+			spip_log("Analyse de $table (commence en $pos)");
 			affiche_progression_javascript($abs_pos,$size,$table);
 			$oldtable = $table;
-		}
+			$cpt = 0;
+			$pos = $abs_pos;
+		} 
+		$cpt++;
 	}
+	spip_log("$cpt entrees");
 
-	if (!$import_ok) 
+	if (!$import_imok) 
 		$res =  _T('avis_archive_invalide');
 	else {
 		$res = '';
diff --git a/ecrire/inc/import_1_3.php b/ecrire/inc/import_1_3.php
index b4a559dd6f..971c499305 100644
--- a/ecrire/inc/import_1_3.php
+++ b/ecrire/inc/import_1_3.php
@@ -78,7 +78,7 @@ function inc_import_1_3_dist($lecteur, $request, $gz='fread') {
 			if ($request['insertion']=='on') {
 // Au premier tour de l'insertion, ne memoriser que le strict necessaire 
 // pour pouvoir identifier avec l'existant.
-
+// (Faudrait convenir d'une structure de donnees, c'est lourd & inextensible)
 				$b = array();
 				if (isset($desc['field'][$p='titre']))
 					$b[$p]= $desc['field'][$p];
@@ -86,6 +86,13 @@ function inc_import_1_3_dist($lecteur, $request, $gz='fread') {
 					$b[$p]= $desc['field'][$p];
 				if (isset($desc['field'][$p='id_parent']))
 					$b[$p]= $desc['field'][$p];
+				if (isset($desc['field'][$p='id_rubrique']))
+					$b[$p]= $desc['field'][$p];
+				if (isset($desc['field'][$p='fichier'])) {
+					$b[$p]= $desc['field'][$p];
+					$b['taille']= $desc['field']['taille'];
+					spip_log("pass1 " . join(',', array_keys($b)));
+				}
 				$p = $desc['key']["PRIMARY KEY"];
 				$b[$p] = $desc['field'][$p];
 				$desc['field'] = $b; 
diff --git a/ecrire/inc/import_insere.php b/ecrire/inc/import_insere.php
index 30ef76ccbe..0d01682ceb 100644
--- a/ecrire/inc/import_insere.php
+++ b/ecrire/inc/import_insere.php
@@ -12,27 +12,6 @@
 
 if (!defined("_ECRIRE_INC_VERSION")) return;
 
-// http://doc.spip.org/@insere_2_init
-function insere_2_init($request) {
-
-	// l'insertion porte sur les tables principales ...
-	$t = array_keys($GLOBALS['tables_principales']);
-	// ... mais pas cette table car elle n'est pas extensible ..
-	// (si on essaye ==> duplication sur la cle secondaire)
-	unset($t[array_search('spip_types_documents', $t)]);
-	// .. ni celle-ci a cause de la duplication des login 
-	unset($t[array_search('spip_auteurs', $t)]);
-	// et les tables auxiliaires sur les mots car on sait les identifier
-	$t[]= 'spip_mots_articles';
-	$t[]= 'spip_mots_breves';
-	$t[]= 'spip_mots_rubriques';
-	$t[]= 'spip_mots_syndic';
-	$t[]= 'spip_mots_forum';
-	$t[]= 'spip_mots_documents';
-
-	return $t;
-}
-
 // http://doc.spip.org/@insere_1_init
 function insere_1_init($request) {
 
@@ -52,7 +31,38 @@ function insere_1_init($request) {
 	spip_create_table('spip_translate', $spip_translate, $spip_translate_key, true);
 	// au cas ou la derniere fois ce serait terminee anormalement
 	spip_query("DELETE FROM spip_translate");
-	return insere_2_init($request);
+	return insere_1bis_init($request);
+}
+
+// http://doc.spip.org/@insere_2_init
+function insere_1bis_init($request) {
+
+	// l'insertion porte sur les tables principales ...
+	$t = array_keys($GLOBALS['tables_principales']);
+	// ... mais pas cette table car elle n'est pas extensible ..
+	// (si on essaye ==> duplication sur la cle secondaire)
+	unset($t[array_search('spip_types_documents', $t)]);
+	// .. ni celle-ci a cause de la duplication des login 
+	unset($t[array_search('spip_auteurs', $t)]);
+	return $t;
+}
+
+// En passe 2, relire les tables principales et les tables auxiliaires 
+// sur les mots et les documents car on sait les identifier
+
+function insere_2_init($request) {
+	$t = insere_1bis_init($request);
+
+	$t[]= 'spip_mots_articles';
+	$t[]= 'spip_mots_breves';
+	$t[]= 'spip_mots_rubriques';
+	$t[]= 'spip_mots_syndic';
+	$t[]= 'spip_mots_forum';
+	$t[]= 'spip_mots_documents';
+	$t[]= 'spip_documents_articles';
+	$t[]= 'spip_documents_rubriques';
+
+	return $t;
 }
 
 //   construire le tableau PHP de la table spip_translate
@@ -88,56 +98,93 @@ function import_insere($values, $table, $desc, $request) {
 		}
 		$ajout = 1;
 	}
-	// et memoriser la correspondance dans la table auxiliaire
-	// si different et pas de recherche dessus plus tard
-	if (($n != $values[$type_id]) OR $type_id == 'id_groupe') {
-		if (is_array($n))
-		  list($id, $titre) = $n; 
-		else {$id = $n; $titre = "";}
-		spip_abstract_insert('spip_translate',
+
+	if (is_array($n))
+		list($id, $titre) = $n; 
+	else {$id = $n; $titre = "";}
+	spip_abstract_insert('spip_translate',
 				"(id_old, id_new, titre, type, ajout)",
 				     "(". $values[$type_id] .",$id, " . _q($titre) . ", '$type_id', '$ajout')");
-	}
 }
 
 // Renumerotation des entites collectees
-// Le tableau de correspondance est passe en reference pour que le nouveau
-// numero d'une entite soit calcule une seule fois, a sa premiere occurrence.
-// Si une allocation est finalement necessaire, la renumerotation
-// est repercutee sur la table SQL temporaire pour qu'en cas de reprise
-// sur Time-Out il n'y ait pas reallocation.
-// Autrement on evite cet acces SQL, quitte a recalculer le nouveau numero
-// si une autre occurrence est rencontree a la reprise. Pas dramatique.
+// Appelle la fonction specifique a la table, ou a defaut la std.
+// Le tableau de correspondance est global, et permet qu'un numero
+// d'une entite soit calcule une seule fois, a sa premiere occurrence.
+// (Mais des requetes avec jointures eviteraient sa construction. A voir)
 
 // http://doc.spip.org/@import_translate
 function import_translate($values, $table, $desc, $request) {
+
+	if (!function_exists($f = 'import_translate_' . $table))
+	  $f = 'import_translate_std';
+	$f($values, $table, $desc, $request);
+}
+
+// La fonction d'insertion apres renumerotation.
+// Afin qu'inserer une 2e fois la meme sauvegarde ne change pas la base,
+// chaque entree de la sauvegarde est ignoree s'il existe une entree
+// de meme titre avec le meme contexte (parent etc) dans la base installee.
+// Une synchronisation plus fine serait preferable, cf [8002]
+
+function import_inserer_translate($values, $table, $desc, $request, $vals) {
 	global $trans;
+	$p = $desc['key']["PRIMARY KEY"];
+	$v = $values[$p];
+	if (!isset($trans[$p]) OR !isset($trans[$p][$v]) OR $trans[$p][$v][2])
+		spip_query("REPLACE $table (" . join(',',array_keys($values)) . ') VALUES (' .substr($vals,1) . ')');
+}
+
+// Insertion avec renumerotation, y compris des raccourcis.
+function import_translate_std($values, $table, $desc, $request) {
+
 	$vals = '';
 
 	foreach ($values as $k => $v) {
-		if ($k=='id_parent' OR $k=='id_secteur') $k = 'id_rubrique';
+		if (($k=='chapo') AND preg_match(',^=(\d+)(.*)$,', $v, $m))
+			$v = '=' . importe_translate_maj('id_article',$m[1]).$m[2];
+		else {
+			if ($k=='id_parent' OR $k=='id_secteur')
+				$k = 'id_rubrique';
+			$v = importe_raccourci($k,importe_translate_maj($k, $v));
+		}
+		$vals .= "," . _q($v);
+	}
+	import_inserer_translate($values, $table, $desc, $request, $vals);
+}
 
-		$v = importe_translate_maj($k, $v);
+function import_translate_spip_documents($values, $table, $desc, $request) {
 
-		if (preg_match_all(_RACCOURCI_LIEN, $v, $m, PREG_SET_ORDER)) {
-			foreach ($m as $regs) {
-				$v = importe_raccourci($regs, $k, $v);
-			}
-		}
 
-		$vals .= "," . _q($v);
+	if (isset($request['url_site'])) {
+		$distancer = ($values['distant'] == 'non');
+		$url = $request['url_site'];
+	} else  $distancer = false;
+
+	$values['distant']= 'oui';
+
+	$vals = '';
+	foreach ($values as $k => $v) {
+	  if ($distancer AND $k=='fichier')
+	    $v = $url .$v;
+	  else $v = importe_raccourci($k,importe_translate_maj($k, $v));
+	  $vals .= "," . _q($v);
 	}
-	// pas la peine d'ecraser avec les memes valeurs si rien de neuf
-	$p = $desc['key']["PRIMARY KEY"];
-	$v = $values[$p];
-	if (!isset($trans[$p]) OR !isset($trans[$p][$v]) OR $trans[$p][$v][2])
-		spip_query($q = "REPLACE $table (" . join(',',array_keys($values)) . ') VALUES (' .substr($vals,1) . ')');
+	import_inserer_translate($values, $table, $desc, $request, $vals);
 }
 
+// Fonction de renumerotation, par delegation aux fonction specialisees
+// Si une allocation est finalement necessaire, celles-ci doivent repercuter
+// la renumerotation sur la table SQL temporaire pour qu'en cas de reprise
+// sur Time-Out il n'y ait pas reallocation.
+// En l'absence d'allocation, cet acces SQL peut etre omis, quitte a 
+// recalculer le nouveau numero  si une autre occurrence est rencontree
+// a la reprise. Pas dramatique.
+
 // http://doc.spip.org/@importe_translate_maj
 function importe_translate_maj($k, $v)
 {
-  global $trans;
+	global $trans;
 	if (!(isset($trans[$k]) AND isset($trans[$k][$v]))) return $v;
 
 	list($g, $titre, $ajout) = $trans[$k][$v];
@@ -154,27 +201,41 @@ function importe_translate_maj($k, $v)
 }
 
 // http://doc.spip.org/@importe_raccourci
-function importe_raccourci($regs, $k, $v)
+function importe_raccourci($k, $v)
 {
-	$lien = vider_url($regs[3]); # supprimer 'http://' ou 'mailto:'
-
-	if (!$match = typer_raccourci($lien)) return $v;
-
-	list($f,$objet,$id,$params,$ancre) = $match;
-
-	$k = 'id_' . $f;
-	$g = importe_translate_maj($k, $id);
-
-	if ($g == $id) return $v;
+	if (preg_match_all(_RACCOURCI_LIEN, $v, $m, PREG_SET_ORDER)) {
+		foreach ($m as $regs) {
+		  // supprimer 'http://' ou 'mailto:'
+		  	$lien = vider_url($regs[3]);
+			if ($match = typer_raccourci($lien)) {
+				list($f,$objet,$id,$params,$ancre) = $match;
+				$k = 'id_' . $f;
+				$g = importe_translate_maj($k, $id);
+				if ($g != $id) {
+
+				  $rac = '[' . $regs[1] . '->' . $reg[2] . $objet . $g . $params . $ancre .']';
+				  $v = str_replace($regs[0], $rac, $v);
+				}
+			}
+		}
+	}
+	return $v;
+}
 
-	$rac = '[' . $regs[1] . '->' . $reg[2] . $objet . $g . $params . $ancre .']';
-	return str_replace($regs[0], $rac, $v);
+// un document importe est considere comme identique a un document present
+// s'ils ont meme taille et meme nom
+function import_identifie_id_document($values, $table, $desc, $request) {
+	$t = $values['taille'];
+	$f = $values['fichier'];
+	$h = $request['url_site'] . $f;
+	$r = spip_fetch_array(spip_query($q="SELECT id_document, fichier FROM spip_documents WHERE taille=" . _q($t) . " AND (fichier=" . _q($f) . " OR fichier= " . _q($h) . ')'), SPIP_NUM);
+	return $r;
 }
 
 // deux groupes de mots ne peuvent avoir le meme titre ==> identification
 // http://doc.spip.org/@import_identifie_id_groupe
 function import_identifie_id_groupe($values, $table, $desc, $request)  {
-	$r = spip_fetch_array(spip_query($q = "SELECT id_groupe, titre FROM spip_groupes_mots WHERE titre=" . _q($values['titre'])), SPIP_NUM);
+	$r = spip_fetch_array(spip_query("SELECT id_groupe, titre FROM spip_groupes_mots WHERE titre=" . _q($values['titre'])), SPIP_NUM);
 	return $r;
 }
 
@@ -185,11 +246,11 @@ function import_identifie_id_mot($values, $table, $desc, $request) {
 	return array((0 - $values['id_groupe']), $values['titre']);
 }
 
-// mot de meme titre et de meme groupe ==> identification
+// Passe 2: mot de meme titre et de meme groupe ==> identification
 // http://doc.spip.org/@import_identifie_parent_id_mot
 function import_identifie_parent_id_mot($id_groupe, $titre, $v)
 {
-  global $trans;
+	global $trans;
 	$titre = _q($titre);
 	$id_groupe = 0-$id_groupe;
 	if (isset($trans['id_groupe'])
@@ -201,9 +262,30 @@ function import_identifie_parent_id_mot($id_groupe, $titre, $v)
 	$r = spip_abstract_insert('spip_mots', '', '()');
 	spip_query("REPLACE spip_translate (id_old, id_new, titre, type, ajout) VALUES ($v,$r,$titre,'id_mot',1)");
 	return $r;
+}
+
+// idem pour les articles
+function import_identifie_id_article($values, $table, $desc, $request) {
+	return array((0 - $values['id_rubrique']), $values['titre']);
+}
+
+// Passe 2 des articles comme pour les mots
+
+function import_identifie_parent_id_article($id_parent, $titre, $v)
+{
+	$id_parent = importe_translate_maj('id_rubrique', (0 - $id_parent));
 
+	$titre = _q($titre);
+	$r = spip_fetch_array(spip_query("SELECT id_article FROM spip_articles WHERE titre=$titre AND id_rubrique=$id_parent" ));
+
+	if ($r) return (0 - $r['id_article']);
+
+	$r = spip_abstract_insert('spip_articles', '', '()');
+	spip_query("REPLACE spip_translate (id_old, id_new, titre, type, ajout) VALUES ($v,$r,$titre,'id_article',1)");
+	return $r;
 }
 
+
 // pour une rubrique le titre est insuffisant, il faut l'identite du parent
 // Memoriser ces 2 infos et le signaler a import_translate grace a 1 negatif
 // http://doc.spip.org/@import_identifie_id_rubrique
@@ -211,7 +293,7 @@ function import_identifie_id_rubrique($values, $table, $desc, $request) {
 	return array((0 - $values['id_parent']), $values['titre']);
 }
 
-// renumerotation en cascade. 
+// Passe 2 des rubriques, renumerotation en cascade. 
 // rubrique de meme titre et de meme parent ==> identification
 // http://doc.spip.org/@import_identifie_parent_id_rubrique
 function import_identifie_parent_id_rubrique($id_parent, $titre, $v)
@@ -256,5 +338,4 @@ function import_alloue_id_rubrique($id_parent, $titre, $v) {
 	spip_query("REPLACE spip_translate (id_old, id_new, titre, type, ajout) VALUES ($v,$r,$titre,'id_rubrique',1)");
 	return $r;
 }
-
 ?>
-- 
GitLab