X-Git-Url: http://git.cyclocoop.org/?p=velocampus%2Fweb%2Fwww.git;a=blobdiff_plain;f=www%2Fecrire%2Finc%2Fexport.php;h=0637d8602403ca685eba11be8b5b362fe6779411;hp=25afae2549f7fc6423b372e613ff60af978c68f9;hb=e99f0878011913365e49b30d90e496c24c301393;hpb=80b4d3e85f78d402ed2e73f8f5d1bf4c19962eed diff --git a/www/ecrire/inc/export.php b/www/ecrire/inc/export.php index 25afae2..0637d86 100644 --- a/www/ecrire/inc/export.php +++ b/www/ecrire/inc/export.php @@ -3,7 +3,7 @@ /***************************************************************************\ * SPIP, Systeme de publication pour l'internet * * * - * Copyright (c) 2001-2011 * + * Copyright (c) 2001-2014 * * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * * * * Ce programme est un logiciel libre distribue sous licence GNU/GPL. * @@ -15,118 +15,132 @@ if (!defined('_ECRIRE_INC_VERSION')) return; define('_EXPORT_TRANCHES_LIMITE', 200); define('_EXTENSION_PARTIES', '.gz'); -// http://doc.spip.org/@exec_export_all_args function inc_export_dist($meta) { if (!isset($GLOBALS['meta'][$meta])) { include_spip('inc/minipres'); echo minipres(); + } else { + while (true) { + $val = unserialize($GLOBALS['meta'][$meta]); + if ($dir = export_repertoire($meta, $val)) + export_trace($val, $dir, $meta); + else break; + } + list($gz, $archive, $rub,,,,$serveur,$save) = $val; + // retour a exec_export_all qui renverra sur action_export_all + return "end,$gz,$archive,$rub,$serveur,$save"; } - else { - $start = false; - list($gz, $archive, $rub, $tables_for_dump, $etape_actuelle, $sous_etape) = - unserialize($GLOBALS['meta'][$meta]); - - // determine upload va aussi initialiser l'index "restreint" - $maindir = determine_upload(); - if (!$GLOBALS['visiteur_session']['restreint']) - $maindir = _DIR_DUMP; - $dir = sous_repertoire($maindir, $meta); - $file = $dir . $archive; - $metatable = $meta . '_tables'; +} - // Reperer une situation anormale (echec reprise sur interruption) - if (!$etape_actuelle AND !$sous_etape) { - $l = preg_files($file . ".part_[0-9]+_[0-9]+"); - if ($l) { - spip_log("menage d'une sauvegarde inachevee: " . join(',', $l)); - foreach($l as $dummy) spip_unlink($dummy); - } - $start = true; // utilise pour faire un premier hit moitie moins long - $tables_sauvegardees = array(); - } else $tables_sauvegardees = isset($GLOBALS['meta'][$metatable])?unserialize($GLOBALS['meta'][$metatable]):array(); - - // concatenation des fichiers crees a l'appel precedent - ramasse_parties($dir, $archive); - $all = count($tables_for_dump); - if ($etape_actuelle > $all OR !$all){ - return "end,$gz,$archive,$rub"; // c'est fini ! - } +// calcule le repertoire de la sauvegarde +// et le nettoie au premier appel. +// Aux suivants, retourne le nom du repertoire ou rien si c'est fini. - include_spip('inc/minipres'); - @ini_set("zlib.output_compression","0"); // pour permettre l'affichage au fur et a mesure +function export_repertoire($meta, $val_meta) +{ + list(, $archive, , $tables, $etape, $sous_etape, , $save) = $val_meta; + if (!function_exists('inc_export_' . ($save ? $save : 'xml'))) { + spip_log("fonction inc_export_$save indisponible"); + return false; + } + $dir = base_dump_dir($meta); - echo ( install_debut_html(_T('info_sauvegarde') . " ($all)")); + // Reperer une situation anormale (echec reprise sur interruption) + if (($etape == 1) AND !$sous_etape) { + $file = $dir . $archive; + $l = preg_files($file . ".part_[0-9]+_[0-9]+"); + if ($l) { + spip_log("menage d'une sauvegarde inachevee: " . join(',', $l)); + foreach($l as $dummy) spip_unlink($dummy); + } + } + $all = count($tables); + return ($etape > $all OR !$all) ? false : $dir; +} + +function export_trace($val_meta, $dir, $meta) +{ + list($gz, $archive, $rub, $tables_for_dump, $etape_actuelle, $sous_etape, $serveur, $save) = $val_meta; + include_spip('inc/minipres'); + // pour permettre l'affichage au fur et a mesure + @ini_set("zlib.output_compression","0"); - if (!($timeout = ini_get('max_execution_time')*1000)); - $timeout = 30000; // parions sur une valeur tellement courante ... + if (!($timeout = ini_get('max_execution_time')*1000)); + $timeout = 30000; // parions sur une valeur tellement courante ... // le premier hit est moitie moins long car seulement une phase d'ecriture de morceaux // sans ramassage // sinon grosse ecriture au 1er hit, puis gros rammassage au deuxieme avec petite ecriture,... ca oscille - if ($start) $timeout = round($timeout/2); + if (!$etape_actuelle AND !$sous_etape) { + $timeout = round($timeout/2); + $tables_sauvegardees = array(); + } else { + $metatable = $meta . '_tables'; + $tables_sauvegardees = isset($GLOBALS['meta'][$metatable])?unserialize($GLOBALS['meta'][$metatable]):array(); + } // Les sauvegardes partielles prennent le temps d'indiquer les logos // Instancier une fois pour toutes, car on va boucler un max. // On complete jusqu'au secteur pour resituer dans l'arborescence) - if ($rub) { - $GLOBALS['chercher_logo'] = charger_fonction('chercher_logo', 'inc',true); - $les_rubriques = complete_fils(array($rub)); - $les_meres = complete_secteurs(array($rub)); - } else { - $GLOBALS['chercher_logo'] = false; - $les_rubriques = $les_meres = ''; - } + if ($rub) { + $GLOBALS['chercher_logo'] = charger_fonction('chercher_logo', 'inc',true); + $les_rubriques = complete_fils(array($rub), $serveur); + $les_meres = complete_secteurs(array($rub), $serveur); + } else { + $GLOBALS['chercher_logo'] = false; + $les_rubriques = $les_meres = ''; + } // script de rechargement auto sur timeout - $redirect = generer_url_ecrire("export_all"); - echo http_script("window.setTimeout('location.href=\"".$redirect."\";',$timeout)"); - - echo "
\n"; - $etape = 1; - foreach($tables_for_dump as $table){ - if ($etape_actuelle > $etape) { - // sauter les deja faits, mais rappeler qu'ils sont fait - echo ( "\n
".$etape. '. '."". $tables_sauvegardees[$table]); - } + $redirect = generer_url_ecrire("export_all"); + $all = count($tables_for_dump); + echo ( install_debut_html(_T('info_sauvegarde') . " ($all)")); + echo http_script("window.setTimeout('location.href=\"".$redirect."\";',$timeout)"); + + echo "
\n"; + $etape = 1; + foreach($tables_for_dump as $table){ + if ($etape_actuelle > $etape) { + // sauter les deja faits, mais rappeler qu'ils sont fait + echo ( "\n
".$etape. '. '."". $tables_sauvegardees[$table]); + } + else { + echo ( "\n
".$etape. '. '. $table." "); + $r = sql_countsel($table, array(), array(), array(), $serveur); + flush(); + if (!$r) $r = ( _T('texte_vide')); else { - echo ( "\n
".$etape. '. '. $table." "); - $r = sql_countsel($table); - flush(); - if (!$r) $r = ( _T('texte_vide')); - else { $f = $dir . $archive . '.part_' . sprintf('%03d',$etape); $r = export_objets($table, $sous_etape, $r, $f, $les_rubriques, $les_meres, $meta); $r += $sous_etape*_EXPORT_TRANCHES_LIMITE; // info pas fiable si interruption+partiel if ($rub AND $etape_actuelle > 1) $r = ">= $r"; - } - echo " $r"; - flush(); - $sous_etape = 0; - // on utilise l'index comme ca c'est pas grave si on ecrit plusieurs fois la meme - $tables_sauvegardees[$table] = "$table ($r)"; - ecrire_meta($metatable, serialize($tables_sauvegardees),'non'); } - $etape++; - $v = serialize(array($gz, $archive, $rub, $tables_for_dump, $etape,$sous_etape)); - ecrire_meta($meta, $v,'non'); + echo " $r"; + flush(); + $sous_etape = 0; + // on utilise l'index comme ca c'est pas grave si on ecrit plusieurs fois la meme + $tables_sauvegardees[$table] = "$table ($r)"; + ecrire_meta($meta . '_tables', serialize($tables_sauvegardees),'non'); } - echo ( "
\n"); - // si Javascript est dispo, anticiper le Time-out - echo ("\n"); - echo (install_fin_html()); - flush(); + $etape++; + $v = serialize(array($gz, $archive, $rub, $tables_for_dump, $etape,$sous_etape, $serveur, $save)); + ecrire_meta($meta, $v,'non'); } + echo ( "
\n"); + // si Javascript est dispo, anticiper le Time-out + echo ("\n"); + echo (install_fin_html()); + flush(); } - // http://doc.spip.org/@complete_secteurs -function complete_secteurs($les_rubriques) +function complete_secteurs($les_rubriques, $serveur='') { $res = array(); foreach($les_rubriques as $r) { do { - $r = sql_getfetsel("id_parent", "spip_rubriques", "id_rubrique=$r"); + $r = sql_getfetsel("id_parent", "spip_rubriques", "id_rubrique=$r", array(), array(), '', array(), $serveur); if ($r) { if ((isset($les_rubriques[$r])) OR isset($res[$r])) $r = false; @@ -138,13 +152,13 @@ function complete_secteurs($les_rubriques) } // http://doc.spip.org/@complete_fils -function complete_fils($rubriques) +function complete_fils($rubriques, $serveur='') { $r = $rubriques; do { - $q = sql_select("id_rubrique", "spip_rubriques", "id_parent IN (".join(',',$r).")"); + $q = sql_select("id_rubrique", "spip_rubriques", "id_parent IN (".join(',',$r).")", array(), array(), '', array(), $serveur); $r = array(); - while ($row = sql_fetch($q)) { + while ($row = sql_fetch($q, $serveur)) { $r[]= $rubriques[] = $row['id_rubrique']; } } while ($r); @@ -153,31 +167,6 @@ function complete_fils($rubriques) return $rubriques; } -// Concatenation des tranches -// Il faudrait ouvrir une seule fois le fichier, et d'abord sous un autre nom -// et sans detruire les tranches: au final renommage+destruction massive pour -// prevenir autant que possible un Time-out. - -// http://doc.spip.org/@ramasse_parties -function ramasse_parties($dir, $archive) -{ - $files = preg_files($dir . $archive . ".part_[0-9]+_[0-9]+[.gz]?"); - - $ok = true; - $files_o = array(); - $but = $dir . $archive; - foreach($files as $f) { - $contenu = ""; - if (lire_fichier ($f, $contenu)) { - if (!ecrire_fichier($but,$contenu,false,false)) - { $ok = false; break;} - } - spip_unlink($f); - $files_o[]=$f; - } - return $ok ? $files_o : false; -} - // // Exportation de table SQL au format xml // La constante ci-dessus determine la taille des tranches, @@ -203,33 +192,36 @@ function export_objets($table, $cpt, $total, $filetable, $les_rubriques, $les_me $debut = $cpt * _EXPORT_TRANCHES_LIMITE; $effectifs = 0; + $v = unserialize($GLOBALS['meta'][$meta]); while (1){ // on ne connait pas le nb de paquets d'avance $cpt++; - $tranche = build_while($debut, $table, $prim, $les_rubriques, $les_meres); + $tranche = build_while($debut, $table, $prim, $les_rubriques, $les_meres, $v[7], $v[6]); // attention: vide ne suffit pas a sortir // car les sauvegardes partielles peuvent parcourir // une table dont la portion qui les concerne sera vide.. if ($tranche) { // on ecrit dans un fichier generique // puis on le renomme pour avoir une operation atomique - ecrire_fichier ($temp, join('', $tranche)); - $f = $filetable . sprintf('_%04d',$cpt) . _EXTENSION_PARTIES; - // le fichier destination peut deja exister - // si on sort d'un timeout entre le rename et le ecrire_meta - if (file_exists($f)) spip_unlink($f); - rename($temp, $f); - $effectifs += count($tranche); + if (is_array($tranche)) { + ecrire_fichier ($temp, join('', $tranche)); + $f = $filetable . sprintf('_%04d',$cpt) . _EXTENSION_PARTIES; + // le fichier destination peut deja exister + // si on sort d'un timeout entre le rename et le ecrire_meta + if (file_exists($f)) spip_unlink($f); + rename($temp, $f); + $tranche = count($tranche); + } + $effectifs += $tranche; } // incrementer le numero de sous-etape // au cas ou une interruption interviendrait - $v = unserialize($GLOBALS['meta'][$meta]); $v[5]++; ecrire_meta($meta, serialize($v)); $debut += _EXPORT_TRANCHES_LIMITE; if ($debut >= $total) {break;} /* pour tester la robustesse de la reprise sur interruption - decommenter ce qui suit. + decommenter ce qui suit. if ($cpt && 1) { spip_log("force interrup $s"); include_spip('inc/headers'); @@ -238,50 +230,53 @@ function export_objets($table, $cpt, $total, $filetable, $les_rubriques, $les_me echo(". "); flush(); } - return $effectifs; } - -// Construit la version xml des champs d'une table - +// sauvegarde d'une table par ordre croissant de la cle primaire simple +// sinon les sequences PG seront pertubees a la restauration +// (a ameliorer) +// Retourne un tableau de chaines, d'autant d'element que de Row +// ou leur nombre, selon la fonction utilisee // http://doc.spip.org/@build_while -function build_while($debut, $table, $prim, $les_rubriques, $les_meres) { - global $chercher_logo ; +function build_while($debut, $table, $prim, $les_rubriques, $les_meres, $save='', $serveur='') { - // sauver par ordre croissant les tables avec cles primaires simples - // sinon les sequences PG seront pertubees a la restauration - // (a ameliorer) - $result = sql_select('*', $table, '', '', $prim, "$debut," . _EXPORT_TRANCHES_LIMITE); + $result = sql_select('*', $table, '', '', $prim, "$debut," . _EXPORT_TRANCHES_LIMITE, array(), $serveur); + $i = 0; $res = array(); - while ($row = sql_fetch($result)) { - if (export_select($row, $les_rubriques, $les_meres)) { - $attributs = ""; - if ($chercher_logo) { - if ($logo = $chercher_logo($row[$prim], $prim, 'on')) - $attributs .= ' on="' . $logo[3] . '"'; - if ($logo = $chercher_logo($row[$prim], $prim, 'off')) - $attributs .= ' off="' . $logo[3] . '"'; - } - - $string = "<$table$attributs>\n"; - foreach ($row as $k => $v) { - $string .= "<$k>" . text_to_xml($v) . "\n"; - } - $string .= "\n\n"; - $res[]= $string; + $save = 'inc_export_' . ($save ? $save : 'xml'); + while ($r = sql_fetch($result, $serveur)) { + if (export_select($r, $les_rubriques, $les_meres)) { + if ($s = $save($r, $table, $prim, $serveur)) $res[]=$s; else $i++; } } - sql_free($result); - return $res; + sql_free($result, $serveur); + return $res ? $res : $i; +} + +// Construit la version xml des champs d'une table +function inc_export_xml($row, $table, $prim, $serveur) { + global $chercher_logo ; + if ($chercher_logo) { + $on = $chercher_logo($row[$prim], $prim, 'on'); + $off = $chercher_logo($row[$prim], $prim, 'off'); + } else $on = $off = ""; + foreach ($row as $k => $v) { + $row[$k] = "<$k>" . text_to_xml($v) . ""; + } + return "<$table" + . ($on ? " on='$on[3]'" : '') + . ($off ? " off='$off[3]'" : '') + . ">\n" + . join("\n", $row) + . "\n\n\n"; } // dit si Row est exportable, // en particulier quand on se restreint a certaines rubriques -// Attention, la table articles doit etre au debut -// et la table document_articles avant la table documents -// (faudrait blinder, c'est un bug potentiel) +// La table des documents doit etre apres celle des liens de doc +// elle-meme apres celle des objets auxquels elle lie ces documents. // http://doc.spip.org/@export_select function export_select($row, $les_rubriques, $les_meres) { @@ -291,7 +286,7 @@ function export_select($row, $les_rubriques, $les_meres) { if (isset($row['impt']) AND $row['impt'] !='oui') return false; if (!$les_rubriques) return true; - // numero de rubrique non determinant pour les forums (0 � 99%) + // numero de rubrique non determinant pour les forums (0 a 99%) if (isset($row['id_rubrique']) AND $row['id_rubrique']) { if (in_array($row['id_rubrique'], $les_rubriques)) { if (isset($row['id_article'])) @@ -346,7 +341,9 @@ function export_select($row, $les_rubriques, $les_meres) { // Conversion texte -> xml (ajout d'entites) // http://doc.spip.org/@text_to_xml function text_to_xml($string) { - return str_replace(array('&','<','>'), array('&','<','>'), $string); + static $old = array('&','<','>'); + static $new = array('&','<','>'); + return str_replace($old, $new, $string); } ?>