Completed
Push — spip-3.0 ( 5d8b58 )
by cam
53:01 queued 42:30
created

dump.php ➔ base_copier_tables()   F

Complexity

Conditions 53
Paths > 20000

Size

Total Lines 162
Code Lines 107

Duplication

Lines 18
Ratio 11.11 %

Importance

Changes 2
Bugs 1 Features 0
Metric Value
cc 53
eloc 107
c 2
b 1
f 0
nc 55905280
nop 5
dl 18
loc 162
rs 2

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

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);
0 ignored issues
show
Security Best Practice introduced by
It seems like you do not handle an error condition here. This can introduce security issues, and is generally not recommended.

If you suppress an error, we recommend checking for the error condition explicitly:

// For example instead of
@mkdir($dir);

// Better use
if (@mkdir($dir) === false) {
    throw new \RuntimeException('The directory '.$dir.' could not be created.');
}
Loading history...
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']);
0 ignored issues
show
Unused Code introduced by
$meta is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
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'))
0 ignored issues
show
Bug introduced by
It seems like sql_countsel($t, '', '', '', $serveur) targeting sql_countsel() can also be of type boolean; however, singulier_ou_pluriel() does only seem to accept integer, maybe add an additional type check?

This check looks at variables that are passed out again to other methods.

If the outgoing method call has stricter type requirements than the method itself, an issue is raised.

An additional type check may prevent trouble.

Loading history...
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'])){
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array[].

This check looks for the generic type array as a return type and suggests a more specific type. This type is inferred from the actual code.

Loading history...
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){
0 ignored issues
show
Bug introduced by
The expression $tables of type array|boolean is not guaranteed to be traversable. How about adding an additional type check?

There are different options of fixing this problem.

  1. If you want to be on the safe side, you can add an additional type-check:

    $collection = json_decode($data, true);
    if ( ! is_array($collection)) {
        throw new \RuntimeException('$collection must be an array.');
    }
    
    foreach ($collection as $item) { /** ... */ }
    
  2. If you are sure that the expression is traversable, you might want to add a doc comment cast to improve IDE auto-completion and static analysis:

    /** @var array $collection */
    $collection = json_decode($data, true);
    
    foreach ($collection as $item) { /** .. */ }
    
  3. Mark the issue as a false-positive: Just hover the remove button, in the top-right corner of this issue for more options.

Loading history...
232 View Code Duplication
			if ($infos['principale'] AND !isset($tables_principales[$t]))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
233
				$tables_principales[$t] = true;
234 View Code Duplication
			if (!$infos['principale'] AND !isset($tables_auxiliaires[$t]))
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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)) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
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
0 ignored issues
show
Documentation introduced by
The doc-type int/bool could not be parsed: Unknown type name "int/bool" at position 0. (view supported doc-types)

This check marks PHPDoc comments that could not be parsed by our parser. To see which comment annotations we can parse, please refer to our documentation on supported doc-types.

Loading history...
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);
0 ignored issues
show
Unused Code introduced by
$r is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
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
?>
0 ignored issues
show
Best Practice introduced by
It is not recommended to use PHP's closing tag ?> in files other than templates.

Using a closing tag in PHP files that only contain PHP code is not recommended as you might accidentally add whitespace after the closing tag which would then be output by PHP. This can cause severe problems, for example headers cannot be sent anymore.

A simple precaution is to leave off the closing tag as it is not required, and it also has no negative effects whatsoever.

Loading history...
664