/lib/mustache/src/Mustache/Logger/StreamLogger.php

https://github.com/jfilip/moodle · PHP · 194 lines · 88 code · 19 blank · 87 comment · 10 complexity · b1ead3003e9d4f4194bbd3239a730957 MD5 · raw file

  1. <?php
  2. /*
  3. * This file is part of Mustache.php.
  4. *
  5. * (c) 2010-2014 Justin Hileman
  6. *
  7. * For the full copyright and license information, please view the LICENSE
  8. * file that was distributed with this source code.
  9. */
  10. /**
  11. * A Mustache Stream Logger.
  12. *
  13. * The Stream Logger wraps a file resource instance (such as a stream) or a
  14. * stream URL. All log messages over the threshold level will be appended to
  15. * this stream.
  16. *
  17. * Hint: Try `php://stderr` for your stream URL.
  18. */
  19. class Mustache_Logger_StreamLogger extends Mustache_Logger_AbstractLogger
  20. {
  21. protected static $levels = array(
  22. self::DEBUG => 100,
  23. self::INFO => 200,
  24. self::NOTICE => 250,
  25. self::WARNING => 300,
  26. self::ERROR => 400,
  27. self::CRITICAL => 500,
  28. self::ALERT => 550,
  29. self::EMERGENCY => 600,
  30. );
  31. protected $level;
  32. protected $stream = null;
  33. protected $url = null;
  34. /**
  35. * @throws InvalidArgumentException if the logging level is unknown.
  36. *
  37. * @param resource|string $stream Resource instance or URL
  38. * @param integer $level The minimum logging level at which this handler will be triggered
  39. */
  40. public function __construct($stream, $level = Mustache_Logger::ERROR)
  41. {
  42. $this->setLevel($level);
  43. if (is_resource($stream)) {
  44. $this->stream = $stream;
  45. } else {
  46. $this->url = $stream;
  47. }
  48. }
  49. /**
  50. * Close stream resources.
  51. */
  52. public function __destruct()
  53. {
  54. if (is_resource($this->stream)) {
  55. fclose($this->stream);
  56. }
  57. }
  58. /**
  59. * Set the minimum logging level.
  60. *
  61. * @throws Mustache_Exception_InvalidArgumentException if the logging level is unknown.
  62. *
  63. * @param integer $level The minimum logging level which will be written
  64. */
  65. public function setLevel($level)
  66. {
  67. if (!array_key_exists($level, self::$levels)) {
  68. throw new Mustache_Exception_InvalidArgumentException(sprintf('Unexpected logging level: %s', $level));
  69. }
  70. $this->level = $level;
  71. }
  72. /**
  73. * Get the current minimum logging level.
  74. *
  75. * @return integer
  76. */
  77. public function getLevel()
  78. {
  79. return $this->level;
  80. }
  81. /**
  82. * Logs with an arbitrary level.
  83. *
  84. * @throws Mustache_Exception_InvalidArgumentException if the logging level is unknown.
  85. *
  86. * @param mixed $level
  87. * @param string $message
  88. * @param array $context
  89. */
  90. public function log($level, $message, array $context = array())
  91. {
  92. if (!array_key_exists($level, self::$levels)) {
  93. throw new Mustache_Exception_InvalidArgumentException(sprintf('Unexpected logging level: %s', $level));
  94. }
  95. if (self::$levels[$level] >= self::$levels[$this->level]) {
  96. $this->writeLog($level, $message, $context);
  97. }
  98. }
  99. /**
  100. * Write a record to the log.
  101. *
  102. * @throws Mustache_Exception_LogicException If neither a stream resource nor url is present.
  103. * @throws Mustache_Exception_RuntimeException If the stream url cannot be opened.
  104. *
  105. * @param integer $level The logging level
  106. * @param string $message The log message
  107. * @param array $context The log context
  108. */
  109. protected function writeLog($level, $message, array $context = array())
  110. {
  111. if (!is_resource($this->stream)) {
  112. if (!isset($this->url)) {
  113. throw new Mustache_Exception_LogicException('Missing stream url, the stream can not be opened. This may be caused by a premature call to close().');
  114. }
  115. $this->stream = fopen($this->url, 'a');
  116. if (!is_resource($this->stream)) {
  117. // @codeCoverageIgnoreStart
  118. throw new Mustache_Exception_RuntimeException(sprintf('The stream or file "%s" could not be opened.', $this->url));
  119. // @codeCoverageIgnoreEnd
  120. }
  121. }
  122. fwrite($this->stream, self::formatLine($level, $message, $context));
  123. }
  124. /**
  125. * Gets the name of the logging level.
  126. *
  127. * @throws InvalidArgumentException if the logging level is unknown.
  128. *
  129. * @param integer $level
  130. *
  131. * @return string
  132. */
  133. protected static function getLevelName($level)
  134. {
  135. return strtoupper($level);
  136. }
  137. /**
  138. * Format a log line for output.
  139. *
  140. * @param integer $level The logging level
  141. * @param string $message The log message
  142. * @param array $context The log context
  143. *
  144. * @return string
  145. */
  146. protected static function formatLine($level, $message, array $context = array())
  147. {
  148. return sprintf(
  149. "%s: %s\n",
  150. self::getLevelName($level),
  151. self::interpolateMessage($message, $context)
  152. );
  153. }
  154. /**
  155. * Interpolate context values into the message placeholders.
  156. *
  157. * @param string $message
  158. * @param array $context
  159. *
  160. * @return string
  161. */
  162. protected static function interpolateMessage($message, array $context = array())
  163. {
  164. if (strpos($message, '{') === false) {
  165. return $message;
  166. }
  167. // build a replacement array with braces around the context keys
  168. $replace = array();
  169. foreach ($context as $key => $val) {
  170. $replace['{' . $key . '}'] = $val;
  171. }
  172. // interpolate replacement values into the the message and return
  173. return strtr($message, $replace);
  174. }
  175. }