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

formulaire_.php ➔ balise_FORMULAIRE__contexte()   F

Complexity

Conditions 33
Paths > 20000

Size

Total Lines 105
Code Lines 59

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 33
eloc 59
c 0
b 0
f 0
nc 798402
nop 2
dl 0
loc 105
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
 *  SPIP, Systeme de publication pour l'internet                           *
4
 *                                                                         *
5
 *  Copyright (c) 2001-2016                                                *
6
 *  Arnaud Martin, Antoine Pitrou, Philippe Riviere, Emmanuel Saint-James  *
7
 *                                                                         *
8
 *  Ce programme est un logiciel libre distribue sous licence GNU/GPL.     *
9
 *  Pour plus de details voir le fichier COPYING.txt ou l'aide en ligne.   *
10
\***************************************************************************/
11
12
/**
13
 * Fonctions génériques pour les balises formulaires
14
 *
15
 * @package SPIP\Formulaires
16
**/
17
if (!defined('_ECRIRE_INC_VERSION')) return;
18
19
include_spip('inc/filtres');
20
include_spip('inc/texte');
21
22
/**
23
 * Protéger les saisies d'un champ de formulaire
24
 * 
25
 * Proteger les ' et les " dans les champs que l'on va injecter,
26
 * sans toucher aux valeurs sérialisées
27
 *
28
 * @see entites_html()
29
 * @param string|array $texte
30
 *     Saisie à protéger
31
 * @return string|array
32
 *     Saisie protégée
33
**/
34
function protege_champ($texte){
35
	if (is_array($texte))
36
		$texte = array_map('protege_champ',$texte);
37
	else {
38
		// ne pas corrompre une valeur serialize
39
		if ((preg_match(",^[abis]:\d+[:;],", $texte) AND unserialize($texte)!=false) OR is_null($texte))
40
			return $texte;
41
		if (is_string($texte)
42
			AND $texte
43
			AND strpbrk($texte, "&\"'<>")!==false
44
			) {
45
				$texte = spip_htmlspecialchars($texte,ENT_QUOTES);
46
		}
47
		elseif(is_bool($texte))
48
			$texte = ($texte?'1':'');
49
	}
50
	return $texte;
51
}
52
53
/**
54
 * Teste si un formulaire demandé possède un squelette pour l'afficher
55
 *
56
 * @see trouver_fond()
57
 * @param string
58
 *     Nom du formulaire
59
 * @return string|bool
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string|false.

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...
60
 *     - string : chemin du squelette
61
 *     - false : pas de squelette trouvé
62
**/
63
function existe_formulaire($form)
64
{
65
	if (substr($form,0,11)=="FORMULAIRE_")
66
		$form = strtolower(substr($form,11));
67
	else 
68
		$form = strtolower($form);
69
70
	if (!$form) return ''; // on ne sait pas, le nom du formulaire n'est pas fourni ici
71
72
	return trouver_fond($form, 'formulaires/') ? $form : false;
73
}
74
75
76
/**
77
 * Balises Formulaires par défaut.
78
 *
79
 * Compilé en un appel à une balise dynamique. 
80
 *
81
 * @param Champ $p
82
 *     Description de la balise formulaire
83
 * @return Champ
84
 *     Description complétée du code compilé appelant la balise dynamique
85
**/
86
function balise_FORMULAIRE__dist($p) {
87
88
	// Cas d'un #FORMULAIRE_TOTO inexistant : renvoyer la chaine vide.
89
	// mais si #FORMULAIRE_{toto} on ne peut pas savoir a la compilation, continuer
90
	if (existe_formulaire($p->nom_champ)===FALSE) {
91
		    $p->code = "''";
92
		    $p->interdire_scripts = false;
93
		    return $p;
94
	}
95
96
	// sinon renvoyer un code php dynamique
97
	return calculer_balise_dynamique($p, $p->nom_champ, array());
98
}
99
100
/**
101
 * Balise dynamiques par défaut des formulaires
102
 *
103
 * @param string $form
104
 *     Nom du formulaire
105
 * @return string|array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use string|array<integer|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...
106
 *     - array : squelette à appeler, durée du cache, contexte
107
 *     - string : texte à afficher directement
108
 */
