Completed
Push — master ( b0e666...8bdd42 )
by cam
04:37
created

cvt_multietapes.php ➔ cvtmulti_formulaire_verifier_etapes()   D

Complexity

Conditions 18
Paths 14

Size

Total Lines 72

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 18
nc 14
nop 2
dl 0
loc 72
rs 4.8666
c 0
b 0
f 0

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, Système de publication pour l'internet                           *
5
 *                                                                         *
6
 *  Copyright © avec tendresse depuis 2001                                 *
7
 *  Arnaud Martin, Antoine Pitrou, Philippe Rivière, Emmanuel Saint-James  *
8
 *                                                                         *
9
 *  Ce programme est un logiciel libre distribué sous licence GNU/GPL.     *
10
 *  Pour plus de détails voir le fichier COPYING.txt ou l'aide en ligne.   *
11
\***************************************************************************/
12
13
/**
14
 * CVT Multi étapes
15
 *
16
 * Module facilitant l'écriture de formulaires CVT
17
 * en plusieurs étapes.
18
 *
19
 * `#FORMULAIRE_TRUC`
20
 *
21
 * Squelette :
22
 * Chaque étape est representée par un squelette indépendant qui doit
23
 * implémenter un formulaire autonome pour les saisies de l'étape n :
24
 *
25
 * - formulaires/truc.html pour l'etape 1
26
 * - formulaires/truc_2.html pour l'etape 2
27
 * - formulaires/truc_n.html pour l'etape n
28
 *
29
 * Si un squelette `formulaires/truc_n.html` manque pour l'étape n
30
 * c'est `formulaires/truc.html` qui sera utilisé
31
 * (charge à lui de gérer le cas de cette étape).
32
 *
33
 * Charger :
34
 * `formulaires_truc_charger_dist()` :
35
 *  passer '_etapes' => nombre total d'etapes de saisies (>1 !)
36
 *  indiquer toutes les valeurs à saisir sur toutes les pages
37
 *  comme si il s'agissait d'un formulaire unique
38
 *
39
 * Vérifier :
40
 * Le numero d'étape courante est disponible dans `$x=_request('_etape')`, si nécessaire
41
 * `_request()` permet d'accéder aux saisies effectuées depuis l'étape 1,
42
 * comme si les étapes 1 a `$x` avaient été saisies en une seule fois
43
 *
44
 * - formulaires_truc_verifier_1_dist() : verifier les saisies de l'etape 1 uniquement
45
 * - formulaires_truc_verifier_2_dist() : verifier les saisies de l'etape 2
46
 * - formulaires_truc_verifier_n_dist() : verifier les saisies de l'etape n
47
 *
48
 * Il est possible d'implémenter toutes les vérifications dans une fonction unique
49
 * qui sera alors appelée avec en premier argument le numero de l'étape à vérifier
50
 * `formulaires_truc_verifier_etape_dist($etape,...)` : vérifier les saisies
51
 * de l'étape `$etape` uniquement.
52
 *
53
 * À chaque étape x, les étapes 1 a x sont appelées en vérification
54
 * pour vérifier l'absence de régression dans la validation (erreur, tentative de réinjection ...)
55
 * en cas d'erreur, la saisie retourne à la première étape en erreur.
56
 * en cas de succès, l'étape est incrémentée, sauf si c'est la dernière.
57
 * Dans ce dernier cas on déclenche `traiter()`.
58
 *
59
 * Traiter :
60
 * `formulaires_truc_traiter_dist()` : ne sera appelé que lorsque **toutes**
61
 * les étapes auront été saisies sans erreur.
62
 *
63
 * La fonction traiter peut donc traiter l'ensemble des saisies comme si il
64
 * s'agissait d'un formulaire unique dans lequel toutes les données auraient
65
 * été saisies en une fois.
66
 */
67
68
if (!defined('_ECRIRE_INC_VERSION')) {
69
	return;
70
}
71
72
/**
73
 * Reinjecter dans _request() les valeurs postees
74
 * dans les etapes precedentes
75
 *
76
 * @param string $form
77
 * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be array|false?

This check compares the return type specified in the @return annotation of a function or method doc comment with the types returned by the function and raises an issue if they mismatch.

Loading history...
78
 */
