Completed
Push — master ( 117d82...bd6ae7 )
by cam
04:12
created

editer_auteur.php ➔ revision_auteur()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
nc 1
nop 2
dl 0
loc 3
rs 10
c 0
b 0
f 0
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
 * Gestion de l'action editer_auteur et de l'API d'édition d'un auteur
15
 *
16
 * @package SPIP\Core\Auteurs\Edition
17
 */
18
19
if (!defined('_ECRIRE_INC_VERSION')) {
20
	return;
21
}
22
23
/**
24
 * Éditer ou créer un auteur
25
 *
26
 * Si aucun identifiant d'auteur n'est donné, on crée alors un nouvel auteur.
27
 *
28
 * @global array visiteur_session
29
 * @uses auteur_inserer()
30
 * @uses auteur_modifier()
31
 *
32
 * @param array|null $arg
33
 *     Identifiant de l'auteur. En absence utilise l'argument
34
 *     de l'action sécurisée.
35
 * @return array
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use array<boolean|string|integer>.

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...
36
 *     Liste (identifiant de l'auteur, Texte d'erreur éventuel)
37
 */
38
function action_editer_auteur_dist($arg = null) {
39
40
	if (is_null($arg)) {
41
		$securiser_action = charger_fonction('securiser_action', 'inc');
42
		$arg = $securiser_action();
43
	}
44
45
46
	// si id_auteur n'est pas un nombre, c'est une creation
47
	if (!$id_auteur = intval($arg)) {
48
49
		if (($id_auteur = auteur_inserer()) > 0) {
50
51
			# cf. GROS HACK
52
			# recuperer l'eventuel logo charge avant la creation
53
			# ils ont un id = 0-id_auteur de la session
54
			$id_hack = 0 - $GLOBALS['visiteur_session']['id_auteur'];
55
			$chercher_logo = charger_fonction('chercher_logo', 'inc');
56
			foreach (array('on', 'off') as $type) {
57
				if ($logo = $chercher_logo($id_hack, 'id_auteur', $type)) {
58
					if ($logo = reset($logo)) {
59
						rename($logo, str_replace($id_hack, $id_auteur, $logo));
60
					}
61
				}
62
			}
63
		}
64
	}
65
66
	// Enregistre l'envoi dans la BD
67
	$err = "";
68
	if ($id_auteur > 0) {
69
		$err = auteur_modifier($id_auteur);
70
	}
71
72
	if ($err) {
0 ignored issues
show
Bug Best Practice introduced by
The expression $err of type string|false is loosely compared to true; 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...
73
		spip_log("echec editeur auteur: $err", _LOG_ERREUR);
74
	}
75
76
	return array($id_auteur, $err);
77
}
78
79
/**
80
 * Insérer un auteur en base
81
 *
82
 * @pipeline_appel pre_insertion
83
 * @pipeline_appel post_insertion
84
 *
85
 * @param string|null $source
86
 *     D'où provient l'auteur créé ? par défaut 'spip', mais peut être 'ldap' ou autre.
87
 * @param array|null $set
88
 * @return int
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean|string?

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...
89
 *     Identifiant de l'auteur créé
90
 */
91
function auteur_inserer($source = null, $set = null) {
92
93
	// Ce qu'on va demander comme modifications
94
	$champs = array();
95
	$champs['source'] = $source ? $source : 'spip';
96
97
	$champs['login'] = '';
98
	$champs['statut'] = '5poubelle';  // inutilisable tant qu'il n'a pas ete renseigne et institue
99
	$champs['webmestre'] = 'non';
100
	if (empty($champs['imessage'])) {
101
		$champs['imessage'] = 'oui';
102
	}
103
104
	if ($set) {
105
		$champs = array_merge($champs, $set);
106
	}
107
108
	// Envoyer aux plugins
109
	$champs = pipeline('pre_insertion',
110
		array(
111
			'args' => array(
112
				'table' => 'spip_auteurs',
113
			),
114
			'data' => $champs
115
		)
116
	);
117
	$id_auteur = sql_insertq("spip_auteurs", $champs);
118
	pipeline('post_insertion',
119
		array(
120
			'args' => array(
121
				'table' => 'spip_auteurs',
122
				'id_objet' => $id_auteur
123
			),
124
			'data' => $champs
125
		)
126
	);
127
128
	return $id_auteur;
129
}
130
131
132
/**
133
 * Modifier un auteur
134
 *
135
 * Appelle toutes les fonctions de modification d'un auteur
136
 *
137
 * @param int $id_auteur
138
 *     Identifiant de l'auteur
139
 * @param array|null $set
140
 *     Couples (colonne => valeur) de données à modifier.
141
 *     En leur absence, on cherche les données dans les champs éditables
142
 *     qui ont été postés (via collecter_requests())
143
 * @param bool $force_update
144
 *   Permet de forcer la maj en base des champs fournis, sans passer par instancier.
145
 *   Utilise par auth/spip
146
 * @return string|null
0 ignored issues
show
Documentation introduced by
Should the return type not be string|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...
147
 *
148
 *     - Chaîne vide si aucune erreur,
149
 *     - Chaîne contenant un texte d'erreur sinon.
150
 */
