PageRenderTime 57ms CodeModel.GetById 29ms RepoModel.GetById 0ms app.codeStats 0ms

/libraries/joomla/log/log.php

https://bitbucket.org/joomla/joomla-platform/
PHP | 389 lines | 147 code | 50 blank | 192 comment | 21 complexity | 641a6786ebe0efefe3ec680dc5406753 MD5 | raw file
Possible License(s): GPL-2.0, LGPL-2.1, BSD-3-Clause
  1. <?php
  2. /**
  3. * @package Joomla.Platform
  4. * @subpackage Log
  5. *
  6. * @copyright Copyright (C) 2005 - 2011 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. jimport('joomla.log.logentry');
  11. jimport('joomla.log.logexception');
  12. jimport('joomla.log.logger');
  13. JLoader::discover('JLogger', dirname(__FILE__).'/loggers');
  14. // @deprecated 11.2
  15. jimport('joomla.filesystem.path');
  16. /**
  17. * Joomla! Log Class
  18. *
  19. * This class hooks into the global log configuration settings to allow for user configured
  20. * logging events to be sent to where the user wishes them to be sent. On high load sites
  21. * SysLog is probably the best (pure PHP function), then the text file based loggers (CSV, W3C
  22. * or plain FormattedText) and finally MySQL offers the most features (e.g. rapid searching)
  23. * but will incur a performance hit due to INSERT being issued.
  24. *
  25. * @package Joomla.Platform
  26. * @subpackage Log
  27. * @since 11.1
  28. */
  29. class JLog
  30. {
  31. /**
  32. * @var integer All log priorities.
  33. * @since 11.1
  34. */
  35. const ALL = 30719;
  36. /**
  37. * @var integer The system is unusable.
  38. * @since 11.1
  39. */
  40. const EMERGENCY = 1;
  41. /**
  42. * @var integer Action must be taken immediately.
  43. * @since 11.1
  44. */
  45. const ALERT = 2;
  46. /**
  47. * @var integer Critical conditions.
  48. * @since 11.1
  49. */
  50. const CRITICAL = 4;
  51. /**
  52. * @var integer Error conditions.
  53. * @since 11.1
  54. */
  55. const ERROR = 8;
  56. /**
  57. * @var integer Warning conditions.
  58. * @since 11.1
  59. */
  60. const WARNING = 16;
  61. /**
  62. * @var integer Normal, but significant condition.
  63. * @since 11.1
  64. */
  65. const NOTICE = 32;
  66. /**
  67. * @var integer Informational message.
  68. * @since 11.1
  69. */
  70. const INFO = 64;
  71. /**
  72. * @var integer Debugging message.
  73. * @since 11.1
  74. */
  75. const DEBUG = 128;
  76. /**
  77. * @var JLog The global JLog instance.
  78. * @since 11.1
  79. */
  80. protected static $instance;
  81. /**
  82. * @var array The array of instances created through the deprecated getInstance method.
  83. * @since 11.1
  84. * @see JLog::getInstance()
  85. * @deprecated 11.2
  86. */
  87. public static $legacy = array();
  88. /**
  89. * @var array Container for JLogger configurations.
  90. * @since 11.1
  91. */
  92. protected $configurations = array();
  93. /**
  94. * @var array Container for JLogger objects.
  95. * @since 11.1
  96. */
  97. protected $loggers = array();
  98. /**
  99. * @var array Lookup array for loggers.
  100. * @since 11.1
  101. */
  102. protected $lookup = array();
  103. /**
  104. * Constructor.
  105. *
  106. * @return void
  107. *
  108. * @since 11.1
  109. */
  110. protected function __construct()
  111. {
  112. }
  113. /**
  114. * Method to add an entry to the log.
  115. *
  116. * @param mixed $entry The JLogEntry object to add to the log or the message for a new JLogEntry object.
  117. * @param integer $priority Message priority.
  118. * @param string $category Type of entry
  119. * @param string $date Date of entry (defaults to now if not specified or blank)
  120. *
  121. * @return void
  122. *
  123. * @since 11.1
  124. */
  125. public static function add($entry, $priority = JLog::INFO, $category = '', $date = null)
  126. {
  127. // Automatically instantiate the singleton object if not already done.
  128. if (empty(self::$instance)) {
  129. self::setInstance(new JLog());
  130. }
  131. // If the entry object isn't a JLogEntry object let's make one.
  132. if (!($entry instanceof JLogEntry)) {
  133. $entry = new JLogEntry((string) $entry, $priority, $category, $date);
  134. }
  135. self::$instance->addLogEntry($entry);
  136. }
  137. /**
  138. * Method to set the way the JError will handle different error levels.
  139. * Use this if you want to override the default settings.
  140. *
  141. * @param array $options The object configuration array.
  142. * @param integer $priorities ...
  143. * @param array $categories ...
  144. * @return void
  145. *
  146. * @since 11.1
  147. */
  148. public static function addLogger(array $options, $priorities = JLog::ALL, $categories = array())
  149. {
  150. // Automatically instantiate the singleton object if not already done.
  151. if (empty(self::$instance)) {
  152. self::setInstance(new JLog());
  153. }
  154. // The default logger is the formatted text log file.
  155. if (empty($options['logger'])) {
  156. $options['logger'] = 'formattedtext';
  157. }
  158. $options['logger'] = strtolower($options['logger']);
  159. // Generate a unique signature for the JLog instance based on its options.
  160. $signature = md5(serialize($options));
  161. // Register the configuration if it doesn't exist.
  162. if (empty(self::$instance->configurations[$signature])) {
  163. self::$instance->configurations[$signature] = $options;
  164. }
  165. self::$instance->lookup[$signature] = (object) array('priorities' => $priorities, 'categories' => array_map('strtolower', (array) $categories));
  166. }
  167. /**
  168. * Returns a JLog object for a given log file/configuration, only creating it if it doesn't already exist.
  169. *
  170. * This method must be invoked as:
  171. * <pre>$log = JLog::getInstance($file, $options, $path);</pre>
  172. *
  173. * @param string $file The filename of the log file.
  174. * @param array $options The object configuration array.
  175. * @param string $path The base path for the log file.
  176. *
  177. * @return JLog
  178. *
  179. * @deprecated 11.2
  180. * @since 11.1
  181. */
  182. public static function getInstance($file = 'error.php', $options = null, $path = null)
  183. {
  184. // Deprecation warning.
  185. JLog::add('JLog::getInstance() is deprecated. See JLog::addLogger().', JLog::WARNING, 'deprecated');
  186. // Get the system configuration object.
  187. $config = JFactory::getConfig();
  188. // Set default path if not set and sanitize it.
  189. if (!$path) {
  190. $path = $config->get('log_path');
  191. }
  192. // If no options were explicitly set use the default from configuration.
  193. if (empty($options)) {
  194. $options = (array) $config->getValue('log_options');
  195. }
  196. // Fix up the options so that we use the w3c format.
  197. $options['text_entry_format'] = empty($options['format']) ? null : $options['format'];
  198. $options['text_file'] = $file;
  199. $options['text_file_path'] = $path;
  200. $options['logger'] = 'w3c';
  201. // Generate a unique signature for the JLog instance based on its options.
  202. $signature = md5(serialize($options));
  203. // Only create the object if not already created.
  204. if (empty(self::$legacy[$signature])) {
  205. self::$legacy[$signature] = new JLog();
  206. // Register the configuration.
  207. self::$legacy[$signature]->configurations[$signature] = $options;
  208. // Setup the lookup to catch all.
  209. self::$legacy[$signature]->lookup[$signature] = (object) array('priorities' => JLog::ALL, 'categories' => array());
  210. }
  211. return self::$legacy[$signature];
  212. }
  213. /**
  214. * Returns a reference to the a JLog object, only creating it if it doesn't already exist.
  215. * Note: This is principly made available for testing and internal purposes.
  216. *
  217. * @param JLog $instance The logging object instance to be used by the static methods.
  218. *
  219. * @return void
  220. *
  221. * @since 11.1
  222. */
  223. public static function setInstance($instance)
  224. {
  225. if (($instance instanceof JLog) || $instance === null) {
  226. self::$instance = & $instance;
  227. }
  228. }
  229. /**
  230. * Method to add an entry to the log file.
  231. *
  232. * @param array Array of values to map to the format string for the log file.
  233. *
  234. * @return boolean True on success.
  235. *
  236. * @deprecated 11.2
  237. * @since 11.1
  238. */
  239. public function addEntry($entry)
  240. {
  241. // Deprecation warning.
  242. JLog::add('JLog::addEntry() is deprecated, use JLog::add() instead.', JLog::WARNING, 'deprecated');
  243. // Easiest case is we already have a JLogEntry object to add.
  244. if ($entry instanceof JLogEntry) {
  245. return $this->addLogEntry($entry);
  246. }
  247. // We have either an object or array that needs to be converted to a JLogEntry.
  248. elseif (is_array($entry) || is_object($entry)) {
  249. $tmp = new JLogEntry('');
  250. foreach ((array) $entry as $k => $v)
  251. {
  252. switch ($k)
  253. {
  254. case 'c-ip':
  255. $tmp->clientIP = $v;
  256. break;
  257. case 'status':
  258. $tmp->category = $v;
  259. break;
  260. case 'level':
  261. $tmp->priority = $v;
  262. break;
  263. case 'comment':
  264. $tmp->message = $v;
  265. break;
  266. default:
  267. $tmp->$k = $v;
  268. break;
  269. }
  270. }
  271. }
  272. // Unrecognized type.
  273. else {
  274. return false;
  275. }
  276. return $this->addLogEntry($tmp);
  277. }
  278. /**
  279. * Method to add an entry to the appropriate loggers.
  280. *
  281. * @param JLogEntry $entry The JLogEntry object to send to the loggers.
  282. *
  283. * @return void
  284. *
  285. * @since 11.1
  286. * @throws LogException
  287. */
  288. protected function addLogEntry(JLogEntry $entry)
  289. {
  290. // Find all the appropriate loggers based on priority and category for the entry.
  291. $loggers = $this->findLoggers($entry->priority, $entry->category);
  292. foreach ((array) $loggers as $signature)
  293. {
  294. // Attempt to instantiate the logger object if it doesn't already exist.
  295. if (empty($this->loggers[$signature])) {
  296. $class = 'JLogger'.ucfirst($this->configurations[$signature]['logger']);
  297. if (class_exists($class)) {
  298. $this->loggers[$signature] = new $class($this->configurations[$signature]);
  299. }
  300. else {
  301. throw new LogException(JText::_('Unable to create a JLogger instance: '));
  302. }
  303. }
  304. // Add the entry to the logger.
  305. $this->loggers[$signature]->addEntry($entry);
  306. }
  307. }
  308. /**
  309. * Method to find the loggers to use based on priority and category values.
  310. *
  311. * @param integer $priority Message priority.
  312. * @param string $category Type of entry
  313. *
  314. * @return array The array of loggers to use for the given priority and category values.
  315. *
  316. * @since 11.1
  317. */
  318. protected function findLoggers($priority, $category)
  319. {
  320. // Initialize variables.
  321. $loggers = array();
  322. // Sanitize inputs.
  323. $priority = (int) $priority;
  324. $category = strtolower($category);
  325. // Let's go iterate over the loggers and get all the ones we need.
  326. foreach ((array) $this->lookup as $signature => $rules)
  327. {
  328. // Check to make sure the priority matches the logger.
  329. if ($priority & $rules->priorities) {
  330. // If either there are no set categories (meaning all) or the specific category is set, add this logger.
  331. if (empty($category) || empty($rules->categories) || in_array($category, $rules->categories)) {
  332. $loggers[] = $signature;
  333. }
  334. }
  335. }
  336. return $loggers;
  337. }
  338. }