From b231955973945b24778ef7af7b43fcb64d275e22 Mon Sep 17 00:00:00 2001
From: "Committo,Ergo:sum" <esj@rezo.net>
Date: Mon, 22 Jan 2007 18:00:11 +0000
Subject: [PATCH] =?UTF-8?q?Correction=20de=20[8454]:=20vraiment=20sportif?=
 =?UTF-8?q?=20de=20concilier=20les=20extraits=20de=20table=20pour=20les=20?=
 =?UTF-8?q?admins=20restreints=20et=20l'=C3=A9criture=20par=20tranche=20de?=
 =?UTF-8?q?=20table=20pour=20reprendre=20sur=20time-out.=20Ca=20semble=20c?=
 =?UTF-8?q?orrect=20=C3=A0=20pr=C3=A9sent.?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 ecrire/action/export_all.php |  26 ++++---
 ecrire/exec/export_all.php   |  60 ++++++++--------
 ecrire/inc/export.php        | 129 +++++++++++++++++------------------
 3 files changed, 103 insertions(+), 112 deletions(-)

diff --git a/ecrire/action/export_all.php b/ecrire/action/export_all.php
index 1c9e5c74f8..56f2094d71 100644
--- a/ecrire/action/export_all.php
+++ b/ecrire/action/export_all.php
@@ -18,7 +18,7 @@ include_spip('inc/minipres');
 
 function action_export_all_dist()
 {
-	global $gz, $connect_toutes_rubriques ;
+	global $connect_toutes_rubriques ;
 	
         $securiser_action = charger_fonction('securiser_action', 'inc');
         $arg = $securiser_action();
@@ -28,18 +28,10 @@ function action_export_all_dist()
 	if ($connect_toutes_rubriques AND file_exists(_DIR_DUMP))
 		$dir = _DIR_DUMP;
 
-	$file =  $dir . $arg;
-
-	if ($GLOBALS['flag_ob_flush']) ob_flush();
-	flush();
-
-	$f = ($gz) ? gzopen($file, "ab") : fopen($file, "ab");
-	$_fputs = ($gz) ? gzputs : fputs;
-	$_fputs($f, export_entete());
-	$files = ramasse_parties($file, $gz, $file . ".part");
-	$_fputs($f, export_enpied());
-	if ($gz) gzclose($f); else fclose($f);
-		
+	list($file, $nb) = split('/', $arg);
+	$file =  $dir . $file;
+	$files = ramasse_parties($file, $file, $nb, true);
+	
 	effacer_meta("status_dump");
 	ecrire_metas();
 
@@ -49,9 +41,14 @@ function action_export_all_dist()
 		array('archive' => ':<br /><b>'.joli_repertoire($file)."</b> ($n)"));
 
 	echo install_debut_html(_T('info_sauvegarde'));
+	if (!$files) {
+	  echo _T('avis_erreur_sauvegarde', array('type'=>'.', 'id_objet'=>'. .'));
+
+	} else {
 	// ne pas effrayer inutilement: il peut y avoir moins de fichiers
 	// qu'annonce' si certains etaient vides
-#	echo "<ul><li>", join('</li><li>', $files), '</li></ul>';
+
+	echo "<!--", join("\n", $files), '-->';
 	echo "<p style='text-align: left'>".
 	  $n,
 	" <a href='" . _DIR_RESTREINT . "'>".
@@ -59,6 +56,7 @@ function action_export_all_dist()
 	. "</a> "
 	._T('info_sauvegarde_reussi_04')
 	. "</p>\n";
+	}
 	echo install_fin_html();
 }
 ?>
