PageRenderTime 48ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 1ms

/libraries/joomla/log/log.php

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