Subversion Repositories Applications.framework

Rev

Rev 369 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5 aurelien 1
<?php
105 aurelien 2
// declare(encoding='UTF-8');
5 aurelien 3
/**
142 jpm 4
 * Classe de gestion des exceptions.
5
 * C'est un Singleton.
129 aurelien 6
 *
232 jpm 7
 * @category	PHP 5.2
8
 * @package	Framework
9
 * @author		Aurélien PERONNET <aurelien@tela-botanica.org>
241 jpm 10
 * @author		Jean-Pascal MILCENT <jmp@tela-botanica.org>
232 jpm 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 497 2019-09-17 09:49:05Z killian $$
15
 * @link		/doc/framework/
129 aurelien 16
 *
17
 */
5 aurelien 18
class GestionnaireException {
192 jpm 19
 
20
	const MODE_CLI = 'cli';
21
 
22
	/** Liste des exceptions enregistrées */
120 aurelien 23
	private static $exceptions = array();
24
 
192 jpm 25
	/** Détermine si l'on affiche ou non le contexte */
120 aurelien 26
	private static $contexte = false;
27
 
192 jpm 28
	 /** Détermine si l'on loggue ou non les erreurs */
129 aurelien 29
	private static $logger = false;
122 aurelien 30
 
192 jpm 31
	/** Détermine si l'affichage des erreurs est forcé (true) ou pas (false) à la destruction de la classe */
160 aurelien 32
	private static $afficher = false;
33
 
192 jpm 34
	/** Definit si php est lancé en ligne de commande ou en mode serveur */
161 aurelien 35
	private static $mode = null ;
120 aurelien 36
 
241 jpm 37
	/** Tableau des noms des paramètres à définir dans le fichier de config car obligatoirement nécessaire à cette classe.*/
274 jpm 38
	private static $parametres_obligatoires = array('debogage', 'debogage_contexte', 'log_debogage');
241 jpm 39
 
192 jpm 40
	/** Initialise le Gestionnaire d'exceptions et d'erreur sans tenir comptes des paramêtres de config. */
189 jpm 41
	public static function initialiser() {
42
		self::$mode = php_sapi_name();
192 jpm 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
 
189 jpm 48
		set_exception_handler(array(get_class(),'gererException'));
49
		set_error_handler(array(get_class(),'gererErreur'));
50
	}
51
 
192 jpm 52
	/** Configure le Gestionnaire d'exceptions et d'erreur à partir des paramêtres de config. */
189 jpm 53
	public static function configurer() {
241 jpm 54
		Config::verifierPresenceParametres(self::$parametres_obligatoires);
274 jpm 55
		self::$contexte = Config::get('debogage_contexte');
56
		self::$logger = Config::get('log_debogage');
57
		self::$afficher = Config::get('debogage');
5 aurelien 58
	}
189 jpm 59
 
232 jpm 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
	 */
120 aurelien 74
	public static function getContexte() {
129 aurelien 75
		return self::$contexte;
5 aurelien 76
	}
120 aurelien 77
 
5 aurelien 78
	/**
79
	 * Definit si l'on veut afficher le contexte ou non
105 aurelien 80
	 * @param bool true si on veut afficher le contexte, false sinon, par défaut vaut false
5 aurelien 81
	 */
160 aurelien 82
	public static function setContexte($contexte) {
129 aurelien 83
		self::$contexte = $contexte;
5 aurelien 84
	}
120 aurelien 85
 
5 aurelien 86
	/**
216 jpm 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.
129 aurelien 89
	 * @param Exception $e l'exception à traiter
5 aurelien 90
	 */
497 killian 91
	public static function gererException(Throwable $e) {
216 jpm 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
		}
5 aurelien 97
	}
120 aurelien 98
 
129 aurelien 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
	 */
120 aurelien 107
	public static function gererErreur($niveau,  $message,  $fichier,  $ligne,  $contexte){
189 jpm 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);
216 jpm 111
			self::gererException($e);
120 aurelien 112
		}
189 jpm 113
		return null;
120 aurelien 114
	}
115
 
5 aurelien 116
	/**
232 jpm 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.
5 aurelien 122
	 */
120 aurelien 123
	public static function getExceptions() {
232 jpm 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() {
114 jp_milcent 133
		$retour = '';
232 jpm 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]);
98 jpm 145
			}
5 aurelien 146
		}
147
		return $retour;
148
	}
232 jpm 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
	}
5 aurelien 171
 
129 aurelien 172
	/**
189 jpm 173
	 * Logue une exception donnée sous une forme lisible si self::logger vaut true.
129 aurelien 174
	 * @param Exception	$e l'exception à logger
175
	 */
497 killian 176
	private static function loggerException(Throwable $e) {
189 jpm 177
		if (self::$logger) {
232 jpm 178
			$message = self::formaterExceptionTxt($e);
179
			Log::ajouterEntree('erreurs', $message);
129 aurelien 180
		}
181
	}
232 jpm 182
 
183
	/**
365 jpm 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
	 */
497 killian 191
	public static function formaterExceptionDebug(Throwable $e) {
369 jpm 192
		$txt = '';
193
		if ($e->getSeverity() == E_USER_NOTICE) {
194
			$txt = $e->getMessage();
195
		} else {
196
			$txt = self::formaterExceptionTxt($e);
197
		}
198
		return $txt;
365 jpm 199
	}
200
 
201
	/**
232 jpm 202
	 * Formate en texte une exception passée en paramètre.
203
	 * @since 0.3
204
	 * @param Exception l'exception à formater.
205
	 */
497 killian 206
	public static function formaterExceptionTxt(Throwable $e) {
232 jpm 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
	 */
497 killian 223
	public static function formaterExceptionXhtml(Throwable $e) {
232 jpm 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
	 */
135 aurelien 242
	public function __destruct() {
142 jpm 243
		// Si des erreurs n'ont pas été affichée nous forçons leur affichage
232 jpm 244
		if (self::$afficher && self::getExceptionsNbre() > 0) {
245
			echo self::getExceptionsFormatees();
142 jpm 246
		}
135 aurelien 247
	}
248
 
120 aurelien 249
}
497 killian 250
?>