79
function cvtmulti_recuperer_post_precedents($form) {
80
	include_spip('inc/filtres');
81
	if ($form
82
		and $c = _request('cvtm_prev_post')
83
		and $c = decoder_contexte_ajax($c, $form)
84
	) {
85
		#var_dump($c);
86
87
		# reinjecter dans la bonne variable pour permettre de retrouver
88
		# toutes les saisies dans un seul tableau
89
		if ($_SERVER['REQUEST_METHOD'] == 'POST') {
90
			$store = &$_POST;
91
		} else {
92
			$store = &$_GET;
93
		}
94
95
		foreach ($c as $k => $v) // on ecrase pas si saisi a nouveau !
0 ignored issues
show
Bug introduced by
The expression $c of type array|string|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...
96
		{
97
			if (!isset($store[$k])) {
98
				$_REQUEST[$k] = $store[$k] = $v;
99
			} // mais si tableau des deux cotes, on merge avec priorite a la derniere saisie
100
			elseif (is_array($store[$k])
101
				and is_array($v)
102
				and $z = array_keys($v)
103
				and !is_numeric(reset($z))
104
				and $z = array_keys($store[$k])
105
				and !is_numeric(reset($z))
106
			) {
107
				$_REQUEST[$k] = $store[$k] = array_merge($v, $store[$k]);
108
			}
109
		}
110
111
		// vider pour eviter un second appel a verifier_n
112
		// en cas de double implementation (unipotence)
113
		set_request('cvtm_prev_post');
114
115
		return array($c['_etape'], $c['_etapes']);
116
	}
117
118
	return false;
119
}
120
121
/**
122
 * Sauvegarder les valeurs postees dans une variable encodee
123
 * pour les recuperer a la prochaine etape
124
 *
125
 * @param string $form
126
 * @param bool $je_suis_poste
127
 * @param array $valeurs
128
 * @return array
129
 */
130
function cvtmulti_sauver_post($form, $je_suis_poste, &$valeurs) {
131
	if (!isset($valeurs['_cvtm_prev_post'])) {
132
		$post = array('_etape' => $valeurs['_etape'], '_etapes' => $valeurs['_etapes']);
133
		foreach (array_keys($valeurs) as $champ) {
134
			if (substr($champ, 0, 1) !== '_') {
135
				if ($je_suis_poste || (isset($valeurs['_forcer_request']) && $valeurs['_forcer_request'])) {
136
					if (($v = _request($champ)) !== null) {
137
						$post[$champ] = $v;
138
					}
139
				}
140
			}
141
		}
142
		include_spip('inc/filtres');
143
		$c = encoder_contexte_ajax($post, $form);
144
		if (!isset($valeurs['_hidden'])) {
145
			$valeurs['_hidden'] = '';
146
		}
147
		$valeurs['_hidden'] .= "<input type='hidden' name='cvtm_prev_post' value='$c' />";
148
		// marquer comme fait, pour eviter double encodage (unipotence)
149
		$valeurs['_cvtm_prev_post'] = true;
150
	}
151
152
	return $valeurs;
153
}
154
155
156
/**
157
 * Reperer une demande de formulaire CVT multi page
158
 * et la reformater
159
 *
160
 * @deprecated : appel direct de cvtmulti_formulaire_charger_etapes par le core
161
 * @param array $flux
162
 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,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...
163
 */
164
function cvtmulti_formulaire_charger($flux) {
165
	if (is_array($flux['data'])
166
		and isset($flux['data']['_etapes'])
167
	) {
168
		$flux['data'] = cvtmulti_formulaire_charger_etapes($flux['args'], $flux['data']);
169
	}
170
171
	return $flux;
172
}
173
174
/**
175
 * Charger une etape du cvt multi
176
 * @param $args
177
 * @param $valeurs
178
 * @return array
179
 */
180
function cvtmulti_formulaire_charger_etapes($args, $valeurs) {
181
	if (!isset($valeurs['_etape'])) {
182
		$form = $args['form'];
183
		$je_suis_poste = $args['je_suis_poste'];
184
		$nb_etapes = $valeurs['_etapes'];
185
		$etape = _request('_etape');
186
		$etape = min(max($etape, 1), $nb_etapes);
187
		set_request('_etape', $etape);
188
		$valeurs['_etape'] = $etape;
189
190
		// sauver les posts de cette etape pour les avoir a la prochaine etape
191
		$valeurs = cvtmulti_sauver_post($form, $je_suis_poste, $valeurs);
192
	}
193
	return $valeurs;
194
}
195
196
197
/**
198
 * Verifier les etapes de saisie
199
 *
200
 * @deprecated : appel direct de cvtmulti_formulaire_verifier_etapes par le core
201
 * @param array $flux
202
 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<string,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...
203
 */
