Subversion Repositories Applications.referentiel

Rev

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