109
function balise_FORMULAIRE__dyn($form)
110
{
111
	$form = existe_formulaire($form);
112
	if (!$form) return '';
0 ignored issues
show
Bug Best Practice introduced by
The expression $form of type string|false is loosely compared to false; this is ambiguous if the string can be empty. You might want to explicitly use === false instead.

In PHP, under loose comparison (like ==, or !=, or switch conditions), values of different types might be equal.

For string values, the empty string '' is a special case, in particular the following results might be unexpected:

''   == false // true
''   == null  // true
'ab' == false // false
'ab' == null  // false

// It is often better to use strict comparison
'' === false // false
'' === null  // false
Loading history...
113
114
	// deux moyen d'arriver ici : 
115
	// soit #FORMULAIRE_XX reroute avec 'FORMULAIRE_XX' ajoute en premier arg
116
	// soit #FORMULAIRE_{xx}
117
118
	// recuperer les arguments passes a la balise
119
	// on enleve le premier qui est le nom de la balise 
120
	// deja recupere ci-dessus
121
122
	$args = func_get_args();
123
	array_shift($args);
124
	$contexte = balise_FORMULAIRE__contexte($form, $args);
125
	if (!is_array($contexte)) return $contexte;
126
	return array("formulaires/$form", 3600, $contexte);
127
}
128
129
/**
130
 * Calcule le contexte à envoyer dans le squelette d'un formulaire 
131
 *
132
 * @param string $form
133
 *     Nom du formulaire
134
 * @param array $args
135
 *     Arguments envoyés à l'appel du formulaire
136
 * @return array
0 ignored issues
show
Documentation introduced by
Should the return type not be string|array?

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...
137
 *     Contexte d'environnement à envoyer au squelette
138
**/
139
function balise_FORMULAIRE__contexte($form, $args)
140
{
141
	// tester si ce formulaire vient d'etre poste (memes arguments)
142
	// pour ne pas confondre 2 #FORMULAIRES_XX identiques sur une meme page
143
	// si poste, on recupere les erreurs
144
145
	$je_suis_poste = false;
146
	if ($post_form = _request('formulaire_action')
147
	 AND $post_form==$form
148
	 AND $p = _request('formulaire_action_args')
149
	 AND is_array($p = decoder_contexte_ajax($p, $post_form))) {
150
		// enlever le faux attribut de langue masque
151
		array_shift($p);
152
		if (formulaire__identifier($form, $args, $p))
153
			$je_suis_poste = true;
154
	}
155
156
	$editable = true;
157
	$erreurs = $post = array();
158
	if ($je_suis_poste) {
159
		$post = traiter_formulaires_dynamiques(true);
160
		$e = "erreurs_$form";
161
		$erreurs = isset($post[$e]) ? $post[$e] : array();
162
		$editable = "editable_$form";
163
		$editable = (!isset($post[$e]))
164
			  || count($erreurs)
165
			  || (isset($post[$editable]) && $post[$editable]);
166
	}
167
168
	$valeurs = formulaire__charger($form, $args, $je_suis_poste);
169
170
	// si $valeurs n'est pas un tableau, le formulaire n'est pas applicable
171
	// C'est plus fort qu'editable qui est gere par le squelette 
172
	// Idealement $valeur doit etre alors un message explicatif.
173
	if (!is_array($valeurs)) return is_string($valeurs) ? $valeurs : '';
174
	
175
	// charger peut passer une action si le formulaire ne tourne pas sur self()
176
	// ou une action vide si elle ne sert pas
177
	$action = (isset($valeurs['action'])) ? $valeurs['action'] : self('&amp;', true);
178
	// bug IEx : si action finit par / 
179
	// IE croit que le <form ... action=../ > est autoferme
180
	if (substr($action,-1)=='/') {
181
		// on ajoute une ancre pour feinter IE, au pire ca tue l'ancre qui finit par un /
182
		$action .= '#';
183
	}
184
185
	// recuperer la saisie en cours si erreurs
186
	// seulement si c'est ce formulaire qui est poste
187
	// ou si on le demande explicitement par le parametre _forcer_request = true
188
	$dispo = ($je_suis_poste || (isset($valeurs['_forcer_request']) && $valeurs['_forcer_request']));
189
	foreach(array_keys($valeurs) as $champ){
190
		if ($champ[0]!=='_' AND !in_array($champ, array('message_ok','message_erreur','editable'))) {
191
			if ($dispo AND (($v = _request($champ))!==NULL))
192
				$valeurs[$champ] = $v;
193
			// nettoyer l'url des champs qui vont etre saisis
194
			if ($action)
195
				$action = parametre_url($action,$champ,'');
196
			// proteger les ' et les " dans les champs que l'on va injecter
197
			$valeurs[$champ] = protege_champ($valeurs[$champ]);
198
		}
199
	}
200
201
	if ($action) {
202
		// nettoyer l'url
203
		$action = parametre_url($action,'formulaire_action','');
204
		$action = parametre_url($action,'formulaire_action_args','');
205
	}
206
207
	if (isset($valeurs['_action'])){
208
		$securiser_action = charger_fonction('securiser_action','inc');
209
		$secu = $securiser_action(reset($valeurs['_action']),end($valeurs['_action']),'',-1);
210
		$valeurs['_hidden'] = (isset($valeurs['_hidden'])?$valeurs['_hidden']:'') .
211
		"<input type='hidden' name='arg' value='".$secu['arg']."' />"
212
		. "<input type='hidden' name='hash' value='".$secu['hash']."' />";
213
	}
214
215
	// empiler la lang en tant que premier argument implicite du CVT
216
	// pour permettre de la restaurer au moment du Verifier et du Traiter
217
	array_unshift($args, $GLOBALS['spip_lang']);
218
219
	$valeurs['formulaire_args'] = encoder_contexte_ajax($args, $form);
220
	$valeurs['erreurs'] = $erreurs;
221
	$valeurs['action'] = $action;
222
	$valeurs['form'] = $form;
223
224
	if (!isset($valeurs['id'])) $valeurs['id'] = 'new';
225
	// editable peut venir de charger() ou de traiter() sinon
226
	if (!isset($valeurs['editable'])) $valeurs['editable'] = $editable;
227
	// dans tous les cas, renvoyer un espace ou vide (et pas un booleen)
228
	$valeurs['editable'] = ($valeurs['editable']?' ':'');
229
230
	if ($je_suis_poste) {
231
		$valeurs['message_erreur'] = "";
232
		if (isset($erreurs['message_erreur']))
233
			$valeurs['message_erreur'] = $erreurs['message_erreur'];
234
235
		$valeurs['message_ok'] = "";
236
		if (isset($post["message_ok_$form"]))
237
			$valeurs['message_ok'] = $post["message_ok_$form"];
238
		elseif (isset($erreurs['message_ok']))
239
			$valeurs['message_ok'] = $erreurs["message_ok"];
240
	}
241
	
242
	return $valeurs;
243
}
244
245
/**
246
 * Charger les valeurs de saisie du formulaire
247
 *
248
 * @param string $form
249
 * @param array $args
250
 * @param bool $poste
251
 * @return array
252
 */
