dbc0da429a8365418f71c8c6c6159dfb202f5b07
3 /***************************************************************************\
4 * SPIP, Systeme de publication pour l'internet *
6 * Copyright (c) 2001-2016 *
7 * Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James *
9 * Ce programme est un logiciel libre distribue sous licence GNU/GPL. *
10 * Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne. *
11 \***************************************************************************/
14 * API permettant la manipulation des sauvegardes
16 * @package SPIP\Dump\API
19 if (!defined('_ECRIRE_INC_VERSION')) {
25 * Répertoire de sauvegarde
27 * Crée et retourne le chemin du répertoire de sauvegarde
33 function dump_repertoire() {
34 $repertoire = _DIR_DUMP
;
35 if (!@file_exists
($repertoire)
36 and !$repertoire = sous_repertoire(_DIR_DUMP
, '', false, true)
38 $repertoire = preg_replace(',' . _DIR_TMP
. ',', '', _DIR_DUMP
);
39 $repertoire = sous_repertoire(_DIR_TMP
, $repertoire);
47 * Nom du fichier de sauvegarde
49 * la fourniture de l'extension permet de vérifier que le nom n'existe pas déjà.
51 * @param string $dir Chemin de stockage du fichier
52 * @param string $extension Extension du fichier de sauvegarde
55 function dump_nom_fichier($dir, $extension = 'sqlite') {
56 include_spip('inc/texte');
58 if (isset($GLOBALS['meta']['nom_site'])) {
59 $site = typo($GLOBALS['meta']['nom_site']); // extraire_multi
60 $site = couper(translitteration(trim($site)), 30, '');
61 $site = preg_replace(array(',\W,is', ',_(?=_),', ',_$,'), array('_', '', ''), $site);
64 $site .= '_' . date('Ymd');
68 while (file_exists($dir . $nom . ".$extension")) {
69 $nom = $site . sprintf('_%03d', ++
$cpt);
72 return $nom . ".$extension";
76 * Détermine le type de serveur de sauvegarde,
81 function dump_type_serveur() {
83 // chercher si sqlite2 ou 3 est disponible
84 include_spip('req/sqlite3');
85 if (spip_versions_sqlite3()) {
89 include_spip('req/sqlite2');
90 if (spip_versions_sqlite2()) {
98 * Conteneur pour les arguments de la connexion
100 * Si on passe $args, les arguments de la connexion sont memorisés.
101 * Renvoie toujours les derniers arguments memorisés.
103 * @staticvar array $connect_args Pour stocker le premier conteneur
107 function dump_serveur($args = null) {
108 static $connect_args = null;
110 $connect_args = $args;
113 return $connect_args;
116 function dump_connect_args($archive) {
117 if (!$type_serveur = dump_type_serveur()) {
121 return array(dirname($archive), '', '', '', basename($archive, '.sqlite'), $type_serveur, 'spip');
125 * Initialiser un dump
127 * @param string $status_file Fichier contenant les informations serialisees sur le statut de l'export
128 * @param string $archive Nom de l'archive (stockee dans le fichier de statut)
129 * @param array $tables Liste des tables a exporter (autocaculee par defaut)
130 * @param array $where Condition sur l'export
131 * @param string $action Pour differencier la sauvegarde de l'import
132 * @return bool/string
134 function dump_init($status_file, $archive, $tables = null, $where = array(), $action = 'sauvegarde') {
135 $status_file = _DIR_TMP
. basename($status_file) . '.txt';
137 if (lire_fichier($status_file, $status)
138 and $status = unserialize($status)
139 and $status['etape'] !== 'fini'
140 and filemtime($status_file) >= time() - 120
142 // si le fichier status est trop vieux c'est un abandon
143 return _T('dump:erreur_' . $action . '_deja_en_cours');
146 if (!$type_serveur = dump_type_serveur()) {
147 return _T('dump:erreur_sqlite_indisponible');
151 list($tables, ) = base_liste_table_for_dump(lister_tables_noexport());
153 $status = array('tables' => $tables, 'where' => $where, 'archive' => $archive);
155 $status['connect'] = dump_connect_args($archive);
156 dump_serveur($status['connect']);
157 if (!spip_connect('dump')) {
158 return _T('dump:erreur_creation_base_sqlite');
161 // la constante sert a verifier qu'on utilise bien le connect/dump du plugin,
162 // et pas une base externe homonyme
163 if (!defined('_DUMP_SERVEUR_OK')) {
164 return _T('erreur_connect_dump', array('dump' => 'dump'));
167 $status['etape'] = 'init';
169 if (!ecrire_fichier($status_file, serialize($status))) {
170 return _T('dump:avis_probleme_ecriture_fichier', array('fichier' => $status_file));
177 * Afficher l'avancement de la copie
179 * @staticvar int $etape Nombre de fois ou on est passe dans cette foncion
180 * @param <type> $courant Flag pour indiquer si c'est la table sur laquelle on travaille actuellement
181 * @param <type> $total Nombre total de tables
182 * @param <type> $table Nom de la table
184 function dump_afficher_progres($courant, $total, $table) {
186 if (unique($table)) {
187 if ($total < 0 or !is_numeric($total)) {
188 echo '<br /><strong>' . $etape . '. ' . "</strong>$table ";
190 echo '<br /><strong>' . $etape . '. ' . "$table</strong> " . ($courant ?
" <i>($courant)</i> " : '');
194 if (is_numeric($total) and $total >= 0) {
197 echo '(' . (-intval($total)) . ')';
203 * Écrire le js pour relancer la procédure de dump
205 * @param string $redirect URL de la prochaine etape du dump
206 * @return string Code HTML de redirection
208 function dump_relance($redirect) {
209 // si Javascript est dispo, anticiper le Time-out
210 return "<script language=\"JavaScript\" type=\"text/javascript\">window.setTimeout('location.href=\"$redirect\";',300);</script>\n";
215 * Marquer la procédure de dump comme finie
217 * @param string $status_file
218 * Fichier qui mémorise les infos utiles concernant la sauvegarde en cours
219 * @param string $action
220 * Type d'action supplémentaire à réaliser :
222 * - restaurer : supprimer la structure qui était stockée dans le dump
223 * - 'auvegarder : stocker dans le dump la structure de la base source
225 function dump_end($status_file, $action = '') {
226 $status_file = _DIR_TMP
. basename($status_file) . '.txt';
227 if (!lire_fichier($status_file, $status)
228 or !$status = unserialize($status)
235 // supprimer la structure qui etait stockee dans le dump
236 sql_delete('spip_meta', "nom='dump_structure_temp'");
239 // stocker dans le dump la structure de la base source
240 $structure = array();
241 foreach ($status['tables_copiees'] as $t => $n) {
242 $structure[$t] = sql_showtable($t, true);
244 dump_serveur($status['connect']);
245 spip_connect('dump');
246 // si spip_meta n'a pas ete backup elle n'est pas dans le dump, il faut la creer pour y stocker cette meta
247 if (!sql_showtable('spip_meta', true, 'dump')) {
248 $desc = sql_showtable('spip_meta', true);
249 sql_create('spip_meta', $desc['field'], $desc['key'], false, false, 'dump');
251 sql_delete('spip_meta', "nom='dump_structure_temp'", 'dump'); #enlever une vieille structure deja la, au cas ou
254 array('nom' => 'dump_structure_temp', 'valeur' => serialize($structure), 'impt' => 'non'),
261 $status['etape'] = 'fini';
262 ecrire_fichier($status_file, serialize($status));
266 * Lister les fichiers de sauvegarde existant dans un repertoire
267 * trie par nom, date ou taille
269 * @param string $dir Repertoire de sauvegarde
270 * @param string $tri Tri pour recuperer les fichiers
271 * @param string $extension Extension des fichiers de sauvegarde
272 * @param int $limit Nombre max de fichiers listes
275 function dump_lister_sauvegardes($dir, $tri = 'nom', $extension = 'sqlite', $limit = 100) {
276 $liste_dump = preg_files($dir, '\.' . $extension . '$', $limit, false);
279 $tn = $tl = $tt = $td = array();
280 foreach ($liste_dump as $fichier) {
281 $d = filemtime($fichier);
282 $t = filesize($fichier);
283 $fichier = substr($fichier, $n);
284 $tl[] = array('fichier' => $fichier, 'taille' => $t, 'date' => $d);
289 if ($tri == 'taille') {
290 array_multisort($tt, SORT_ASC
, $tl);
291 } elseif ($tri == 'date') {
292 array_multisort($td, SORT_ASC
, $tl);
294 array_multisort($tn, SORT_ASC
, $tl);
301 * Extraire le statut contenu dans un fichier
303 * @param $status_file Nom du fichier stocke dans _DIR_TMP
306 function dump_lire_status($status_file) {
307 $status_file = _DIR_TMP
. basename($status_file) . '.txt';
308 if (!lire_fichier($status_file, $status)
309 or !$status = unserialize($status)
318 * Verifier qu'un sauvegarde est finie
320 * @param $status_file Nom du fichier stocke dans _DIR_TMP
321 * @return string Chaine non vide s'il reste des choses a faire
323 function dump_verifie_sauvegarde_finie($status_file) {
324 if (!$status = dump_lire_status($status_file)
325 or $status['etape'] !== 'fini'
334 * Recuperer le nom du fichier d'archivage qui est memorise dans le fichier de statut
336 * @param $status_file Nom du fichier stocke dans _DIR_TMP
337 * @return string Nom ou chaine vide si on a un probleme
339 function dump_nom_sauvegarde($status_file) {
340 if (!$status = dump_lire_status($status_file)
341 or !file_exists($f = $status['archive'] . '.sqlite')
350 * Recuperer la taille du fichier de sauvegarde
352 * @param $status_file Nom du fichier stocke dans _DIR_TMP
353 * @return string/int Taille ou Chaine vide en cas de probleme
355 function dump_taille_sauvegarde($status_file) {
356 if (!$f = dump_nom_sauvegarde($status_file)
357 or !$s = filesize($f)
366 * Recuperer la date de derniere modification du fichier de sauvegarde
368 * @param $status_file Nom du fichier stocke dans _DIR_TMP
369 * @return string/int Date ou Chaine vide en cas de probleme
371 function dump_date_sauvegarde($status_file) {
372 if (!$f = dump_nom_sauvegarde($status_file)
373 or !$d = filemtime($f)
378 return date('Y-m-d', $d);