\ No newline at end of file
diff --git a/ecrire/exec/export_all.php b/ecrire/exec/export_all.php
index 13109f3c80..9a05e2bc3e 100644
--- a/ecrire/exec/export_all.php
+++ b/ecrire/exec/export_all.php
@@ -58,7 +58,7 @@ $GLOBALS['flag_ob_flush'] = function_exists('ob_flush');
 // http://doc.spip.org/@exec_export_all_dist
 function exec_export_all_dist()
 {
-	global $archive, $etape, $gz, $connect_toutes_rubriques;
+	global $archive, $gz, $connect_toutes_rubriques;
 
 	if ($connect_toutes_rubriques AND file_exists(_DIR_DUMP))
 		$dir = _DIR_DUMP;
@@ -72,7 +72,6 @@ function exec_export_all_dist()
 	if (!$archive) $archive = export_nom_fichier_dump($dir,$gz);
 	
 	$file = $dir . $archive;
-	$partfile = $file . ".part";
   
 	// utiliser une version fraiche des metas (ie pas le cache)
 	include_spip('inc/meta');
@@ -89,7 +88,7 @@ function exec_export_all_dist()
 	}
 
 	if ($start){
-		$status_dump = "$gz::$archive::0::0";
+		$status_dump = "$gz::$archive::1::0";
 		ecrire_meta("status_dump", "$status_dump",'non');
 		$status_dump = explode("::",$status_dump);
 		ecrire_metas();
@@ -105,19 +104,20 @@ function exec_export_all_dist()
 	list($tables_for_dump, $tables_for_link) = export_all_list_tables();
 
 	$status_dump = explode("::",$GLOBALS['meta']["status_dump"]);
-	$etape = $status_dump[2];
+	$etape_actuelle = $status_dump[2];
+	$sous_etape = $status_dump[3];
+	$all = count($tables_for_dump);
 
 	// Pour avoir les valeurs de _DIR_IMG etc relatives a l'espace public
 	// la phase finale de reunion des fichiers en un seul est faite la-bas
-	$href = generer_action_auteur("export_all",$archive,'',true);
+	$href = generer_action_auteur("export_all","$archive/$all",'',true);
 
-	if ($etape >= count($tables_for_dump)){ // au timeout
+	if ($etape_actuelle > $all){ // au timeout
 		include_spip('inc/headers');
 		redirige_par_entete($href);
 	}
 
-	echo install_debut_html(_T('info_sauvegarde'));
-	echo "<p>",_T("info_sauvegarde"), $reprise, "</p>\n";
+	echo install_debut_html(_T('info_sauvegarde') . " ($all)");
 	$f = ($gz) ? gzopen($file, "ab") : fopen($file, "ab");
 	if (!$f) {
 		echo "<p>",
@@ -138,36 +138,34 @@ function exec_export_all_dist()
 	if ($start) $timeout = round($timeout/2);
 		// script de rechargement auto sur timeout
 	echo ("<script language=\"JavaScript\" type=\"text/javascript\">window.setTimeout('location.href=\"".generer_url_ecrire("export_all","archive=$archive&gz=$gz",true)."\";',$timeout);</script>\n");
-	$cpt = 0;
-	$paquets = 400; // nombre d'enregistrements dans chaque paquet
-	echo "<div style='text-align: left'>\n";
-	foreach($tables_for_dump as $i=>$table){
-
-		while (1){ // on ne connait pas le nb de paquets d'avance
 
-			list($string,$status_dump)=export_objets($table, $tables_for_link[$table],0, false, $i, _T("info_sauvegarde").", $table",$paquets);
-
-			if ($string) { 
-// on ecrit dans un fichier generique
-// puis on le renomme pour avoir une operation atomique 
-				ecrire_fichier ($partfile, $string);
-				rename($partfile,$partfile.".$cpt");
-				$cpt ++;
-			}
-	// on se contente d'une ecriture en base pour aller plus vite
-	// a la relecture on en profitera pour mettre le cache a jour
-			ecrire_meta("status_dump", implode("::",$status_dump),'non');
-			// attention $string vide ne suffit pas a sortir
-			// car les admins restreints peuvent parcourir
-			// une portion de table vide pour eux.
-			if (!$status_dump[3]) break;
+	echo "<div style='text-align: left'>\n";
+	$etape = 1;
+	foreach($tables_for_dump as $table){
+
+		$liens = $tables_for_link[$table];
+		if ($etape_actuelle <= $etape) {
+		  $r = spip_query("SELECT COUNT(*) FROM $table");
+		  $r = spip_fetch_array($r, SPIP_NUM);
+		  $r = $r[0];
+		  echo "\n<br /><strong>",$etape, '. ', $table,"</strong> ";
+		  if (!$r) echo _T('texte_vide');
+		  else {
+		    $cpt = export_objets($table, $liens, $etape, $sous_etape,$dir, $archive, $gz, $r);
+			$filetable = $dir . $archive . '_' . $etape;
+			ramasse_parties($dir . $archive . ".$etape", $filetable, $cpt);
+		  }
+		  $etape++;
+		  $sous_etape = 0;
+		  $status_dump = "$gz::$archive::" . $etape . "::0";
+		  ecrire_meta("status_dump", $status_dump,'non');
 		}
 	}
 	echo "</div>\n";
 	// si Javascript est dispo, anticiper le Time-out
 	echo ("<script language=\"JavaScript\" type=\"text/javascript\">window.setTimeout('location.href=\"$href\";',0);</script>\n");
 	echo install_fin_html();
-}
+	}
 
 // construction de la liste des tables pour le dump :
 // toutes les tables principales
diff --git a/ecrire/inc/export.php b/ecrire/inc/export.php
index 2c903e0a62..c07a7e243c 100644
--- a/ecrire/inc/export.php
+++ b/ecrire/inc/export.php
@@ -27,94 +27,88 @@ function export_nom_fichier_dump($dir,$gz=true){
 
 
 // http://doc.spip.org/@ramasse_parties
-function ramasse_parties($archive, $gz, $partfile){
+function ramasse_parties($archive, $partfile, $nb, $fin=''){
 	// a ameliorer par un preg_file
 	// si le rammassage est interrompu par un timeout, on perd des morceaux
-	$cpt=0;
 	$files = array();
-	while(file_exists($f = $partfile.".$cpt")){
-		$contenu = "";
-		if (lire_fichier ($f, $contenu))
-			if (!ecrire_fichier($archive,$contenu,false,false))
-			{
-				echo "<p>"._T('avis_erreur_sauvegarde', array('type'=>'.', 'id_objet'=>'. .'))."</p>\n";
-				exit;
+	$ok = true;
+	if (!ecrire_fichier($archive,$fin ? export_entete() : '',false,false))
+	  $ok = false;
+	else {
+		for($cpt =1; $cpt <= $nb; $cpt++) {
+			if (file_exists($f = $partfile.".$cpt")) {
+			  $contenu = "";
+			  if (lire_fichier ($f, $contenu)) {
+			    if (!ecrire_fichier($archive,$contenu,false,false))
+			      { $ok = false; break;}
+			  }
+			  unlink($f);
+			  $files[]=$f;
 			}
-		unlink($f);
-		$files[]=$f;
-		$cpt++;
+		}
 	}
-	return $files;
+
+	if ($fin AND $ok)
+		$ok = ecrire_fichier($archive, export_enpied(),false,false);
+
+	return $ok ? $files : false;
 }
 
+define('_EXPORT_TRANCHES_LIMITE', 400);
+
 //
-// Exportation generique d'objets (fichier ou retour de fonction)
-//
+// Exportation de table SQL au format xml
+// La constante ci-dessus determine la taille des tranches,
+// chaque tranche etant copiee immediatement dans un fichier 
+// et son numero memorisee dans le serveur SQL.
+// En cas d'abandon sur Time-out, le travail pourra ainsi avancer
+// charge a l'appelant de coller tous les morceaux de 1 a N
+
 // http://doc.spip.org/@export_objets
-function export_objets($table, $liens, $file = 0, $gz = false, $etape_actuelle="", $nom_etape="",$limit=0) {
+function export_objets($table, $liens, $etape, $cpt, $dir, $archive, $gz, $total) {
 	static $etape_affichee=array();
 
-	$string='';
-	$status_dump = explode("::",$GLOBALS['meta']["status_dump"]);
-	$etape_en_cours = $status_dump[2];
-	$pos_in_table = $status_dump[3];
-
-	if ($etape_en_cours < 1 OR $etape_en_cours == $etape_actuelle){
-
-	  // on calcule ca autant de fois qu'il y a de paquets!
-	  // on devrait plutot le faire dans l'appelant
-	  // et le memoriser dans status_dump
-		$result = spip_query("SELECT COUNT(*) FROM $table");
-		$row = spip_fetch_array($result,SPIP_NUM);
-		$total = $row[0];
-		if (!isset($etape_affichee[$etape_actuelle]) AND $total){
-			echo "\n<br /><strong>$etape_actuelle-$nom_etape</strong>";
-			$etape_affichee[$etape_actuelle] = 1;
-		}
-		if ($pos_in_table!=0 AND $total)
-			echo " ", $pos_in_table;
+	$debut = $cpt * _EXPORT_TRANCHES_LIMITE;
+	$filetable = $dir . $archive . '_' . $etape . '.';
+
+	while (1){ // on ne connait pas le nb de paquets d'avance
+
 		if ($GLOBALS['flag_ob_flush']) ob_flush();
 		flush();
-		if ($limit == 0) $limit = $total;
-
-		$string = build_while($pos_in_table, $limit, $table);
-
-		if ($pos_in_table>=$total){
-			if ($total) echo " ok";
-			$status_dump[2] = $status_dump[2]+1;
-			$status_dump[3] = 0;
-		} else  $status_dump[3] = $pos_in_table;
-
-		if ($file) {
-			$_fputs = ($gz) ? gzputs : fputs;
-			$_fputs($file, $string);
-			fflush($file);
-			ecrire_meta("status_dump", implode("::",$status_dump),'non');
-			$string='';
+
+		$string = build_while($debut, $table);
+		// attention $string vide ne suffit pas a sortir
+		// car les admins restreints peuvent parcourir
+		// une portion de table vide pour eux.
+		if ($string) { 
+// on ecrit dans un fichier generique
+// puis on le renomme pour avoir une operation atomique 
+			$cpt++;
+			ecrire_fichier ($filetable, $string);
+			rename($filetable,$filetable . $cpt);
 		}
-	} else { // ca ne sert plus il me semble
-	  if ($etape_actuelle < $etape_en_cours) {
-		if (!isset($etape_affichee[$etape_actuelle]))
-			echo "\n<li>", $etape_actuelle,'-',$nom_etape,"</li>";
-	  } else {
-		if (!isset($etape_affichee[$etape_actuelle]))
-			echo "\n<li> <span style='color: #999999'>",$etape_actuelle,'-',$nom_etape,'</span></li>';
-	  }
-	  if ($GLOBALS['flag_ob_flush']) ob_flush();
-	  flush();
+
+		$debut += _EXPORT_TRANCHES_LIMITE;
+		if ($debut >= $total) {break;}
+		echo " $debut";
+	// on se contente d'une ecriture en base pour aller plus vite
+	// a la relecture on en profitera pour mettre le cache a jour
+		$status_dump = "$gz::$archive::$etape::$cpt";
+		ecrire_meta("status_dump", $status_dump,'non');
 	}
-	return array($string,$status_dump);
+	echo " $total."; 
+	return $cpt;
 }
 
-// Exporter les champs de la table
+// Construit la version xml  des champs d'une table
 
 // http://doc.spip.org/@build_while
-function build_while(&$pos_in_table, $limit, $table) {
+function build_while($debut, $table) {
 	global $connect_toutes_rubriques ;
 	global $tables_principales;
 	static $table_fields=array();
 
-	$result = spip_query("SELECT * FROM $table LIMIT " . intval($pos_in_table) .',' . intval($limit));
+	$result = spip_query("SELECT * FROM $table LIMIT $debut," . _EXPORT_TRANCHES_LIMITE);
 	// Recuperer les noms des champs
 	// Ces infos sont donnees par le abstract_showtable
 	// les instructions natives mysql ne devraient pas apparaitre ici
@@ -125,20 +119,21 @@ function build_while(&$pos_in_table, $limit, $table) {
 	} else	$nfields = count($table_fields[$table]);
 
 	$string = '';
+
 	$all = $connect_toutes_rubriques
 	  ||(!in_array('id_rubrique',$table_fields[$table]));
 
 	while ($row = spip_fetch_array($result,SPIP_ASSOC)) {
 		if ((!isset($row['impt']) OR $row['impt']=='oui')
 		AND ($all OR autoriser('publierdans','rubrique',$row['id_rubrique']))) {
-			$string .= "<$table>\n";
+			$attributs = "";
+			$string .= "<$table$attributs>\n";
 			for ($i = 0; $i < $nfields; ++$i) {
 				$k = $table_fields[$table][$i];
 				$string .= "<$k>" . text_to_xml($row[$k]) . "</$k>\n";
 			}
 			$string .= "</$table>\n\n";
 		}
-		$pos_in_table++;
 	}
 	spip_free_result($result);
 	return $string;
-- 
GitLab