151
function auteur_modifier($id_auteur, $set = null, $force_update = false) {
152
153
	include_spip('inc/modifier');
154
	include_spip('inc/filtres');
155
	$c = collecter_requests(
156
	// white list
157
		objet_info('auteur', 'champs_editables'),
0 ignored issues
show
Bug introduced by
It seems like objet_info('auteur', 'champs_editables') targeting objet_info() can also be of type string; however, collecter_requests() does only seem to accept array, 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...
158
		// black list
159
		$force_update ? array() : array('webmestre', 'pass', 'login'),
160
		// donnees eventuellement fournies
161
		$set
162
	);
163
164
	if ($err = objet_modifier_champs('auteur', $id_auteur,
165
		array(
166
			'data' => $set,
167
			'nonvide' => array('nom' => _T('ecrire:item_nouvel_auteur'))
168
		),
169
		$c)
170
	) {
171
		return $err;
172
	}
173
	$session = $c;
174
175
	$err = '';
176
	if (!$force_update) {
177
		// Modification de statut, changement de rubrique ?
178
		$c = collecter_requests(
179
		// white list
180
			array(
181
				'statut',
182
				'new_login',
183
				'new_pass',
184
				'login',
185
				'pass',
186
				'webmestre',
187
				'restreintes',
188
				'id_parent'
189
			),
190
			// black list
191
			array(),
192
			// donnees eventuellement fournies
193
			$set
194
		);
195
		if (isset($c['new_login']) and !isset($c['login'])) {
196
			$c['login'] = $c['new_login'];
197
		}
198
		if (isset($c['new_pass']) and !isset($c['pass'])) {
199
			$c['pass'] = $c['new_pass'];
200
		}
201
		$err = auteur_instituer($id_auteur, $c);
202
		$session = array_merge($session, $c);
203
	}
204
205
	// .. mettre a jour les sessions de cet auteur
206
	include_spip('inc/session');
207
	$session['id_auteur'] = $id_auteur;
208
	unset($session['new_login']);
209
	unset($session['new_pass']);
210
	actualiser_sessions($session);
211
212
	return $err;
213
}
214
215
/**
216
 * Associer un auteur à des objets listés
217
 *
218
 * @uses objet_associer()
219
 *
220
 * @param int $id_auteur
221
 *     Identifiant de l'auteur
222
 * @param array $objets
223
 *     Liste sous la forme `array($objet=>$id_objets,...)`.
224
 *     `$id_objets` peut lui-même être un scalaire ou un tableau pour une liste
225
 *     d'objets du même type.
226
 * @param array|null $qualif
227
 *     Optionnellement indique une qualification du (des) lien(s) qui sera
228
 *     alors appliquée dans la foulée.
229
 *     En cas de lot de liens, c'est la même qualification qui est appliquée à tous
230
 * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean|integer|array? Also, consider making the array more specific, something like array<String>, or String[].

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.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
231
 */
232
function auteur_associer($id_auteur, $objets, $qualif = null) {
233
	include_spip('action/editer_liens');
234
235
	return objet_associer(array('auteur' => $id_auteur), $objets, $qualif);
236
}
237
238
239
/**
240
 * Ancien nommage pour compatibilité
241
 *
242
 * @deprecated Utiliser auteur_associer()
243
 * @see auteur_associer()
244
 *
245
 * @param int $id_auteur
246
 * @param array $c
247
 * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean|integer|array? Also, consider making the array more specific, something like array<String>, or String[].

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.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
248
 */
