|
1
|
|
|
<?php |
|
2
|
|
|
|
|
3
|
|
|
/***************************************************************************\ |
|
4
|
|
|
* SPIP, Systeme de publication pour l'internet * |
|
5
|
|
|
* * |
|
6
|
|
|
* Copyright (c) 2001-2016 * |
|
7
|
|
|
* Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James * |
|
8
|
|
|
* * |
|
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
|
|
|
\***************************************************************************/ |
|
12
|
|
|
|
|
13
|
|
|
/** |
|
14
|
|
|
* |
|
15
|
|
|
* Fonctions de base pour la sauvegarde |
|
16
|
|
|
* Boite a outil commune, sans prejuger de la methode de sauvegarde |
|
17
|
|
|
* |
|
18
|
|
|
*/ |
|
19
|
|
|
|
|
20
|
|
|
if (!defined('_ECRIRE_INC_VERSION')) return; |
|
21
|
|
|
|
|
22
|
|
|
define('_VERSION_ARCHIVE', '1.3'); |
|
23
|
|
|
|
|
24
|
|
|
include_spip('base/serial'); |
|
25
|
|
|
include_spip('base/auxiliaires'); |
|
26
|
|
|
include_spip('public/interfaces'); // pour table_jointures |
|
27
|
|
|
|
|
28
|
|
|
// NB: Ce fichier peut ajouter des tables (old-style) |
|
29
|
|
|
// donc il faut l'inclure "en globals" |
|
30
|
|
|
if ($f = find_in_path('mes_fonctions.php')) { |
|
31
|
|
|
global $dossier_squelettes; |
|
32
|
|
|
@include_once (_ROOT_CWD . $f); |
|
|
|
|
|
|
33
|
|
|
} |
|
34
|
|
|
|
|
35
|
|
|
if (@is_readable(_CACHE_PLUGINS_FCT)){ |
|
36
|
|
|
// chargement optimise precompile |
|
37
|
|
|
include_once(_CACHE_PLUGINS_FCT); |
|
38
|
|
|
} |
|
39
|
|
|
|
|
40
|
|
|
function base_dump_meta_name($rub){ |
|
41
|
|
|
return $meta = "status_dump_{$rub}_" . abs($GLOBALS['visiteur_session']['id_auteur']); |
|
|
|
|
|
|
42
|
|
|
} |
|
43
|
|
|
function base_dump_dir($meta){ |
|
44
|
|
|
include_spip('inc/documents'); |
|
45
|
|
|
// determine upload va aussi initialiser l'index "restreint" |
|
46
|
|
|
$maindir = determine_upload(); |
|
47
|
|
|
if (!$GLOBALS['visiteur_session']['restreint']) |
|
48
|
|
|
$maindir = _DIR_DUMP; |
|
49
|
|
|
$dir = sous_repertoire($maindir, $meta); |
|
50
|
|
|
return $dir; |
|
51
|
|
|
} |
|
52
|
|
|
|
|
53
|
|
|
/** |
|
54
|
|
|
* Lister toutes les tables d'un serveur |
|
55
|
|
|
* en excluant eventuellement une liste fournie |
|
56
|
|
|
* |
|
57
|
|
|
* @param string $serveur |
|
58
|
|
|
* @param array $tables |
|
59
|
|
|
* @param array $exclude |
|
60
|
|
|
* @param bool $affiche_vrai_prefixe |
|
61
|
|
|
* @return array |
|
62
|
|
|
*/ |
|
63
|
|
|
function base_lister_toutes_tables($serveur='', $tables=array(), $exclude = array(),$affiche_vrai_prefixe=false) { |
|
64
|
|
|
spip_connect($serveur); |
|
65
|
|
|
$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0]; |
|
66
|
|
|
$prefixe = $connexion['prefixe']; |
|
67
|
|
|
|
|
68
|
|
|
$p = '/^' . $prefixe . '/'; |
|
69
|
|
|
$res = $tables; |
|
70
|
|
|
foreach(sql_alltable(null,$serveur) as $t) { |
|
71
|
|
|
if (preg_match($p, $t)) { |
|
72
|
|
|
$t1 = preg_replace($p, 'spip', $t); |
|
73
|
|
|
if (!in_array($t1, $tables) AND !in_array($t1, $exclude)) |
|
74
|
|
|
$res[]= ($affiche_vrai_prefixe?$t:$t1); |
|
75
|
|
|
} |
|
76
|
|
|
} |
|
77
|
|
|
sort($res); |
|
78
|
|
|
return $res; |
|
79
|
|
|
} |
|
80
|
|
|
|
|
81
|
|
|
/** |
|
82
|
|
|
* Retrouver le prefixe des tables |
|
83
|
|
|
* @param string $serveur |
|
84
|
|
|
* @return string |
|
85
|
|
|
*/ |
|
86
|
|
|
function base_prefixe_tables($serveur=''){ |
|
87
|
|
|
spip_connect($serveur); |
|
88
|
|
|
$connexion = $GLOBALS['connexions'][$serveur ? $serveur : 0]; |
|
89
|
|
|
$prefixe = $connexion['prefixe']; |
|
90
|
|
|
return $prefixe; |
|
91
|
|
|
} |
|
92
|
|
|
|
|
93
|
|
|
|
|
94
|
|
|
/** |
|
95
|
|
|
* Fabrique la liste a cocher des tables a traiter (copie, delete, sauvegarde) |
|
96
|
|
|
* |
|
97
|
|
|
* @param string $name |
|
98
|
|
|
* @param array $tables |
|
99
|
|
|
* @param array $exclude |
|
100
|
|
|
* @param array|null $post |
|
101
|
|
|
* @param string $serveur |
|
102
|
|
|
* @return array |
|
103
|
|
|
*/ |
|
104
|
|
|
function base_saisie_tables($name, $tables, $exclude = array(), $post=null, $serveur='') { |
|
105
|
|
|
include_spip('inc/filtres'); |
|
106
|
|
|
$res = array(); |
|
107
|
|
|
foreach ($tables as $k => $t) { |
|
108
|
|
|
// par defaut tout est coche sauf les tables dans $exclude |
|
109
|
|
|
if (is_null($post)) |
|
110
|
|
|
$check = (in_array($t,$exclude)?false:true); |
|
111
|
|
|
// mais si on a poste une selection, la reprendre |
|
112
|
|
|
else |
|
113
|
|
|
$check = in_array($t,$post); |
|
114
|
|
|
|
|
115
|
|
|
$res[$k] = "<input type='checkbox' value='$t' name='$name" |
|
116
|
|
|
. "[]' id='$name$k'" |
|
117
|
|
|
. ($check ? " checked='checked'" : '') |
|
118
|
|
|
. "/>\n" |
|
119
|
|
|
. "<label for='$name$k'>".$t."</label>" |
|
120
|
|
|
. " (" |
|
121
|
|
|
. sinon(singulier_ou_pluriel(sql_countsel($t,'','','',$serveur), 'dump:une_donnee', 'dump:nb_donnees'),_T('dump:aucune_donnee')) |
|
|
|
|
|
|
122
|
|
|
. ")"; |
|
123
|
|
|
} |
|
124
|
|
|
return $res; |
|
125
|
|
|
} |
|
126
|
|
|
|
|
127
|
|
|
|
|
128
|
|
|
/** |
|
129
|
|
|
* Lister les tables non exportables par defaut |
|
130
|
|
|
* (liste completable par le pipeline lister_tables_noexport |
|
131
|
|
|
* |
|
132
|
|
|
* @staticvar array $EXPORT_tables_noexport |
|
133
|
|
|
* @return array |
|
134
|
|
|
*/ |
|
135
|
|
|
function lister_tables_noexport(){ |
|
136
|
|
|
// par defaut tout est exporte sauf les tables ci-dessous |
|
137
|
|
|
static $EXPORT_tables_noexport = null; |
|
138
|
|
|
if (!is_null($EXPORT_tables_noexport)) |
|
139
|
|
|
return $EXPORT_tables_noexport; |
|
140
|
|
|
|
|
141
|
|
|
$EXPORT_tables_noexport= array( |
|
142
|
|
|
'spip_caches', // plugin invalideur |
|
143
|
|
|
'spip_resultats', // resultats de recherche ... c'est un cache ! |
|
144
|
|
|
'spip_test', // c'est un test ! |
|
145
|
|
|
#'spip_referers', |
|
146
|
|
|
#'spip_referers_articles', |
|
147
|
|
|
#'spip_visites', |
|
148
|
|
|
#'spip_visites_articles', |
|
149
|
|
|
#'spip_versions', |
|
150
|
|
|
#'spip_versions_fragments' |
|
151
|
|
|
); |
|
152
|
|
|
|
|
153
|
|
|
$EXPORT_tables_noexport = pipeline('lister_tables_noexport',$EXPORT_tables_noexport); |
|
154
|
|
|
return $EXPORT_tables_noexport; |
|
155
|
|
|
} |
|
156
|
|
|
|
|
157
|
|
|
/** |
|
158
|
|
|
* Lister les tables non importables par defaut |
|
159
|
|
|
* (liste completable par le pipeline lister_tables_noimport |
|
160
|
|
|
* |
|
161
|
|
|
* @staticvar array $IMPORT_tables_noimport |
|
162
|
|
|
* @return array |
|
163
|
|
|
*/ |
|
164
|
|
|
function lister_tables_noimport(){ |
|
165
|
|
|
static $IMPORT_tables_noimport=null; |
|
166
|
|
|
if (!is_null($IMPORT_tables_noimport)) |
|
167
|
|
|
return $IMPORT_tables_noimport; |
|
168
|
|
|
|
|
169
|
|
|
$IMPORT_tables_noimport = array(); |
|
170
|
|
|
// par defaut tout est importe sauf les tables ci-dessous |
|
171
|
|
|
// possibiliter de definir cela tables via la meta |
|
172
|
|
|
// compatibilite |
|
173
|
|
View Code Duplication |
if (isset($GLOBALS['meta']['IMPORT_tables_noimport'])){ |
|
|
|
|
|
|
174
|
|
|
$IMPORT_tables_noimport = unserialize($GLOBALS['meta']['IMPORT_tables_noimport']); |
|
175
|
|
|
if (!is_array($IMPORT_tables_noimport)){ |
|
176
|
|
|
include_spip('inc/meta'); |
|
177
|
|
|
effacer_meta('IMPORT_tables_noimport'); |
|
178
|
|
|
} |
|
179
|
|
|
} |
|
180
|
|
|
$IMPORT_tables_noimport = pipeline('lister_tables_noimport',$IMPORT_tables_noimport); |
|
181
|
|
|
return $IMPORT_tables_noimport; |
|
182
|
|
|
} |
|
183
|
|
|
|
|
184
|
|
|
|
|
185
|
|
|
/** |
|
186
|
|
|
* Lister les tables a ne pas effacer |
|
187
|
|
|
* (liste completable par le pipeline lister_tables_noerase |
|
188
|
|
|
* |
|
189
|
|
|
* @staticvar array $IMPORT_tables_noerase |
|
190
|
|
|
* @return array |
|
191
|
|
|
*/ |
|
192
|
|
|
function lister_tables_noerase(){ |
|
193
|
|
|
static $IMPORT_tables_noerase=null; |
|
194
|
|
|
if (!is_null($IMPORT_tables_noerase)) |
|
195
|
|
|
return $IMPORT_tables_noerase; |
|
196
|
|
|
|
|
197
|
|
|
$IMPORT_tables_noerase = array( |
|
198
|
|
|
'spip_meta', |
|
199
|
|
|
// par defaut on ne vide pas les stats, car elles ne figurent pas dans les dump |
|
200
|
|
|
// et le cas echeant, un bouton dans l'admin permet de les vider a la main... |
|
201
|
|
|
'spip_referers', |
|
202
|
|
|
'spip_referers_articles', |
|
203
|
|
|
'spip_visites', |
|
204
|
|
|
'spip_visites_articles' |
|
205
|
|
|
); |
|
206
|
|
|
$IMPORT_tables_noerase = pipeline('lister_tables_noerase',$IMPORT_tables_noerase); |
|
207
|
|
|
return $IMPORT_tables_noerase; |
|
208
|
|
|
} |
|
209
|
|
|
|
|
210
|
|
|
|
|
211
|
|
|
/** |
|
212
|
|
|
* construction de la liste des tables pour le dump : |
|
213
|
|
|
* toutes les tables principales |
|
214
|
|
|
* + toutes les tables auxiliaires hors relations |
|
215
|
|
|
* + les tables relations dont les deux tables liees sont dans la liste |
|
216
|
|
|
* |
|
217
|
|
|
* @param array $exclude_tables |
|
218
|
|
|
* @return array |
|
|
|
|
|
|
219
|
|
|
*/ |
|
220
|
|
|
function base_liste_table_for_dump($exclude_tables = array()){ |
|
221
|
|
|
$tables_for_dump = array(); |
|
222
|
|
|
$tables_pointees = array(); |
|
223
|
|
|
$tables = array(); |
|
224
|
|
|
$tables_principales = $GLOBALS['tables_principales']; |
|
225
|
|
|
$tables_auxiliaires = $GLOBALS['tables_auxiliaires']; |
|
226
|
|
|
$tables_jointures = $GLOBALS['tables_jointures']; |
|
227
|
|
|
|
|
228
|
|
|
if (include_spip('base/objets') |
|
229
|
|
|
AND function_exists('lister_tables_objets_sql')){ |
|
230
|
|
|
$tables = lister_tables_objets_sql(); |
|
231
|
|
|
foreach($tables as $t=>$infos){ |
|
|
|
|
|
|
232
|
|
View Code Duplication |
if ($infos['principale'] AND !isset($tables_principales[$t])) |
|
|
|
|
|
|
233
|
|
|
$tables_principales[$t] = true; |
|
234
|
|
View Code Duplication |
if (!$infos['principale'] AND !isset($tables_auxiliaires[$t])) |
|
|
|
|
|
|
235
|
|
|
$tables_auxiliaires[$t] = true; |
|
236
|
|
|
if (count($infos['tables_jointures'])) |
|
237
|
|
|
$tables_jointures[$t] = array_merge(isset($tables_jointures[$t])?$tables_jointures[$t]:array(),$infos['tables_jointures']); |
|
238
|
|
|
} |
|
239
|
|
|
} |
|
240
|
|
|
|
|
241
|
|
|
// on construit un index des tables de liens |
|
242
|
|
|
// pour les ajouter SI les deux tables qu'ils connectent sont sauvegardees |
|
243
|
|
|
$tables_for_link = array(); |
|
244
|
|
|
foreach($tables_jointures as $table => $liste_relations) |
|
245
|
|
|
if (is_array($liste_relations)) |
|
246
|
|
|
{ |
|
247
|
|
|
$nom = $table; |
|
248
|
|
|
if (!isset($tables_auxiliaires[$nom])&&!isset($tables_principales[$nom])) |
|
249
|
|
|
$nom = "spip_$table"; |
|
250
|
|
|
if (isset($tables_auxiliaires[$nom])||isset($tables_principales[$nom])){ |
|
251
|
|
|
foreach($liste_relations as $link_table){ |
|
252
|
|
|
if (isset($tables_auxiliaires[$link_table])/*||isset($tables_principales[$link_table])*/){ |
|
253
|
|
|
$tables_for_link[$link_table][] = $nom; |
|
254
|
|
|
} |
|
255
|
|
|
else if (isset($tables_auxiliaires["spip_$link_table"])/*||isset($tables_principales["spip_$link_table"])*/){ |
|
256
|
|
|
$tables_for_link["spip_$link_table"][] = $nom; |
|
257
|
|
|
} |
|
258
|
|
|
} |
|
259
|
|
|
} |
|
260
|
|
|
} |
|
261
|
|
|
|
|
262
|
|
|
$liste_tables = array_merge(array_keys($tables_principales),array_keys($tables_auxiliaires),array_keys($tables)); |
|
263
|
|
|
foreach($liste_tables as $table){ |
|
264
|
|
|
// $name = preg_replace("{^spip_}","",$table); |
|
265
|
|
|
if ( !isset($tables_pointees[$table]) |
|
266
|
|
|
&& !in_array($table,$exclude_tables) |
|
267
|
|
|
&& !isset($tables_for_link[$table])){ |
|
268
|
|
|
$tables_for_dump[] = $table; |
|
269
|
|
|
$tables_pointees[$table] = 1; |
|
270
|
|
|
} |
|
271
|
|
|
} |
|
272
|
|
|
foreach ($tables_for_link as $link_table =>$liste){ |
|
273
|
|
|
$connecte = true; |
|
274
|
|
|
foreach($liste as $connect_table) |
|
275
|
|
|
if (!in_array($connect_table,$tables_for_dump)) |
|
276
|
|
|
$connecte = false; |
|
277
|
|
|
if ($connecte) |
|
278
|
|
|
# on ajoute les liaisons en premier |
|
279
|
|
|
# si une restauration est interrompue, |
|
280
|
|
|
# cela se verra mieux si il manque des objets |
|
281
|
|
|
# que des liens |
|
282
|
|
|
array_unshift($tables_for_dump,$link_table); |
|
283
|
|
|
} |
|
284
|
|
|
return array($tables_for_dump, $tables_for_link); |
|
285
|
|
|
} |
|
286
|
|
|
|
|
287
|
|
|
/** |
|
288
|
|
|
* Vider les tables de la base de destination |
|
289
|
|
|
* pour la copie dans une base |
|
290
|
|
|
* |
|
291
|
|
|
* peut etre utilise pour l'import depuis xml, |
|
292
|
|
|
* ou la copie de base a base (mysql<->sqlite par exemple) |
|
293
|
|
|
* |
|
294
|
|
|
* @param array $tables |
|
295
|
|
|
* @param array $exclure_tables |
|
296
|
|
|
* @param string $serveur |
|
297
|
|
|
*/ |
|
298
|
|
|
function base_vider_tables_destination_copie($tables, $exclure_tables = array(), $serveur=''){ |
|
299
|
|
|
$trouver_table = charger_fonction('trouver_table', 'base'); |
|
300
|
|
|
|
|
301
|
|
|
spip_log('Vider '.count($tables) . " tables sur serveur '$serveur' : " . join(', ', $tables),'base.'._LOG_INFO_IMPORTANTE); |
|
302
|
|
|
foreach($tables as $table){ |
|
303
|
|
|
if (!in_array($table,$exclure_tables)){ |
|
304
|
|
|
// sur le serveur principal, il ne faut pas supprimer l'auteur loge ! |
|
305
|
|
|
if (($table!='spip_auteurs') OR $serveur!=''){ |
|
306
|
|
|
// regarder si il y a au moins un champ impt='non' |
|
307
|
|
|
$desc = $trouver_table($table,$serveur); |
|
308
|
|
|
if (isset($desc['field']['impt'])){ |
|
309
|
|
|
sql_delete($table, "impt='oui'", $serveur); |
|
310
|
|
|
} |
|
311
|
|
|
else{ |
|
312
|
|
|
sql_delete($table, "", $serveur); |
|
313
|
|
|
} |
|
314
|
|
|
} |
|
315
|
|
|
} |
|
316
|
|
|
} |
|
317
|
|
|
|
|
318
|
|
|
// sur le serveur principal, il ne faut pas supprimer l'auteur loge ! |
|
319
|
|
|
// Bidouille pour garder l'acces admin actuel pendant toute la restauration |
|
320
|
|
|
if ($serveur=='' |
|
321
|
|
|
AND in_array('spip_auteurs',$tables) |
|
322
|
|
|
AND !in_array('spip_auteurs',$exclure_tables)) { |
|
323
|
|
|
base_conserver_copieur(true, $serveur); |
|
324
|
|
|
sql_delete("spip_auteurs", "id_auteur>0",$serveur); |
|
325
|
|
|
} |
|
326
|
|
|
} |
|
327
|
|
|
|
|
328
|
|
|
/** |
|
329
|
|
|
* Conserver le copieur si besoin |
|
330
|
|
|
* @param bool $move |
|
331
|
|
|
* @param string $serveur |
|
332
|
|
|
* @return void |
|
333
|
|
|
*/ |
|
334
|
|
|
function base_conserver_copieur($move = true,$serveur=''){ |
|
335
|
|
|
// s'asurer qu'on a pas deja fait la manip ! |
|
336
|
|
|
if ($GLOBALS['visiteur_session']['id_auteur']>0 AND sql_countsel("spip_auteurs", "id_auteur>0")) { |
|
337
|
|
|
spip_log('Conserver copieur '.$GLOBALS['visiteur_statut']['id_auteur'] . " dans id_auteur=".$GLOBALS['visiteur_statut']['id_auteur']." pour le serveur '$serveur'",'dump.'._LOG_INFO_IMPORTANTE); |
|
338
|
|
|
sql_delete("spip_auteurs", "id_auteur<0",$serveur); |
|
339
|
|
|
if ($move){ |
|
340
|
|
|
sql_updateq('spip_auteurs', array('id_auteur'=>-$GLOBALS['visiteur_session']['id_auteur']), "id_auteur=".intval($GLOBALS['visiteur_session']['id_auteur']),array(),$serveur); |
|
341
|
|
|
} |
|
342
|
|
|
else { |
|
343
|
|
|
$row = sql_fetsel('*','spip_auteurs','id_auteur='.$GLOBALS['visiteur_session']['id_auteur'],'','','','',$serveur); |
|
344
|
|
|
$row['id_auteur'] = -$GLOBALS['visiteur_session']['id_auteur']; |
|
345
|
|
|
sql_insertq('spip_auteurs',$row,array(),$serveur); |
|
346
|
|
|
} |
|
347
|
|
|
} |
|
348
|
|
|
} |
|
349
|
|
|
|
|
350
|
|
|
/** |
|
351
|
|
|
* Effacement de la bidouille ci-dessus |
|
352
|
|
|
* Toutefois si la table des auteurs ne contient plus qu'elle |
|
353
|
|
|
* c'est que la copie etait incomplete et on restaure le compte |
|
354
|
|
|
* pour garder la connection au site |
|
355
|
|
|
* |
|
356
|
|
|
* (mais il doit pas etre bien beau |
|
357
|
|
|
* et ca ne marche que si l'id_auteur est sur moins de 3 chiffres) |
|
358
|
|
|
* |
|
359
|
|
|
* @param string $serveur |
|
360
|
|
|
*/ |
|
361
|
|
|
function base_detruire_copieur_si_besoin($serveur='') |
|
362
|
|
|
{ |
|
363
|
|
|
// rien a faire si ce n'est pas le serveur principal ! |
|
364
|
|
|
if ($serveur=='') { |
|
365
|
|
|
if (sql_countsel("spip_auteurs", "id_auteur>0")) { |
|
366
|
|
|
spip_log("Detruire copieur id_auteur<0 pour le serveur '$serveur'",'dump.'._LOG_INFO_IMPORTANTE); |
|
367
|
|
|
sql_delete("spip_auteurs", "id_auteur<0", $serveur); |
|
368
|
|
|
} |
|
369
|
|
|
else { |
|
370
|
|
|
spip_log( "Restaurer copieur id_auteur<0 pour le serveur '$serveur' (aucun autre auteur en base)",'dump.'._LOG_INFO_IMPORTANTE); |
|
371
|
|
|
sql_update('spip_auteurs', array('id_auteur'=>'-id_auteur'), "id_auteur<0"); |
|
372
|
|
|
} |
|
373
|
|
|
} |
|
374
|
|
|
else |
|
375
|
|
|
spip_log("Pas de destruction copieur sur serveur '$serveur'",'dump.'._LOG_INFO_IMPORTANTE); |
|
376
|
|
|
} |
|
377
|
|
|
|
|
378
|
|
|
/** |
|
379
|
|
|
* Preparer la table dans la base de destination : |
|
380
|
|
|
* la droper si elle existe (sauf si auteurs ou meta sur le serveur principal) |
|
381
|
|
|
* la creer si necessaire, ou ajouter simplement les champs manquants |
|
382
|
|
|
* |
|
383
|
|
|
* @param string $table |
|
384
|
|
|
* @param array $desc |
|
385
|
|
|
* @param string $serveur_dest |
|
386
|
|
|
* @param bool $init |
|
387
|
|
|
* @return array |
|
388
|
|
|
*/ |
|
389
|
|
|
function base_preparer_table_dest($table, $desc, $serveur_dest, $init=false) { |
|
390
|
|
|
$upgrade = false; |
|
391
|
|
|
// si la table existe et qu'on est a l'init, la dropper |
|
392
|
|
|
if ($desc_dest=sql_showtable($table,true,$serveur_dest) AND $init) { |
|
393
|
|
|
if ($serveur_dest=='' AND in_array($table,array('spip_meta','spip_auteurs'))) { |
|
394
|
|
|
// ne pas dropper auteurs et meta sur le serveur principal |
|
395
|
|
|
// faire un simple upgrade a la place |
|
396
|
|
|
// pour ajouter les champs manquants |
|
397
|
|
|
$upgrade = true; |
|
398
|
|
|
// coherence avec le drop sur les autres tables |
|
399
|
|
|
base_vider_tables_destination_copie(array($table),array(),$serveur_dest); |
|
400
|
|
|
if ($table=='spip_meta'){ |
|
401
|
|
|
// virer les version base qui vont venir avec l'import |
|
402
|
|
|
sql_delete($table, "nom like '%_base_version'",$serveur_dest); |
|
403
|
|
|
// hum casse la base si pas version_installee a l'import ... |
|
404
|
|
|
sql_delete($table, "nom='version_installee'",$serveur_dest); |
|
405
|
|
|
} |
|
406
|
|
|
} |
|
407
|
|
|
else { |
|
408
|
|
|
sql_drop_table($table, '', $serveur_dest); |
|
409
|
|
|
spip_log( "drop table '$table' sur serveur '$serveur_dest'",'dump.'._LOG_INFO_IMPORTANTE); |
|
410
|
|
|
} |
|
411
|
|
|
$desc_dest = false; |
|
412
|
|
|
} |
|
413
|
|
|
// si la table n'existe pas dans la destination, la creer a l'identique ! |
|
414
|
|
|
if (!$desc_dest) { |
|
415
|
|
|
spip_log( "creation '$table' sur serveur '$serveur_dest'",'dump.'._LOG_INFO_IMPORTANTE); |
|
416
|
|
|
include_spip('base/create'); |
|
417
|
|
|
creer_ou_upgrader_table($table, $desc, 'auto', $upgrade,$serveur_dest); |
|
418
|
|
|
$desc_dest = sql_showtable($table,true,$serveur_dest); |
|
419
|
|
|
} |
|
420
|
|
|
if (!$desc_dest){ |
|
421
|
|
|
spip_log( "Erreur creation '$table' sur serveur '$serveur_dest'".var_export($desc,1),'dump.'._LOG_ERREUR); |
|
422
|
|
|
} |
|
423
|
|
|
|
|
424
|
|
|
return $desc_dest; |
|
425
|
|
|
} |
|
426
|
|
|
|
|
427
|
|
|
/** |
|
428
|
|
|
* Copier de base a base |
|
429
|
|
|
* |
|
430
|
|
|
* @param string $status_file |
|
431
|
|
|
* nom avec chemin complet du fichier ou est stocke le status courant |
|
432
|
|
|
* @param array $tables |
|
433
|
|
|
* liste des tables a copier |
|
434
|
|
|
* @param string $serveur_source |
|
435
|
|
|
* @param string $serveur_dest |
|
436
|
|
|
* @param array $options |
|
437
|
|
|
* parametres optionnels sous forme de tableau : |
|
438
|
|
|
* param string $callback_progression |
|
439
|
|
|
* fonction a appeler pour afficher la progression, avec les arguments (compteur,total,table) |
|
440
|
|
|
* param int $max_time |
|
441
|
|
|
* limite de temps au dela de laquelle sortir de la fonction proprement (de la forme time()+15) |
|
442
|
|
|
* param bool $drop_source |
|
443
|
|
|
* vider les tables sources apres copie |
|
444
|
|
|
* param array $no_erase_dest |
|
445
|
|
|
* liste des tables a ne pas vider systematiquement (ne seront videes que si existent dans la base source) |
|
446
|
|
|
* param array $where |
|
447
|
|
|
* liste optionnelle de condition where de selection des donnees pour chaque table |
|
448
|
|
|
* param string $racine_fonctions_dest |
|
449
|
|
|
* racine utilisee pour charger_fonction() des operations elementaires sur la base de destination. |
|
450
|
|
|
* Permet de deleguer vers une autre voie de communication. |
|
451
|
|
|
* Par defaut on utilise 'base', ce qui route vers les fonctions de ce fichier. Concerne : |
|
452
|
|
|
* - vider_tables_destination_copie |
|
453
|
|
|
* - preparer_table_dest |
|
454
|
|
|
* - detruire_copieur_si_besoin |
|
455
|
|
|
* - inserer_copie |
|
456
|
|
|
* param array $fonction_base_inserer |
|
457
|
|
|
* fonction d'insertion en base. Par defaut "inserer_copie" qui fait un insertq a l'identique. |
|
458
|
|
|
* Attention, la fonction appelee est prefixee par $racine_fonctions_dest via un charger_fonction() |
|
459
|
|
|
* Peut etre personalisee pour filtrer, renumeroter.... |
|
460
|
|
|
* param array $desc_tables_dest |
|
461
|
|
|
* description des tables de destination a utiliser de preference a la description de la table source |
|
462
|
|
|
* param int data_pool |
|
463
|
|
|
* nombre de ko de donnees a envoyer d'un coup en insertion dans la table cible (par defaut 1) |
|
464
|
|
|
* permet des envois groupes pour plus de rapidite, notamment si l'insertion est distante |
|
465
|
|
|
* |
|
466
|
|
|
* @return bool |
|
467
|
|
|
*/ |
|
468
|
|
|
function base_copier_tables($status_file, $tables, $serveur_source, $serveur_dest, $options=array()){ |
|
469
|
|
|
|
|
470
|
|
|
$callback_progression = isset($options['callback_progression'])?$options['callback_progression']:''; |
|
471
|
|
|
$max_time = isset($options['max_time'])?$options['max_time']:0; |
|
472
|
|
|
$drop_source = isset($options['drop_source'])?$options['drop_source']:false; |
|
473
|
|
|
$no_erase_dest = isset($options['no_erase_dest'])?$options['no_erase_dest']:array(); |
|
474
|
|
|
$where = isset($options['where'])?$options['where']:array(); |
|
475
|
|
|
$fonction_base_inserer = isset($options['fonction_base_inserer'])?$options['fonction_base_inserer']:'inserer_copie'; |
|
476
|
|
|
$desc_tables_dest = isset($options['desc_tables_dest'])?$options['desc_tables_dest']:array(); |
|
477
|
|
|
$racine_fonctions = (isset($options['racine_fonctions_dest'])?$options['racine_fonctions_dest']:'base'); |
|
478
|
|
|
$data_pool = (isset($options['data_pool'])?$options['data_pool']:50*1024); |
|
479
|
|
|
|
|
480
|
|
|
spip_log( "Copier ".count($tables)." tables de '$serveur_source' vers '$serveur_dest'",'dump.'._LOG_INFO_IMPORTANTE); |
|
481
|
|
|
|
|
482
|
|
View Code Duplication |
if (!$inserer_copie = charger_fonction($fonction_base_inserer,$racine_fonctions, true)) { |
|
|
|
|
|
|
483
|
|
|
spip_log( "Fonction '{$racine_fonctions}_$fonction_base_inserer' inconnue. Abandon",'dump.'._LOG_INFO_IMPORTANTE); |
|
484
|
|
|
return true; // echec mais on a fini, donc true |
|
485
|
|
|
} |
|
486
|
|
View Code Duplication |
if (!$preparer_table_dest = charger_fonction('preparer_table_dest',$racine_fonctions, true)) { |
|
|
|
|
|
|
487
|
|
|
spip_log( "Fonction '{$racine_fonctions}_$preparer_table_dest' inconnue. Abandon",'dump.'._LOG_INFO_IMPORTANTE); |
|
488
|
|
|
return true; // echec mais on a fini, donc true |
|
489
|
|
|
} |
|
490
|
|
|
|
|
491
|
|
|
if (!lire_fichier($status_file, $status) |
|
492
|
|
|
OR !$status = unserialize($status)) |
|
493
|
|
|
$status = array(); |
|
494
|
|
|
$status['etape'] = 'basecopie'; |
|
495
|
|
|
|
|
496
|
|
|
// puis relister les tables a importer |
|
497
|
|
|
// et les vider si besoin, au moment du premier passage ici |
|
498
|
|
|
$initialisation_copie = (!isset($status["dump_status_copie"])) ? 0 : $status["dump_status_copie"]; |
|
499
|
|
|
|
|
500
|
|
|
// si init pas encore faite, vider les tables du serveur destination |
|
501
|
|
|
if (!$initialisation_copie) { |
|
502
|
|
View Code Duplication |
if (!$vider_tables_destination_copie = charger_fonction('vider_tables_destination_copie',$racine_fonctions, true)) { |
|
|
|
|
|
|
503
|
|
|
spip_log( "Fonction '{$racine_fonctions}_vider_tables_destination_copie' inconnue. Abandon",'dump.'._LOG_INFO_IMPORTANTE); |
|
504
|
|
|
return true; // echec mais on a fini, donc true |
|
505
|
|
|
} |
|
506
|
|
|
$vider_tables_destination_copie($tables, $no_erase_dest, $serveur_dest); |
|
507
|
|
|
$status["dump_status_copie"]='ok'; |
|
508
|
|
|
ecrire_fichier($status_file,serialize($status)); |
|
509
|
|
|
} |
|
510
|
|
|
|
|
511
|
|
|
// les tables auteurs et meta doivent etre copiees en dernier ! |
|
512
|
|
|
if (in_array('spip_auteurs',$tables)){ |
|
513
|
|
|
$tables = array_diff($tables,array('spip_auteurs')); |
|
514
|
|
|
$tables[] = 'spip_auteurs'; |
|
515
|
|
|
} |
|
516
|
|
|
if (in_array('spip_meta',$tables)){ |
|
517
|
|
|
$tables = array_diff($tables,array('spip_meta')); |
|
518
|
|
|
$tables[] = 'spip_meta'; |
|
519
|
|
|
} |
|
520
|
|
|
spip_log( "Tables a copier :".implode(", ",$tables),'dump.'._LOG_INFO); |
|
521
|
|
|
|
|
522
|
|
|
$trouver_table = charger_fonction('trouver_table','base'); |
|
523
|
|
|
|
|
524
|
|
|
foreach ($tables as $table){ |
|
525
|
|
|
// si table commence par spip_ c'est une table SPIP, renommer le prefixe si besoin |
|
526
|
|
|
// sinon chercher la vraie table |
|
527
|
|
|
$desc_source = false; |
|
528
|
|
|
if (strncmp($table,"spip_",5)==0){ |
|
529
|
|
|
$desc_source = $trouver_table(preg_replace(",^spip_,","",$table), $serveur_source, true); |
|
530
|
|
|
} |
|
531
|
|
|
if (!$desc_source OR !isset($desc_source['exist']) OR !$desc_source['exist']) |
|
532
|
|
|
$desc_source = $trouver_table($table, $serveur_source, false); |
|
533
|
|
|
|
|
534
|
|
|
// verifier que la table est presente dans la base source |
|
535
|
|
|
if ($desc_source){ |
|
536
|
|
|
// $status['tables_copiees'][$table] contient l'avancement |
|
537
|
|
|
// de la copie pour la $table : 0 a N et -N quand elle est finie (-1 si vide et finie...) |
|
538
|
|
|
if (!isset($status['tables_copiees'][$table])) |
|
539
|
|
|
$status['tables_copiees'][$table] = 0; |
|
540
|
|
|
|
|
541
|
|
|
if (is_numeric($status['tables_copiees'][$table]) |
|
542
|
|
|
AND $status['tables_copiees'][$table]>=0 |
|
543
|
|
|
AND $desc_dest = $preparer_table_dest( |
|
544
|
|
|
$table, |
|
545
|
|
|
isset($desc_tables_dest[$table])?$desc_tables_dest[$table]:$desc_source, |
|
546
|
|
|
$serveur_dest, |
|
547
|
|
|
$status['tables_copiees'][$table] == 0)){ |
|
548
|
|
|
if ($callback_progression) |
|
549
|
|
|
$callback_progression($status['tables_copiees'][$table],0,$table); |
|
550
|
|
|
while (true) { |
|
551
|
|
|
$n = intval($status['tables_copiees'][$table]); |
|
552
|
|
|
// on copie par lot de 400 |
|
553
|
|
|
$res = sql_select('*',$table,isset($where[$table])?$where[$table]:'','','',"$n,400",'',$serveur_source); |
|
554
|
|
|
while ($row = sql_fetch($res,$serveur_source)){ |
|
555
|
|
|
$rows = array($row); |
|
556
|
|
|
// lire un groupe de donnees si demande en option |
|
557
|
|
|
// (permet un envoi par lot vers la destination) |
|
558
|
|
|
if ($data_pool>0){ |
|
559
|
|
|
$s = strlen(serialize($row)); |
|
560
|
|
|
while ($s<$data_pool AND $row = sql_fetch($res,$serveur_source)){ |
|
561
|
|
|
$s += strlen(serialize($row)); |
|
562
|
|
|
$rows[]= $row; |
|
563
|
|
|
} |
|
564
|
|
|
} |
|
565
|
|
|
// si l'enregistrement est deja en base, ca fera un echec ou un doublon |
|
566
|
|
|
// mais si ca renvoie false c'est une erreur fatale => abandon |
|
567
|
|
|
if ($inserer_copie($table,$rows,$desc_dest,$serveur_dest)===false) { |
|
568
|
|
|
// forcer la sortie, charge a l'appelant de gerer l'echec |
|
569
|
|
|
spip_log("Erreur fatale dans $inserer_copie table $table","dump"._LOG_ERREUR); |
|
570
|
|
|
$status['errors'][] = "Erreur fatale lors de la copie de la table $table"; |
|
571
|
|
|
ecrire_fichier($status_file,serialize($status)); |
|
572
|
|
|
// copie finie |
|
573
|
|
|
return true; |
|
574
|
|
|
} |
|
575
|
|
|
$status['tables_copiees'][$table]+=count($rows); |
|
576
|
|
|
if ($max_time AND time()>$max_time) |
|
577
|
|
|
break; |
|
578
|
|
|
} |
|
579
|
|
|
if ($n == $status['tables_copiees'][$table]) |
|
580
|
|
|
break; |
|
581
|
|
|
spip_log( "recopie $table ".$status['tables_copiees'][$table],'dump.'._LOG_INFO_IMPORTANTE); |
|
582
|
|
|
if ($callback_progression) |
|
583
|
|
|
$callback_progression($status['tables_copiees'][$table],0,$table); |
|
584
|
|
|
ecrire_fichier($status_file,serialize($status)); |
|
585
|
|
|
if ($max_time AND time()>$max_time) |
|
586
|
|
|
return false; // on a pas fini, mais le temps imparti est ecoule |
|
587
|
|
|
} |
|
588
|
|
|
if ($drop_source) { |
|
589
|
|
|
sql_drop_table($table,'',$serveur_source); |
|
590
|
|
|
spip_log( "drop $table sur serveur source '$serveur_source'",'dump.'._LOG_INFO_IMPORTANTE); |
|
591
|
|
|
} |
|
592
|
|
|
$status['tables_copiees'][$table]=($status['tables_copiees'][$table]?-$status['tables_copiees'][$table]:"zero"); |
|
593
|
|
|
ecrire_fichier($status_file,serialize($status)); |
|
594
|
|
|
spip_log( "tables_recopiees ".implode(',',$status['tables_copiees']),'dump.'._LOG_INFO); |
|
595
|
|
|
if ($callback_progression) |
|
596
|
|
|
$callback_progression($status['tables_copiees'][$table],$status['tables_copiees'][$table],$table); |
|
597
|
|
|
} |
|
598
|
|
|
else { |
|
599
|
|
|
if ($status['tables_copiees'][$table]<0) |
|
600
|
|
|
spip_log("Table $table deja copiee : ".$status['tables_copiees'][$table],"dump."._LOG_INFO); |
|
601
|
|
|
if ($callback_progression) |
|
602
|
|
|
$callback_progression(0,$status['tables_copiees'][$table],"$table".((is_numeric($status['tables_copiees'][$table]) AND $status['tables_copiees'][$table]>=0)?"[Echec]":"")); |
|
603
|
|
|
} |
|
604
|
|
|
} |
|
605
|
|
|
else { |
|
606
|
|
|
$status['errors'][] = "Impossible de lire la description de la table $table"; |
|
607
|
|
|
ecrire_fichier($status_file,serialize($status)); |
|
608
|
|
|
spip_log("Impossible de lire la description de la table $table","dump."._LOG_ERREUR); |
|
609
|
|
|
} |
|
610
|
|
|
} |
|
611
|
|
|
|
|
612
|
|
|
// si le nombre de tables envoyees n'est pas egal au nombre de tables demandees |
|
613
|
|
|
// abandonner |
|
614
|
|
|
if (count($status['tables_copiees'])<count($tables)){ |
|
615
|
|
|
spip_log("Nombre de tables copiees incorrect : ".count($status['tables_copiees'])."/".count($tables),"dump."._LOG_ERREUR); |
|
616
|
|
|
$status['errors'][] = "Nombre de tables copiees incorrect : ".count($status['tables_copiees'])."/".count($tables); |
|
617
|
|
|
ecrire_fichier($status_file,serialize($status)); |
|
618
|
|
|
} |
|
619
|
|
|
|
|
620
|
|
View Code Duplication |
if ($detruire_copieur_si_besoin = charger_fonction('detruire_copieur_si_besoin',$racine_fonctions, true)) { |
|
|
|
|
|
|
621
|
|
|
$detruire_copieur_si_besoin($serveur_dest); |
|
622
|
|
|
} |
|
623
|
|
|
else { |
|
624
|
|
|
spip_log( "Fonction '{$racine_fonctions}_detruire_copieur_si_besoin' inconnue.",'dump.'._LOG_INFO_IMPORTANTE); |
|
625
|
|
|
} |
|
626
|
|
|
|
|
627
|
|
|
// OK, copie complete |
|
628
|
|
|
return true; |
|
629
|
|
|
} |
|
630
|
|
|
|
|
631
|
|
|
/** |
|
632
|
|
|
* fonction d'insertion en base lors de la copie de base a base |
|
633
|
|
|
* |
|
634
|
|
|
* @param string $table |
|
635
|
|
|
* @param array $rows |
|
636
|
|
|
* @param array $desc_dest |
|
637
|
|
|
* @param string $serveur_dest |
|
638
|
|
|
* @return int/bool |
|
|
|
|
|
|
639
|
|
|
*/ |
|
640
|
|
|
function base_inserer_copie($table,$rows,$desc_dest,$serveur_dest){ |
|
641
|
|
|
|
|
642
|
|
|
// verifier le nombre d'insertion |
|
643
|
|
|
$nb1 = sql_countsel($table,'','','',$serveur_dest); |
|
644
|
|
|
// si l'enregistrement est deja en base, ca fera un echec ou un doublon |
|
645
|
|
|
$r = sql_insertq_multi($table,$rows,$desc_dest,$serveur_dest); |
|
646
|
|
|
$nb = sql_countsel($table,'','','',$serveur_dest); |
|
647
|
|
|
if ($nb-$nb1<count($rows)){ |
|
648
|
|
|
spip_log("base_inserer_copie : ".($nb-$nb1)." insertions au lieu de ".count($rows).". On retente 1 par 1","dump"._LOG_INFO_IMPORTANTE); |
|
649
|
|
|
foreach($rows as $row){ |
|
650
|
|
|
// si l'enregistrement est deja en base, ca fera un echec ou un doublon |
|
651
|
|
|
$r = sql_insertq($table,$row,$desc_dest,$serveur_dest); |
|
|
|
|
|
|
652
|
|
|
} |
|
653
|
|
|
// on reverifie le total |
|
654
|
|
|
$r = 0; |
|
655
|
|
|
$nb = sql_countsel($table,'','','',$serveur_dest); |
|
656
|
|
|
if ($nb-$nb1<count($rows)){ |
|
657
|
|
|
spip_log("base_inserer_copie : ".($nb-$nb1)." insertions au lieu de ".count($rows)." apres insertion 1 par 1","dump"._LOG_ERREUR); |
|
658
|
|
|
$r = false; |
|
659
|
|
|
} |
|
660
|
|
|
} |
|
661
|
|
|
return $r; |
|
662
|
|
|
} |
|
663
|
|
|
?> |
|
|
|
|
|
|
664
|
|
|
|
If you suppress an error, we recommend checking for the error condition explicitly: