Joomla Platform  13.1
Documentation des API du framework Joomla Platform
 Tout Classes Espaces de nommage Fichiers Fonctions Variables Pages
log.php
Aller à la documentation de ce fichier.
1 <?php
2 /**
3  * @package Joomla.Platform
4  * @subpackage Log
5  *
6  * @copyright Copyright (C) 2005 - 2013 Open Source Matters, Inc. All rights reserved.
7  * @license GNU General Public License version 2 or later; see LICENSE
8  */
9 
10 defined('JPATH_PLATFORM') or die;
11 
12 /**
13  * Joomla! Log Class
14  *
15  * This class hooks into the global log configuration settings to allow for user configured
16  * logging events to be sent to where the user wishes them to be sent. On high load sites
17  * Syslog is probably the best (pure PHP function), then the text file based loggers (CSV, W3c
18  * or plain Formattedtext) and finally MySQL offers the most features (e.g. rapid searching)
19  * but will incur a performance hit due to INSERT being issued.
20  *
21  * @package Joomla.Platform
22  * @subpackage Log
23  * @since 11.1
24  */
25 class JLog
26 {
27  /**
28  * All log priorities.
29  * @var integer
30  * @since 11.1
31  */
32  const ALL = 30719;
33 
34  /**
35  * The system is unusable.
36  * @var integer
37  * @since 11.1
38  */
39  const EMERGENCY = 1;
40 
41  /**
42  * Action must be taken immediately.
43  * @var integer
44  * @since 11.1
45  */
46  const ALERT = 2;
47 
48  /**
49  * Critical conditions.
50  * @var integer
51  * @since 11.1
52  */
53  const CRITICAL = 4;
54 
55  /**
56  * Error conditions.
57  * @var integer
58  * @since 11.1
59  */
60  const ERROR = 8;
61 
62  /**
63  * Warning conditions.
64  * @var integer
65  * @since 11.1
66  */
67  const WARNING = 16;
68 
69  /**
70  * Normal, but significant condition.
71  * @var integer
72  * @since 11.1
73  */
74  const NOTICE = 32;
75 
76  /**
77  * Informational message.
78  * @var integer
79  * @since 11.1
80  */
81  const INFO = 64;
82 
83  /**
84  * Debugging message.
85  * @var integer
86  * @since 11.1
87  */
88  const DEBUG = 128;
89 
90  /**
91  * The global JLog instance.
92  * @var JLog
93  * @since 11.1
94  */
95  protected static $instance;
96 
97  /**
98  * Container for JLogLogger configurations.
99  * @var array
100  * @since 11.1
101  */
102  protected $configurations = array();
103 
104  /**
105  * Container for JLogLogger objects.
106  * @var array
107  * @since 11.1
108  */
109  protected $loggers = array();
110 
111  /**
112  * Lookup array for loggers.
113  * @var array
114  * @since 11.1
115  */
116  protected $lookup = array();
117 
118  /**
119  * Constructor.
120  *
121  * @since 11.1
122  */
123  protected function __construct()
124  {
125  }
126 
127  /**
128  * Method to add an entry to the log.
129  *
130  * @param mixed $entry The JLogEntry object to add to the log or the message for a new JLogEntry object.
131  * @param integer $priority Message priority.
132  * @param string $category Type of entry
133  * @param string $date Date of entry (defaults to now if not specified or blank)
134  *
135  * @return void
136  *
137  * @since 11.1
138  */
139  public static function add($entry, $priority = self::INFO, $category = '', $date = null)
140  {
141  // Automatically instantiate the singleton object if not already done.
142  if (empty(self::$instance))
143  {
144  self::setInstance(new JLog);
145  }
146 
147  // If the entry object isn't a JLogEntry object let's make one.
148  if (!($entry instanceof JLogEntry))
149  {
150  $entry = new JLogEntry((string) $entry, $priority, $category, $date);
151  }
152 
153  self::$instance->addLogEntry($entry);
154  }
155 
156  /**
157  * Add a logger to the JLog instance. Loggers route log entries to the correct files/systems to be logged.
158  *
159  * @param array $options The object configuration array.
160  * @param integer $priorities Message priority
161  * @param array $categories Types of entry
162  * @param boolean $exclude If true, all categories will be logged except those in the $categories array
163  *
164  * @return void
165  *
166  * @since 11.1
167  */
168  public static function addLogger(array $options, $priorities = self::ALL, $categories = array(), $exclude = false)
169  {
170  // Automatically instantiate the singleton object if not already done.
171  if (empty(self::$instance))
172  {
173  self::setInstance(new JLog);
174  }
175 
176  // The default logger is the formatted text log file.
177  if (empty($options['logger']))
178  {
179  $options['logger'] = 'formattedtext';
180  }
181  $options['logger'] = strtolower($options['logger']);
182 
183  // Special case - if a Closure object is sent as the callback (in case of JLogLoggerCallback)
184  // Closure objects are not serializable so swap it out for a unique id first then back again later
185  if (isset($options['callback']) && is_a($options['callback'], 'closure'))
186  {
187  $callback = $options['callback'];
188  $options['callback'] = spl_object_hash($options['callback']);
189  }
190 
191  // Generate a unique signature for the JLog instance based on its options.
192  $signature = md5(serialize($options));
193 
194  // Now that the options array has been serialized, swap the callback back in
195  if (isset($callback))
196  {
197  $options['callback'] = $callback;
198  }
199 
200  // Register the configuration if it doesn't exist.
201  if (empty(self::$instance->configurations[$signature]))
202  {
203  self::$instance->configurations[$signature] = $options;
204  }
205 
206  self::$instance->lookup[$signature] = (object) array(
207  'priorities' => $priorities,
208  'categories' => array_map('strtolower', (array) $categories),
209  'exclude' => (bool) $exclude);
210  }
211 
212  /**
213  * Returns a reference to the a JLog object, only creating it if it doesn't already exist.
214  * Note: This is principally made available for testing and internal purposes.
215  *
216  * @param JLog $instance The logging object instance to be used by the static methods.
217  *
218  * @return void
219  *
220  * @since 11.1
221  */
222  public static function setInstance($instance)
223  {
224  if (($instance instanceof JLog) || $instance === null)
225  {
226  self::$instance = & $instance;
227  }
228  }
229 
230  /**
231  * Method to add an entry to the appropriate loggers.
232  *
233  * @param JLogEntry $entry The JLogEntry object to send to the loggers.
234  *
235  * @return void
236  *
237  * @since 11.1
238  * @throws RuntimeException
239  */
240  protected function addLogEntry(JLogEntry $entry)
241  {
242  // Find all the appropriate loggers based on priority and category for the entry.
243  $loggers = $this->findLoggers($entry->priority, $entry->category);
244 
245  foreach ((array) $loggers as $signature)
246  {
247  // Attempt to instantiate the logger object if it doesn't already exist.
248  if (empty($this->loggers[$signature]))
249  {
250 
251  $class = 'JLogLogger' . ucfirst($this->configurations[$signature]['logger']);
252 
253  if (class_exists($class))
254  {
255  $this->loggers[$signature] = new $class($this->configurations[$signature]);
256  }
257  else
258  {
259  throw new RuntimeException('Unable to create a JLogLogger instance: ' . $class);
260  }
261  }
262 
263  // Add the entry to the logger.
264  $this->loggers[$signature]->addEntry(clone($entry));
265  }
266  }
267 
268  /**
269  * Method to find the loggers to use based on priority and category values.
270  *
271  * @param integer $priority Message priority.
272  * @param string $category Type of entry
273  *
274  * @return array The array of loggers to use for the given priority and category values.
275  *
276  * @since 11.1
277  */
278  protected function findLoggers($priority, $category)
279  {
280  $loggers = array();
281 
282  // Sanitize inputs.
283  $priority = (int) $priority;
284  $category = strtolower($category);
285 
286  // Let's go iterate over the loggers and get all the ones we need.
287  foreach ((array) $this->lookup as $signature => $rules)
288  {
289  // Check to make sure the priority matches the logger.
290  if ($priority & $rules->priorities)
291  {
292  if ($rules->exclude)
293  {
294  // If either there are no set categories or the category (including the empty case) is not in the list of excluded categories, add this logger.
295  if (empty($rules->categories) || !in_array($category, $rules->categories))
296  {
297  $loggers[] = $signature;
298  }
299  }
300  else
301  {
302  // If either there are no set categories (meaning all) or the specific category is set, add this logger.
303  if (empty($category) || empty($rules->categories) || in_array($category, $rules->categories))
304  {
305  $loggers[] = $signature;
306  }
307  }
308  }
309  }
310 
311  return $loggers;
312  }
313 }