204
function cvtmulti_formulaire_verifier($flux) {
205
	$flux['data'] = cvtmulti_formulaire_verifier_etapes($flux['args'], $flux['data']);
206
	return $flux;
207
}
208
209
/**
210
 * Verifier les etapes de saisie
211
 * 
212
 * @param array $args
213
 * @param $erreurs
214
 * @return array
215
 */
216
function cvtmulti_formulaire_verifier_etapes($args, $erreurs) {
217
	#var_dump('Pipe verifier');
218
219
	if ($form = $args['form']
220
		and ($e = cvtmulti_recuperer_post_precedents($form)) !== false
221
	) {
222
		// recuperer l'etape saisie et le nombre d'etapes total
223
		list($etape, $etapes) = $e;
224
		$etape_demandee = intval(_request('aller_a_etape')); // possibilite de poster en entier dans aller_a_etape
225
226
		// lancer les verifs pour chaque etape deja saisie de 1 a $etape
227
		$erreurs_etapes = array();
228
		$derniere_etape_ok = 0;
229
		$e = 0;
230
		while ($e < max($etape, $etape_demandee) and $e < $etapes) {
231
			$e++;
232
			$erreurs_etapes[$e] = array();
233
			if ($verifier = charger_fonction("verifier_$e", "formulaires/$form/", true)) {
234
				$erreurs_etapes[$e] = call_user_func_array($verifier, $args['args']);
235
			} elseif ($verifier = charger_fonction("verifier_etape", "formulaires/$form/", true)) {
236
				$a = $args['args'];
237
				array_unshift($a, $e);
238
				$erreurs_etapes[$e] = call_user_func_array($verifier, $a);
239
			}
240
			// et on appelle un pipeline dedie aux etapes, plus easy
241
			$args['etape'] = $e;
242
			$erreurs_etapes[$e] = pipeline(
243
				'formulaire_verifier_etape',
244
				array(
245
					'args' => $args,
246
					'data' => $erreurs_etapes[$e]
247
				)
248
			);
249
250
			if ($derniere_etape_ok == $e - 1 and !count($erreurs_etapes[$e])) {
251
				$derniere_etape_ok = $e;
252
			}
253
			// possibilite de poster dans _retour_etape_x
254
			if (!is_null(_request("_retour_etape_$e"))) {
255
				$etape_demandee = $e;
256
			}
257
		}
258
259
		// si la derniere etape OK etait la derniere
260
		// on renvoie le flux inchange et ca declenche traiter
261
		if ($derniere_etape_ok == $etapes
262
			and (!$etape_demandee or $etape_demandee>=$etapes)) {
263
			return $erreurs;
264
		} else {
265
			$etape = $derniere_etape_ok + 1;
266
			if ($etape_demandee > 0 and $etape_demandee < $etape) {
267
				$etape = $etape_demandee;
268
			}
269
			$etape = min($etape, $etapes);
270
			#var_dump("prochaine etape $etape");
271
			// retourner les erreurs de l'etape ciblee
272
			$erreurs = isset($erreurs_etapes[$etape]) ? $erreurs_etapes[$etape] : array();
273
			// Ne pas se tromper dans le texte du message d'erreur : la clé '_etapes' n'est pas une erreur !
274
			if ($erreurs) {
275
				if (empty($erreurs['message_erreur'])) {
276
					$erreurs['message_erreur'] = singulier_ou_pluriel(count($erreurs), 'avis_1_erreur_saisie', 'avis_nb_erreurs_saisie');
277
				}
278
			} else {
279
				$erreurs['message_erreur'] = '';
280
			}
281
			$erreurs['_etapes'] = "etape suivante $etape";
282
			set_request('_etape', $etape);
283
		}
284
	}
285
286
	return $erreurs;
287
}
288
289
/**
290
 * Selectionner le bon fond en fonction de l'etape
291
 * L'etape 1 est sur le fond sans suffixe
292
 * Les autres etapes x sont sur le fond _x
293
 *
294
 * @param array $flux
295
 * @return array
296
 */
297
function cvtmulti_styliser($flux) {
298
	if (strncmp($flux['args']['fond'], 'formulaires/', 12) == 0
299
		and isset($flux['args']['contexte']['_etapes'])
300
		and isset($flux['args']['contexte']['_etape'])
301
		and ($e = $flux['args']['contexte']['_etape']) > 1
302
		and $ext = $flux['args']['ext']
303
		and $f = $flux['data']
304
		and file_exists($f . "_$e.$ext")
305
	) {
306
		$flux['data'] = $f . "_$e";
307
	}
308
309
	return $flux;
310
}
311