249
function auteur_referent($id_auteur, $c) {
250
	return auteur_associer($id_auteur, $c);
251
}
252
253
/**
254
 * Dissocier un auteur des objets listés
255
 *
256
 * @uses objet_dissocier()
257
 *
258
 * @param int $id_auteur
259
 *     Identifiant de l'auteur
260
 * @param array $objets
261
 *     Liste sous la forme `array($objet=>$id_objets,...)`.
262
 *     `$id_objets` peut lui-même être un scalaire ou un tableau pour une liste
263
 *     d'objets du même type.
264
 *
265
 *     Un `*` pour $id_auteur,$objet,$id_objet permet de traiter par lot
266
 * @return string
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean|integer|array? Also, consider making the array more specific, something like array<String>, or String[].

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.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
267
 */
268
function auteur_dissocier($id_auteur, $objets) {
269
	include_spip('action/editer_liens');
270
271
	return objet_dissocier(array('auteur' => $id_auteur), $objets);
272
}
273
274
/**
275
 * Qualifier le lien d'un auteur avec les objets listés
276
 *
277
 * @uses objet_qualifier_liens()
278
 *
279
 * @param int $id_auteur
280
 *     Identifiant de l'auteur
281
 * @param array $objets
282
 *     Liste sous la forme `array($objet=>$id_objets,...)`.
283
 *     `$id_objets` peut lui-même être un scalaire ou un tableau pour une liste
284
 *     d'objets du même type.
285
 *
286
 *     Un `*` pour $id_auteur,$objet,$id_objet permet de traiter par lot
287
 * @param array $qualif
288
 *     Couples (colonne, valeur) tel que `array('vu'=>'oui');`
289
 * @return bool|int
0 ignored issues
show
Documentation introduced by
Should the return type not be boolean|integer|array? Also, consider making the array more specific, something like array<String>, or String[].

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.

If the return type contains the type array, this check recommends the use of a more specific type like String[] or array<String>.

Loading history...
290
 */
291
function auteur_qualifier($id_auteur, $objets, $qualif) {
292
	include_spip('action/editer_liens');
293
294
	return objet_qualifier_liens(array('auteur' => $id_auteur), $objets, $qualif);
295
}
296
297
298
/**
299
 * Modifier le statut d'un auteur, ou son login/pass
300
 *
301
 * @pipeline_appel pre_edition
302
 * @pipeline_appel post_edition
303
 *
304
 * @param int $id_auteur
305
 *     Identifiant de l'auteur
306
 * @param array $c
307
 *     Couples (colonne => valeur) des données à instituer
308
 * @param bool $force_webmestre
309
 *     Autoriser un auteur à passer webmestre (force l'autorisation)
310
 * @return bool|string
0 ignored issues
show
Documentation introduced by
Consider making the return type a bit more specific; maybe use false|string.

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...
311
 */
