Subversion Repositories Applications.referentiel

Rev

Rev 20 | Rev 30 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
20 jpm 1
<?php
2
// Encodage : UTF-8
3
// +-------------------------------------------------------------------------------------------------------------------+
4
/**
5
* ScriptCommande
6
*
7
* Description : classe abstraite des scripts
8
* Fichier d'origine jelix-scripts par Jouanneau Laurent
9
* copyright		2005-2007 Jouanneau laurent
10
* link			http://www.jelix.org
11
*
12
//Auteur original :
13
* @author		Jean-Pascal MILCENT <jpm@tela-botanica.org>
14
* @copyright	Tela-Botanica 1999-2008
15
* @licence		GPL v3 & CeCILL v2
16
* @version		$Id: ScriptCommande.class.php 1948 2009-09-03 14:12:02Z Jean-Pascal MILCENT $
17
*/
18
// +-------------------------------------------------------------------------------------------------------------------+
19
// TODO : supprimer les classe getStaticIni(), getStaticParam() et getStaticNom(). Utiliser une seule méthode qui gère les deux méthodes d'appel.
20
/**
21
* classe representant une commande
22
*/
23
abstract class ScriptCommande {
24
 
25
	public $nom;
26
	public $parametres;
27
 
28
 
29
	/**
30
	 * Paramêtres disponible pour la ligne de commande
31
	 * le tableau se construit de la forme suivnate :
32
	 * - clé =  nom du paramêtre '-foo'
33
	 * - value = contient un nouveau tableau composé de cette façaon :
34
	 *  - booléen: true si le paramêtre est obligatoire
35
	 *  - booléen ou var : true si le paramêtre nécessite un valeur à sa suite ou la valeur par défaut
36
	 *  - string: description du contenu du paramêtre
37
	 * Les paramêtres optionels devraient être déclaré à la fin du tableau.
38
	 * Le dernier parametre du tableau peut avoir la valeur '...',
39
	 * il contiendra alors l'ensemble des paramêtres suivant trouvés sur la ligne de commande.
40
	 * @var array
41
	 */
42
	private $_parametres_autorises = array(	'-p' => array(true, true, 'Projet, le nom utiliser pour le fichier ini'),
43
											'-a' => array(true, true, 'Action à réaliser'),
44
											'-v' => array(false, '1', 'Mode verbeux : 1 ou 2'),
45
											'-t' => array(false, '', 'Test sur un nombre de ligne...'));
46
	/**
47
	 * Contient les valeurs des paramêtres récupérés de la ligne de commande :
48
	 * le tableau se construit de la forme suivnate :
49
	 * - clé =  nom du paramêtre '-foo'
50
	 * - valeur = la valeur récupérée sur la ligne de commande
51
	 * @var array
52
	 */
53
	private $_parametres;
54
 
55
	private static $_static_nom;
56
	private static $_static_parametres;
57
	private static $_static_ini;
58
	private static $log = '';
59
	private static $log_fichier;
60
	private static $log_resource;
61
	private static $log_fichier_ecraser = false;
62
 
63
	public $syntaxhelp = '';
64
	public $help = 'Aucune aide pour cette commande';
65
 
66
	function __construct($commande_nom) {
67
		$this->setNom($commande_nom);
68
	}
69
 
70
	public function __destruct() {
71
		if (isset(self::$log_resource)) {
72
			if (fclose(self::$log_resource)) {
73
				self::$log_resource = null;
74
			}
75
		}
76
	}
77
 
78
	public function getNom() {
79
		return $this->nom;
80
	}
81
 
82
	public static function getStaticNom() {
83
		return self::$_static_nom;
84
	}
85
 
86
	private function setNom($script_nom) {
87
		$this->nom = $script_nom;
88
		self::$_static_nom = $script_nom;
89
	}
90
 
91
	public static function getLog() {
92
		return self::$log;
93
	}
94
 
95
	public static function setLog($l) {
96
		self::$log .= $l;
97
	}
98
 
99
	public function initialiser($plc) {
100
		// Récupération des paramêtres autorisés par le script
101
		$this->setParamAutorises($this->parametres);
102
 
103
		// Vérification et récupération des paramêtres de la ligne de commande
104
		if ($parametres = $this->verifierParametres($plc, $this->getParamAutorises())) {
105
			$this->setParam($parametres);
106
		}
107
 
108
		// Tableaux des emplacements des fichiers ini à rechercher et à charger dans l'ordre du tableau
109
		$projet_prefixe = '';
110
		if (preg_match('/^([^_]+)/', $this->getParam('p'), $match)) {
111
			$projet_prefixe = $match[1];
112
		}
113
		$tab_fichiers_ini = array(	ES_CHEMIN_CONFIG.'bdd.ini', // Paramêtres de la base de données
114
									ES_CHEMIN_CONFIG.'commun.ini', // Paramêtres communs aux différents projets
115
									$this->getModuleChemin().$this->getParam('p').'.ini',
116
									$this->getModuleChemin().DS.'configurations'.DS.$this->getParam('p').'.ini');
117
 
118
		// Chargement des fichiers ini généraux
119
		for ($i = 0; $i < 2 ; $i++) {
120
			if (!$this->parserFichierIni($tab_fichiers_ini[$i])) {
121
				$e = "Le fichier $tab_fichiers_ini[$i] est introuvable\n";
122
				trigger_error($e, E_USER_WARNING);
123
			}
124
		}
125
		// Chargement du fichier ini du projet
126
		$erreur_ini_projet = true;
26 jpm 127
		for ($i = 2; $i < 4 ; $i++) {
20 jpm 128
			if ($this->parserFichierIni($tab_fichiers_ini[$i])) {
129
				$erreur_ini_projet = false;
130
			}
131
		}
132
		if ($erreur_ini_projet) {
133
			$e = "Le fichier .ini du projet est introuvable : \n".$tab_fichiers_ini[2]."\n".$tab_fichiers_ini[3]."\n";
134
			trigger_error($e, E_USER_WARNING);
135
		}
136
	}
137
 
138
	abstract public function executer();
139
 
140
	protected function getModuleChemin($shouldexist = true) {
141
		$chemin = ES_CHEMIN_MODULE.$this->getNom().DS;
142
		if (!file_exists($chemin) && $shouldexist) {
143
			trigger_error("Erreur: le module '".$this->getNom()."' n'existe pas ($chemin)\n", E_USER_ERROR);
144
		}
145
		return $chemin;
146
	}
147
 
148
	private function verifierParametres($p_ligne, $p_autorise) {
149
 
150
		//print_r($p_ligne);
151
		// Récupération des paramêtres
152
		foreach ($p_autorise as $p_nom => $p_val) {
153
			if (count($p_ligne) == 0) {
154
				if ($p_val[0]) {
155
					trigger_error("Erreur: paramêtre manquant '".$p_nom."' \n", E_USER_WARNING);
156
				}
157
			}
158
			if ($p_nom == '...') {
159
				$parametres['...'] = array();
160
				foreach($p_ligne as $arg) {
161
					$parametres['...'][] = $arg;
162
				}
163
				$p_ligne = array();
164
				break;
165
			} else {
166
				if (isset($p_ligne[$p_nom])) {
167
					// Attribution de la valeur issue de la ligne de commande
168
					$parametres[ltrim($p_nom, '-')] = $p_ligne[$p_nom];
169
					unset($p_ligne[$p_nom]);
170
				} else {
171
					// Attribution de la valeur par défaut
172
					if ($p_val[1] !== true) {
173
						$parametres[ltrim($p_nom, '-')] = $p_val[1];
174
					}
175
				}
176
			}
177
		}
178
 
179
		// Gestion de l'excédant de paramêtres
180
		if (count($p_ligne)) {
181
			trigger_error("Erreur: trop de paramêtres\n", E_USER_ERROR);
182
		}
183
 
184
		return $parametres;
185
	}
186
 
187
	protected function setParamAutorises($param) {
188
		if (!is_null($param)) {
189
			foreach ($param as $c => $v) {
190
				if (isset($this->_parametres_autorises[$c])) {
191
					trigger_error("Erreur: le module '".$this->getNom()."' ne peut définir le paramêtre '$c' car il existe déjà\n", E_USER_ERROR);
192
				} else {
193
					$this->_parametres_autorises[$c] = $v;
194
				}
195
			}
196
		}
197
	}
198
 
199
	protected function getParamAutorises($param = null) {
200
 
201
		if (!is_null($param)) {
202
			if (isset($this->_parametres_autorises['-'.$param])) {
203
				return $this->_parametres_autorises['-'.$param];
204
			} else if (isset($this->_parametres_autorises[$param])) {
205
				return $this->_parametres_autorises[$param];
206
			} else {
207
				trigger_error("Erreur: le module '".$this->getNom()."' n'a pas défini le paramêtre '$param'\n", E_USER_WARNING);
208
				return false;
209
			}
210
		} else {
211
			return $this->_parametres_autorises;
212
		}
213
	}
214
 
215
	protected function setParam($params = array(), $val = null) {
216
 
217
		if (is_array($params)) {
218
			$this->_parametres = $params;
219
			self::$_static_parametres = $params;
220
		} else if (!is_array($params) && !is_null($val)) {
221
			$this->_parametres[$params] = $val;
222
			self::$_static_parametres[$params] = $val;
223
		} else {
224
			return false;
225
		}
226
	}
227
 
228
	protected function getParam($param = null) {
229
 
230
		if (!is_null($param)) {
231
			if (isset($this->_parametres['-'.$param])) {
232
				return $this->_parametres['-'.$param];
233
			} else if (isset($this->_parametres[$param])) {
234
				return $this->_parametres[$param];
235
			} else {
236
				trigger_error("Erreur: la ligne de commande ne contenait pas le paramêtre '$param'\n", E_USER_WARNING);
237
				return false;
238
			}
239
		} else {
240
			return $this->_parametres;
241
		}
242
	}
243
 
244
	protected static function getStaticParam($param = null) {
245
 
246
		if (!is_null($param)) {
247
			if (isset(self::$_static_parametres['-'.$param])) {
248
				return self::$_static_parametres['-'.$param];
249
			} else if (isset(self::$_static_parametres[$param])) {
250
				return self::$_static_parametres[$param];
251
			} else {
252
				trigger_error("Erreur: la ligne de commande ne contenait pas le paramêtre '$param'\n", E_USER_WARNING);
253
				return false;
254
			}
255
		} else {
256
			return self::$_static_parametres;
257
		}
258
	}
259
 
260
	protected function getIni($nom) {
261
		if (isset($this->_ini[$nom])) {
262
			 return $this->_ini[$nom];
263
		 } else {
264
			 return false;
265
		 }
266
	}
267
 
268
	protected static function getStaticIni($nom) {
269
		if (isset(self::$_static_ini[$nom])) {
270
			 return self::$_static_ini[$nom];
271
		 } else {
272
			 return false;
273
		 }
274
	}
275
 
276
	protected function parserFichierIni($fichier_ini) {
277
    	if (file_exists($fichier_ini)) {
278
			$aso_ini = parse_ini_file($fichier_ini);
279
	    	foreach ($aso_ini as $cle => $val) {
280
	    		if (preg_match('/^php:(.+)$/', $val, $correspondances)) {
281
	    			eval('$this->$cle = '.$correspondances[1].';');
282
	    			eval('$this->_ini[$cle] = '.$correspondances[1].';');
283
	    		} else if (preg_match('/^php-static:(.+)$/', $val, $correspondances)) {
284
	    			eval('self::$'.$cle.' = '.$correspondances[1].';');
285
	    			eval('$this->_ini[$cle] = '.$correspondances[1].';');
286
	    		} else {
287
	    			// Ancienne forme : compatibilité avec les anciens scripts...
288
	    			$this->$cle = $val;
289
	    			// Nouvelle forme : utilisation de la méthode getInit().
290
	    			$this->_ini[$cle] = $val;
291
	    		}
292
	    	}
293
	    	self::$_static_ini = $this->_ini;
294
	    	return true;
295
    	} else {
296
    		return false;
297
    	}
298
	}
299
 
300
	// Log Resource
301
	/**
302
	* Lit la valeur de l'attribut Log Resource.
303
	* Utilise le motif de conception (= design pattern) Singleton.
304
	*
305
	* @access public
306
	* @param string le préfixe du nom de fichier à créer.
307
	* @return string retourne le Log Resource.
308
	*/
309
	public static function getLogResource() {
310
		if (!isset(self::$log_resource)) {
311
			if (file_exists(self::getLogFichier()) && !self::$log_fichier_ecraser) {
312
				// Ouvre en écriture seule ; place le pointeur de fichier à la fin du fichier. Si le fichier
313
				// n'existe pas, on tente de le créer.
314
				self::$log_resource = fopen(self::getLogFichier(), 'a');
315
			} else {
316
				//Ouvre en écriture seule ; place le pointeur de fichier au début du fichier et réduit la taille
317
				// du fichier à 0. Si le fichier n'existe pas, on tente de le créer.
318
				self::$log_resource = fopen(self::getLogFichier(), 'w');
319
				$entete_utf8 = "\xEF\xBB\xBF";
320
				if (!fwrite(self::$log_resource, $entete_utf8)) {
321
					echo "Erreur écriture dans le fichier de log lors de l'ajout de l'entête UTF8.\n";
322
				}
323
			}
324
		}
325
		return self::$log_resource;
326
	}
327
 
328
	// Log Fichier
329
	/**
330
	* Lit la valeur de l'attribut Log Fichier.
331
	* Utilise le motif de conception (= design pattern) Singleton.
332
	*
333
	* @access public
334
	* @return string retourne le nom du fichier de log.
335
	*/
336
	public static function getLogFichier() {
337
		if (!isset(self::$log_fichier)) {
338
			if (self::getStaticIni('projet_nom') && self::getStaticIni('version') && self::getStaticIni('sous_version')) {
339
				$fichier =	self::getStaticIni('projet_nom').'_'.
340
							self::getStaticNom().'_'.
341
							self::getStaticParam('a').'_'.
342
							'v'.self::getStaticIni('version').'_'.self::getStaticIni('sous_version');
343
			} else {
344
				$fichier = self::getStaticNom().'_'.self::getStaticParam('a');
345
			}
346
 
347
			if (!self::$log_fichier_ecraser) {
348
				$fichier .= '_'.date('Y-m-j_H:i:s', time());
349
			}
350
			$fichier .= '.log';
351
			// Ajout du chemin vers le fichier de log et stockage dans variable static
352
			self::$log_fichier = self::getStaticIni('log_chemin').$fichier;
353
		}
354
		return self::$log_fichier;
355
	}
356
 
357
	/**
358
	 * Retourne un message d'avertissement formaté.
359
	 *
360
	 * @param string le message d'erreur avec des %s.
361
	 * @param array le tableau des paramêtres à insérer dans le message d'erreur.
362
	 * @param int le niveau de verbosité à dépasser pour afficher les messages.
363
	 * @return string le message d'erreur formaté.
364
	 */
365
	private function traiterMessage($message, $tab_arguments = array(), $niveau = 0) {
366
		// Nous ajoutons dans le texte les infos provenant de la BDD (déjà encodées en UTF-8).
367
		$texte = vsprintf($message, $tab_arguments);
368
		if ($this->getParam('v') >= $niveau) {
369
			$prefixe = '';
370
			if ($this->getIni('projet_nom') && $this->getIni('version') && $this->getIni('sous_version')) {
371
				$prefixe = $this->getIni('projet_nom').'v'.$this->getIni('version').'.'.$this->getIni('sous_version').'. ';
372
			} else {
373
				$prefixe = date('Y-m-j_H:i:s', time()).' - '.Script::getCode($niveau).' : ';
374
			}
375
			$log = $prefixe.$texte."\n";
376
			echo $log;
377
			self::setLog($log);
378
 
379
			if (!fwrite($this->getLogResource(), $log)) {
380
				trigger_error('Erreur écriture dans le fichier de log.'."\n", E_USER_WARNING);
381
			}
382
		}
383
		return "\t".$texte."\n";
384
	}
385
 
386
	/**
387
	 * Retourne un message d'erreur après avoir écrit le message danns le fichier de log.
388
	 * Si le mode verbeux est inactivé, écrit le message dans le fichier de log.
389
	 * Si le mode verbeux de niveau 1 ou plus est activé, écrit le message dans le fichier de log et dans la console.
390
	 *
391
	 * @param string le message d'erreur avec des %s.
392
	 * @param array le tableau des paramêtres à insérer dans le message d'erreur.
393
	 * @return string le message d'erreur formaté.
394
	 */
395
	protected function traiterErreur($message, $tab_arguments = array()) {
396
		$niveau = Script::ERREUR;
397
		return $this->traiterMessage($message, $tab_arguments, $niveau);
398
	}
399
 
400
	/**
401
	 * Retourne un message d'avertissement formaté.
402
	 * Si le mode verbeux de niveau 1 est activé, écrit le message dans le fichier de log.
403
	 * Si le mode verbeux de niveau 2 est activé, écrit le message dans le fichier de log et dans la console.
404
	 *
405
	 * @param string le message d'erreur avec des %s.
406
	 * @param array le tableau des paramêtres à insérer dans le message d'erreur.
407
	 * @return string le message d'erreur formaté.
408
	 */
409
	protected function traiterAttention($message, $tab_arguments = array()) {
410
		$niveau = Script::AVERTISSEMENT;
411
		return $this->traiterMessage($message, $tab_arguments, $niveau);
412
	}
413
 
414
	/**
415
	 * Retourne un message d'information formaté.
416
	 * Si le mode verbeux de niveau 2 est activé, écrit le message dans le fichier de log.
417
	 * Si le mode verbeux de niveau 3 est activé, écrit le message dans le fichier de log et dans la console.
418
	 *
419
	 * @param string le message d'information avec des %s.
420
	 * @param array le tableau des paramêtres à insérer dans le message d'erreur.
421
	 * @param int le niveau de verbosité à dépasser pour afficher les messages.
422
	 * @return string le message d'erreur formaté.
423
	 */
424
	protected function afficher($message, $tab_arguments = array(), $niveau = null) {
425
		if (is_null($niveau)) {
426
			$niveau = Script::INFO;
427
		}
428
		$msg = $this->traiterMessage($message, $tab_arguments, $niveau);
429
		return $msg ;
430
	}
431
 
432
	/**
433
	 * Méthode prenant en paramètre un chemin de fichier squelette et un tableau associatif de données,
434
	 * en extrait les variables, charge le squelette et retourne le résultat des deux combinés.
435
	 *
436
	 * @param String $fichier	le chemin du fichier du squelette
437
	 * @param Array  $donnees	un tableau associatif contenant les variables a injecter dans le squelette.
438
	 *
439
	 * @return boolean false si le squelette n'existe pas, sinon la chaine résultat.
440
	 */
441
	public static function traiterSquelettePhp($fichier, Array $donnees = array()) {
442
		$sortie = false;
443
		if (file_exists($fichier)) {
444
			// Extraction des variables du tableau de données
445
			extract($donnees);
446
			// Démarage de la bufferisation de sortie
447
			ob_start();
448
			// Si les tags courts sont activés
449
			if ((bool) @ini_get('short_open_tag') === true) {
450
				// Simple inclusion du squelette
451
				include $fichier;
452
			} else {
453
				// Sinon, remplacement des tags courts par la syntaxe classique avec echo
454
				$html_et_code_php = self::traiterTagsCourts($fichier);
455
				// Pour évaluer du php mélangé dans du html il est nécessaire de fermer la balise php ouverte par eval
456
				$html_et_code_php = '?>'.$html_et_code_php;
457
				// Interprétation du html et du php dans le buffer
458
				echo eval($html_et_code_php);
459
			}
460
			// Récupèration du contenu du buffer
461
			$sortie = ob_get_contents();
462
			// Suppression du buffer
463
			@ob_end_clean();
464
		} else {
465
			$msg = "Le fichier du squelette '$fichier' n'existe pas.";
466
			trigger_error($msg, E_USER_WARNING);
467
		}
468
		// Retourne le contenu
469
		return $sortie;
470
	}
471
 
472
	/**
473
	 * Fonction chargeant le contenu du squelette et remplaçant les tags court php (<?= ...) par un tag long avec echo.
474
	 *
475
	 * @param String $chemin_squelette le chemin du fichier du squelette
476
	 *
477
	 * @return string le contenu du fichier du squelette php avec les tags courts remplacés.
478
	 */
479
	private static function traiterTagsCourts($chemin_squelette) {
480
		$contenu = file_get_contents($chemin_squelette);
481
		// Remplacement de tags courts par un tag long avec echo
482
		$contenu = str_replace('<?=', '<?php echo ',  $contenu);
483
		// Ajout systématique d'un point virgule avant la fermeture php
484
		$contenu = preg_replace("/;*\s*\?>/", "; ?>", $contenu);
485
		return $contenu;
486
	}
487
 
488
	/**
489
	 * Créer et stocke du contenu dans un fichier.
490
	 *
491
	 * @param string le chemin et le nom du fichier.
492
	 * @param string le contenu à stocker dans le fichier.
26 jpm 493
	 * @param boolean true pour compresser (gz) le fichier. Par défaut vaut false.
20 jpm 494
	 * @return string le message d'erreur formaté.
495
	 */
496
	protected function creerFichier($fichier, $contenu, $compression = false) {
497
		$e = null;
498
		if ($compression) {
499
			// Ajout de l'extension gz
500
			if (substr($fichier, -3) != '.gz') {
501
				$fichier = $fichier.'.gz';
502
			}
503
			// Début de l'écriture du fichier compressé
504
			if ($resource = gzopen($fichier, 'w9')) {
505
				if (!gzwrite($resource, $contenu)) {
506
					$e = "Le contenu texte n'a pas pu être écrit dans le fichier compressé '$fichier'.";
507
				}
508
				if (!gzclose($resource)) {
509
					$e = "Le fichier compressé '$fichier' n'a pas pu être fermé.";
510
				}
511
			} else {
512
				$e = "Le fichier compressé '$fichier' n'a pas pu être ouvert.";
513
			}
514
		} else {
515
			if ($resource = fopen($fichier, 'w')) {
516
				if (!fwrite($resource, $contenu)) {
517
					$e = "Le contenu texte n'a pas pu être écrit dans le fichier '$fichier'.";
518
				}
519
				if (!fclose($resource)) {
520
					$e = "Le fichier '$fichier' n'a pas pu être fermé.";
521
				}
522
			} else {
523
				$e = "Le fichier '$fichier' n'a pas pu être ouvert.";
524
			}
525
		}
526
		if (is_null($e)) {
527
			return true;
528
		} else {
529
			trigger_error($e, E_USER_WARNING);
530
			return false;
531
		}
532
	}
533
 
534
	/**
535
	 * Méthode permettant d'encoder de l'iso-8859-15 vers utf-8 un tableau de variables.
536
	 *
537
	 * @param mixed la chaine ou le tableau à encoder en utf-8 depuis l'iso-8859-15.
538
	 * @param string l'encodage d'origine si ce n'est pas ISO-8859-15.
539
	 * @return mixed la chaine ou le tableau encodé en utf-8.
540
	 * @access protected
541
	 */
542
	protected function encoderUtf8( &$val, $encodage = 'ISO-8859-15') {
543
		//echo print_r($val, true)."\n";
544
		if (is_array($val)) {
545
			foreach ($val as $c => $v) {
546
				$val[$c] = $this->encoderUtf8($v);
547
			}
548
		} else {
549
			// Nous vérifions si nous avons un bon encodage UTF-8
550
			if (!is_numeric($val) && !empty($val) && !$this->detecterUtf8($val)) {
551
				// Les nombres, les valeurs vides et ce qui est déjà en UTF-8 ne sont pas encodés.
552
				$val = mb_convert_encoding($val, 'UTF-8', $encodage);
553
			}
554
		}
555
		return $val;
556
	}
557
 
558
	/**
559
	 * Méthode permettant de détecter réellement l'encodage utf8.
560
	 * mb_detect_encoding plante si la chaine de caractère se termine par un caractère accentué.
561
	 * Provient de  PHPDIG.
562
	 *
563
	 * @param string la chaine à vérifier.
564
	 * @return bool true si c'est de l'utf8, sinon false.
565
	 * @access private
566
	 */
567
	private function detecterUtf8($str) {
568
		if ($str === mb_convert_encoding(mb_convert_encoding($str, 'UTF-32', 'UTF-8'), 'UTF-8', 'UTF-32')) {
569
			return true;
570
		} else {
571
			return false;
572
		}
573
	}
574
}
26 jpm 575
?>