PageRenderTime 44ms CodeModel.GetById 17ms RepoModel.GetById 0ms app.codeStats 0ms

/libraries/joomla/log/log.php

https://bitbucket.org/eternaware/joomus
PHP | 300 lines | 106 code | 35 blank | 159 comment | 16 complexity | 2f068a07b70a4e2db4683a32c45bbd8a MD5 | raw file
Possible License(s): LGPL-2.1
  1. <?php
  2. /**
  3. * @package Joomla.Platform
  4. * @subpackage Log
  5. *
  6. * @copyright Copyright (C) 2005 - 2012 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. *
  144. * @return void
  145. *
  146. * @since 11.1
  147. */
  148. public static function addLogger(array $options, $priorities = self::ALL, $categories = array())
  149. {
  150. // Automatically instantiate the singleton object if not already done.
  151. if (empty(self::$instance))
  152. {
  153. self::setInstance(new JLog);
  154. }
  155. // The default logger is the formatted text log file.
  156. if (empty($options['logger']))
  157. {
  158. $options['logger'] = 'formattedtext';
  159. }
  160. $options['logger'] = strtolower($options['logger']);
  161. // Special case - if a Closure object is sent as the callback (in case of JLoggerCallback)
  162. // Closure objects are not serializable so swap it out for a unique id first then back again later
  163. if (isset($options['callback']) && is_a($options['callback'], 'closure'))
  164. {
  165. $callback = $options['callback'];
  166. $options['callback'] = spl_object_hash($options['callback']);
  167. }
  168. // Generate a unique signature for the JLog instance based on its options.
  169. $signature = md5(serialize($options));
  170. // Now that the options array has been serialized, swap the callback back in
  171. if (isset($callback))
  172. {
  173. $options['callback'] = $callback;
  174. }
  175. // Register the configuration if it doesn't exist.
  176. if (empty(self::$instance->configurations[$signature]))
  177. {
  178. self::$instance->configurations[$signature] = $options;
  179. }
  180. self::$instance->lookup[$signature] = (object) array(
  181. 'priorities' => $priorities,
  182. 'categories' => array_map('strtolower', (array) $categories));
  183. }
  184. /**
  185. * Returns a reference to the a JLog object, only creating it if it doesn't already exist.
  186. * Note: This is principally made available for testing and internal purposes.
  187. *
  188. * @param JLog $instance The logging object instance to be used by the static methods.
  189. *
  190. * @return void
  191. *
  192. * @since 11.1
  193. */
  194. public static function setInstance($instance)
  195. {
  196. if (($instance instanceof JLog) || $instance === null)
  197. {
  198. self::$instance = & $instance;
  199. }
  200. }
  201. /**
  202. * Method to add an entry to the appropriate loggers.
  203. *
  204. * @param JLogEntry $entry The JLogEntry object to send to the loggers.
  205. *
  206. * @return void
  207. *
  208. * @since 11.1
  209. * @throws RuntimeException
  210. */
  211. protected function addLogEntry(JLogEntry $entry)
  212. {
  213. // Find all the appropriate loggers based on priority and category for the entry.
  214. $loggers = $this->findLoggers($entry->priority, $entry->category);
  215. foreach ((array) $loggers as $signature)
  216. {
  217. // Attempt to instantiate the logger object if it doesn't already exist.
  218. if (empty($this->loggers[$signature]))
  219. {
  220. $class = 'JLogLogger' . ucfirst($this->configurations[$signature]['logger']);
  221. if (class_exists($class))
  222. {
  223. $this->loggers[$signature] = new $class($this->configurations[$signature]);
  224. }
  225. else
  226. {
  227. throw new RuntimeException('Unable to create a JLogLogger instance: ' . $class);
  228. }
  229. }
  230. // Add the entry to the logger.
  231. $this->loggers[$signature]->addEntry(clone($entry));
  232. }
  233. }
  234. /**
  235. * Method to find the loggers to use based on priority and category values.
  236. *
  237. * @param integer $priority Message priority.
  238. * @param string $category Type of entry
  239. *
  240. * @return array The array of loggers to use for the given priority and category values.
  241. *
  242. * @since 11.1
  243. */
  244. protected function findLoggers($priority, $category)
  245. {
  246. $loggers = array();
  247. // Sanitize inputs.
  248. $priority = (int) $priority;
  249. $category = strtolower($category);
  250. // Let's go iterate over the loggers and get all the ones we need.
  251. foreach ((array) $this->lookup as $signature => $rules)
  252. {
  253. // Check to make sure the priority matches the logger.
  254. if ($priority & $rules->priorities)
  255. {
  256. // If either there are no set categories (meaning all) or the specific category is set, add this logger.
  257. if (empty($category) || empty($rules->categories) || in_array($category, $rules->categories))
  258. {
  259. $loggers[] = $signature;
  260. }
  261. }
  262. }
  263. return $loggers;
  264. }
  265. }