Subversion Repositories Applications.framework

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
464 jpm 1
<?php
2
// declare(encoding='UTF-8');
3
/**
4
 * Classe de gestion des exceptions.
5
 * C'est un Singleton.
6
 *
7
 * @category	PHP 5.2
8
 * @package	Framework
9
 * @author		Aurélien PERONNET <aurelien@tela-botanica.org>
10
 * @author		Jean-Pascal MILCENT <jmp@tela-botanica.org>
11
 * @copyright	Copyright (c) 2009, Tela Botanica (accueil@tela-botanica.org)
12
 * @license	http://www.cecill.info/licences/Licence_CeCILL_V2-fr.txt Licence CECILL
13
 * @license	http://www.gnu.org/licenses/gpl.html Licence GNU-GPL
14
 * @version	$Id: GestionnaireException.php 369 2011-10-03 12:47:17Z jpm $$
15
 * @link		/doc/framework/
16
 *
17
 */
18
class GestionnaireException {
19
 
20
	const MODE_CLI = 'cli';
21
 
22
	/** Liste des exceptions enregistrées */
23
	private static $exceptions = array();
24
 
25
	/** Détermine si l'on affiche ou non le contexte */
26
	private static $contexte = false;
27
 
28
	 /** Détermine si l'on loggue ou non les erreurs */
29
	private static $logger = false;
30
 
31
	/** Détermine si l'affichage des erreurs est forcé (true) ou pas (false) à la destruction de la classe */
32
	private static $afficher = false;
33
 
34
	/** Definit si php est lancé en ligne de commande ou en mode serveur */
35
	private static $mode = null ;
36
 
37
	/** Tableau des noms des paramètres à définir dans le fichier de config car obligatoirement nécessaire à cette classe.*/
38
	private static $parametres_obligatoires = array('debogage', 'debogage_contexte', 'log_debogage');
39
 
40
	/** Initialise le Gestionnaire d'exceptions et d'erreur sans tenir comptes des paramêtres de config. */
41
	public static function initialiser() {
42
		self::$mode = php_sapi_name();
43
		// Désactivation des balises HTML dans les messages d'erreur de PHP en mode ligne de commande
44
		if (self::$mode == self::MODE_CLI) {
45
			ini_set('html_errors', 0);
46
		}
47
 
48
		set_exception_handler(array(get_class(),'gererException'));
49
		set_error_handler(array(get_class(),'gererErreur'));
50
	}
51
 
52
	/** Configure le Gestionnaire d'exceptions et d'erreur à partir des paramêtres de config. */
53
	public static function configurer() {
54
		Config::verifierPresenceParametres(self::$parametres_obligatoires);
55
		self::$contexte = Config::get('debogage_contexte');
56
		self::$logger = Config::get('log_debogage');
57
		self::$afficher = Config::get('debogage');
58
	}
59
 
60
	/**
61
	 * Renvoie le nombre d'exceptions et d'erreurs levées.
62
	 * @see getExceptions() pour obtenir les exceptions formatées.
63
	 * @since 0.3
64
	 * @return int le nombre d'exception actuellement levées
65
	 */
66
	public static function getExceptionsNbre() {
67
		return count(self::$exceptions);
68
	}
69
 
70
	/**
71
	 * Renvoie le booleen définissant si l'on affiche le contexte ou non
72
	 * @return bool true si on affiche le contexte sinon false.
73
	 */
74
	public static function getContexte() {
75
		return self::$contexte;
76
	}
77
 
78
	/**
79
	 * Definit si l'on veut afficher le contexte ou non
80
	 * @param bool true si on veut afficher le contexte, false sinon, par défaut vaut false
81
	 */
82
	public static function setContexte($contexte) {
83
		self::$contexte = $contexte;
84
	}
85
 
86
	/**
87
	 * Fonction de gestion des exceptions, remplace le handler par défaut.
88
	 * Si une boucle génère de multiple exception (ou erreur) identique une seule sera stockée.
89
	 * @param Exception $e l'exception à traiter
90
	 */
91
	public static function gererException(Exception $e) {
92
		$cle = hash('md5', $e->getMessage().'-'.$e->getFile().'-'.$e->getLine());
93
		if (!isset(self::$exceptions[$cle])) {
94
			self::$exceptions[$cle] = $e;
95
			self::loggerException($e);
96
		}
97
	}
98
 
99
	/**
100
	 * Gère les erreurs en les convertissant en exceptions (remplace la fonction gestion d'erreurs native de php)
101
	 * @param int $niveau le niveau de l'erreur
102
	 * @param string $message le message associé à l'erreur
103
	 * @param string $fichier le nom du fichier où l'erreur s'est produite
104
	 * @param int $ligne la ligne où l'erreur s'est produite
105
	 * @param string $contexte le contexte associé à l'erreur
106
	 */
107
	public static function gererErreur($niveau,  $message,  $fichier,  $ligne,  $contexte){
108
		// Si un rapport d'erreur existe, création d'une exception
109
		if (error_reporting() != 0) {
110
			$e = new ErrorException($message, 0, $niveau, $fichier, $ligne);
111
			self::gererException($e);
112
		}
113
		return null;
114
	}
115
 
116
	/**
117
	 * Renvoie les exceptions au format (X)HTML ou bien au format texte suivant le mode d'utilisation de PHP.
118
	 * @since 0.3
119
	 * @deprecated
120
	 * @see getExceptionsFormatees()
121
	 * @return string les exceptions formatées en texte ou (X)HTML.
122
	 */
123
	public static function getExceptions() {
124
		return self::getExceptionsFormatees();
125
	}
126
 
127
	/**
128
	 * Renvoie les exceptions au format (X)HTML ou bien au format texte suivant le mode d'utilisation de PHP.
129
	 * @since 0.3
130
	 * @return string les exceptions formatées en texte ou (X)HTML.
131
	 */
132
	public static function getExceptionsFormatees() {
133
		$retour = '';
134
		if (self::getExceptionsNbre() > 0) {
135
			foreach (self::$exceptions as $cle => $e) {
136
				switch (self::$mode) {
137
					case self::MODE_CLI :
138
						$retour .= self::formaterExceptionTxt($e);
139
						break;
140
					default:
141
						$retour .= self::formaterExceptionXhtml($e);
142
				}
143
				// Nous vidons le tableau des exceptions au fur et à mesure pour éviter le réaffichage avec le destructeur.
144
				unset(self::$exceptions[$cle]);
145
			}
146
		}
147
		return $retour;
148
	}
149
 
150
	/**
151
	 * Renvoie le tableau d'objets Exception générées par le script PHP triées du niveau de sévérité le plus élevé au moins élevé.
152
	 * Format du tableau :
153
	 * array{sévérité_1 = array{Exception1, Exception2, Exception3,...}, sévérité_1 =  array{Exception1, Exception2, ...}, ...};
154
	 * ATTENTION : si vous utilisez cette méthode, c'est à vous de gérer l'affichage des Exceptions. Le gestionnaire d'exception
155
	 * n'enverra plus rien au navigateur ou à la console.
156
	 * @since 0.3
157
	 * @return array le tableau trié d'objet Exception.
158
	 */
159
	public static function getExceptionsTriees() {
160
		$retour = array();
161
		if (self::getExceptionsNbre() > 0) {
162
			foreach (self::$exceptions as $cle => $e) {
163
				$retour[$e->getSeverity()][] = $e;
164
				// Nous vidons le tableau des exceptions au fur et à mesure pour éviter le réaffichage avec le destructeur.
165
				unset(self::$exceptions[$cle]);
166
			}
167
			ksort($retour);
168
		}
169
		return $retour;
170
	}
171
 
172
	/**
173
	 * Logue une exception donnée sous une forme lisible si self::logger vaut true.
174
	 * @param Exception	$e l'exception à logger
175
	 */
176
	private static function loggerException(Exception $e) {
177
		if (self::$logger) {
178
			$message = self::formaterExceptionTxt($e);
179
			Log::ajouterEntree('erreurs', $message);
180
		}
181
	}
182
 
183
	/**
184
	 * Formate une exception de type Notice générée par la classe Debug.
185
	 * Seul le message est gardé car les autres infos font référence à la classe Debug et non à l'endroit où
186
	 * le débug est lancée.
187
	 * TODO : faire en sorte d'afficher le fichier et la ligne où le débug est lancé.
188
	 * @since 0.3
189
	 * @param Exception l'exception à formater.
190
	 */
191
	public static function formaterExceptionDebug(Exception $e) {
192
		$txt = '';
193
		if ($e->getSeverity() == E_USER_NOTICE) {
194
			$txt = $e->getMessage();
195
		} else {
196
			$txt = self::formaterExceptionTxt($e);
197
		}
198
		return $txt;
199
	}
200
 
201
	/**
202
	 * Formate en texte une exception passée en paramètre.
203
	 * @since 0.3
204
	 * @param Exception l'exception à formater.
205
	 */
206
	public static function formaterExceptionTxt(Exception $e) {
207
		$message = '';
208
		$message .= $e->getMessage()."\n";
209
		$message .= 'Fichier : '.$e->getFile()."\n";
210
		$message .= 'Ligne : '.$e->getLine()."\n";
211
		if (self::getContexte()) {
212
			$message .= 'Contexte : '."\n".print_r($e->getTraceAsString(), true)."\n";
213
		}
214
		$message .= "\n";
215
		return $message;
216
	}
217
 
218
	/**
219
	 * Formate en (X)HTML une exception passée en paramètre.
220
	 * @since 0.3
221
	 * @param Exception l'exception à formater.
222
	 */
223
	public static function formaterExceptionXhtml(Exception $e) {
224
		$message = '';
225
		$message .= '<div class="debogage">'."\n";
226
		$message .= $e->getMessage()."\n";
227
		$message .= '<span class="debogage_fichier">'.'Fichier : '.$e->getFile().'</span>'."\n";
228
		$message .= '<span class="debogage_ligne">'.'Ligne : '.$e->getLine().'</span>'."\n";
229
		if (self::getContexte()) {
230
			$message .= '<pre>'."\n";
231
			$message .= '<strong>Contexte : </strong>'."\n".print_r($e->getTraceAsString(), true)."\n";
232
			$message .= '</pre>'."\n";
233
		}
234
		$message .= '</div>'."\n";
235
		return $message;
236
	}
237
 
238
	/**
239
	 * Lors de la destruction de la classe si des exceptions n'ont pas été affichées, et si le débogage est à true, elles sont
240
	 * affichées.
241
	 */
242
	public function __destruct() {
243
		// Si des erreurs n'ont pas été affichée nous forçons leur affichage
244
		if (self::$afficher && self::getExceptionsNbre() > 0) {
245
			echo self::getExceptionsFormatees();
246
		}
247
	}
248
 
249
}
250
?>