253
function formulaire__charger($form, $args, $poste)
254
{
255 View Code Duplication
	if ($charger_valeurs = charger_fonction("charger","formulaires/$form",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...
256
		$valeurs = call_user_func_array($charger_valeurs,$args);
257
	else $valeurs = array();
258
259
	$valeurs = pipeline(
260
		'formulaire_charger',
261
		array(
262
			'args'=>array('form'=>$form,'args'=>$args,'je_suis_poste'=>$poste),
263
			'data'=>$valeurs)
264
	);
265
266
	// si $valeurs et false ou une chaine, pas de formulaire, donc pas de pipeline !
267
	if (is_array($valeurs)){
268
		if (!isset($valeurs['_pipelines'])) $valeurs['_pipelines']=array();
269
		// l'ancien argument _pipeline devient maintenant _pipelines
270
		// reinjectons le vieux _pipeline au debut de _pipelines
271
		if (isset($valeurs['_pipeline'])) {
272
			$pipe = is_array($valeurs['_pipeline'])?reset($valeurs['_pipeline']):$valeurs['_pipeline'];
273
			$args = is_array($valeurs['_pipeline'])?end($valeurs['_pipeline']):array();
274
275
			$pipelines = array($pipe=>$args);
276
			$valeurs['_pipelines'] = array_merge($pipelines,$valeurs['_pipelines']);
277
		}
278
279
		// et enfin, ajoutons systematiquement un pipeline sur le squelette du formulaire
280
		// qui constitue le cas le plus courant d'utilisation du pipeline recuperer_fond
281
		// (performance, cela evite de s'injecter dans recuperer_fond utilise pour *tous* les squelettes)
282
		$valeurs['_pipelines']['formulaire_fond'] = array('form'=>$form,'args'=>$args,'je_suis_poste'=>$poste);
283
	}
284
285
	return $valeurs;
286
}
287
288
/**
289
 * Vérifier que le formulaire en cours est celui qui est poste
290
 * 
291
 * On se base sur la fonction identifier (si elle existe) qui fournit
292
 * une signature identifiant le formulaire a partir de ses arguments
293
 * significatifs
294
 *
295
 * En l'absence de fonction identifier, on se base sur l'egalite des
296
 * arguments, ce qui fonctionne dans les cas simples
297
 *
298
 * @param string $form
299
 * @param array $args
300
 * @param array $p
301
 * @return bool
302
 */
303
function formulaire__identifier($form, $args, $p) {
304
	if ($identifier_args = charger_fonction("identifier","formulaires/$form",true)) {
305
		return call_user_func_array($identifier_args,$args)===call_user_func_array($identifier_args,$p);
306
	}
307
	return $args===$p;
308
}
309
?>
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...
310