312
function auteur_instituer($id_auteur, $c, $force_webmestre = false) {
313
	if (!$id_auteur = intval($id_auteur)) {
314
		return false;
315
	}
316
	$erreurs = array(); // contiendra les differentes erreurs a traduire par _T()
317
	$champs = array();
318
319
	// les memoriser pour les faire passer dans le pipeline pre_edition
320 View Code Duplication
	if (isset($c['login']) and strlen($c['login'])) {
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...
321
		$champs['login'] = $c['login'];
322
	}
323 View Code Duplication
	if (isset($c['pass']) and strlen($c['pass'])) {
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...
324
		$champs['pass'] = $c['pass'];
325
	}
326
327
	$statut = $statut_ancien = sql_getfetsel('statut', 'spip_auteurs', 'id_auteur=' . intval($id_auteur));
328
329
	if (isset($c['statut'])
330
		and (autoriser('modifier', 'auteur', $id_auteur, null, array('statut' => $c['statut'])))
331
	) {
332
		$statut = $champs['statut'] = $c['statut'];
333
	}
334
335
	// Restreindre avant de declarer l'auteur
336
	// (section critique sur les droits)
337
	if (isset($c['id_parent']) and $c['id_parent']) {
338
		if (is_array($c['restreintes'])) {
339
			$c['restreintes'][] = $c['id_parent'];
340
		} else {
341
			$c['restreintes'] = array($c['id_parent']);
342
		}
343
	}
344
345
	if (isset($c['webmestre'])
346
		and ($force_webmestre or autoriser('modifier', 'auteur', $id_auteur, null, array('webmestre' => '?')))
347
	) {
348
		$champs['webmestre'] = $c['webmestre'] == 'oui' ? 'oui' : 'non';
349
	}
350
351
	// si statut change et n'est pas 0minirezo, on force webmestre a non
352
	if (isset($c['statut']) and $c['statut'] !== '0minirezo') {
353
		$champs['webmestre'] = $c['webmestre'] = 'non';
354
	}
355
356
	// Envoyer aux plugins
357
	$champs = pipeline('pre_edition',
358
		array(
359
			'args' => array(
360
				'table' => 'spip_auteurs',
361
				'id_objet' => $id_auteur,
362
				'action' => 'instituer',
363
				'statut_ancien' => $statut_ancien,
364
			),
365
			'data' => $champs
366
		)
367
	);
368
369
	if (isset($c['restreintes']) and is_array($c['restreintes'])
370
		and autoriser('modifier', 'auteur', $id_auteur, null, array('restreint' => $c['restreintes']))
371
	) {
372
		$rubriques = array_map('intval', $c['restreintes']);
373
		$rubriques = array_unique($rubriques);
374
		$rubriques = array_diff($rubriques, array(0));
375
		auteur_dissocier($id_auteur, array('rubrique' => '*'));
376
		auteur_associer($id_auteur, array('rubrique' => $rubriques));
377
	}
378
379
	$flag_ecrire_acces = false;
380
	// commencer par traiter les cas particuliers des logins et pass
381
	// avant les autres ecritures en base
382
	if (isset($champs['login']) or isset($champs['pass'])) {
383
		$auth_methode = sql_getfetsel('source', 'spip_auteurs', 'id_auteur=' . intval($id_auteur));
384
		include_spip('inc/auth');
385 View Code Duplication
		if (isset($champs['login']) and strlen($champs['login'])) {
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...
386
			if (!auth_modifier_login($auth_methode, $champs['login'], $id_auteur)) {
387
				$erreurs[] = 'ecrire:impossible_modifier_login_auteur';
388
			}
389
		}
390
		if (isset($champs['pass']) and strlen($champs['pass'])) {
391
			$champs['login'] = sql_getfetsel('login', 'spip_auteurs', 'id_auteur=' . intval($id_auteur));
392
			if (!auth_modifier_pass($auth_methode, $champs['login'], $champs['pass'], $id_auteur)) {
393
				$erreurs[] = 'ecrire:impossible_modifier_pass_auteur';
394
			}
395
		}
396
		unset($champs['login']);
397
		unset($champs['pass']);
398
		$flag_ecrire_acces = true;
399
	}
400
401
	if (!count($champs)) {
402
		return implode(' ', array_map('_T', $erreurs));
403
	}
404
	sql_updateq('spip_auteurs', $champs, 'id_auteur=' . $id_auteur);
405
406
	// .. mettre a jour les fichiers .htpasswd et .htpasswd-admin
407
	if ($flag_ecrire_acces
408
		or isset($champs['statut'])
409
	) {
410
		include_spip('inc/acces');
411
		ecrire_acces();
412
	}
413
414
	// Invalider les caches
415
	include_spip('inc/invalideur');
416
	suivre_invalideur("id='auteur/$id_auteur'");
417
418
	// Pipeline
419
	pipeline('post_edition',
420
		array(
421
			'args' => array(
422
				'table' => 'spip_auteurs',
423
				'id_objet' => $id_auteur,
424
				'action' => 'instituer',
425
				'statut_ancien' => $statut_ancien,
426
			),
427
			'data' => $champs
428
		)
429
	);
430
431
432
	// Notifications
433
	if ($notifications = charger_fonction('notifications', 'inc')) {
434
		$notifications('instituerauteur', $id_auteur,
435
			array('statut' => $statut, 'statut_ancien' => $statut_ancien)
436
		);
437
	}
438
439
	return implode(' ', array_map('_T', $erreurs));
440
441
}
442