class-wc-log-handler-email.php 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  1. <?php
  2. /**
  3. * Class WC_Log_Handler_Email file.
  4. *
  5. * @package WooCommerce\Log Handlers
  6. */
  7. if ( ! defined( 'ABSPATH' ) ) {
  8. exit; // Exit if accessed directly.
  9. }
  10. /**
  11. * Handles log entries by sending an email.
  12. *
  13. * WARNING!
  14. * This log handler has known limitations.
  15. *
  16. * Log messages are aggregated and sent once per request (if necessary). If the site experiences a
  17. * problem, the log email may never be sent. This handler should be used with another handler which
  18. * stores logs in order to prevent loss.
  19. *
  20. * It is not recommended to use this handler on a high traffic site. There will be a maximum of 1
  21. * email sent per request per handler, but that could still be a dangerous amount of emails under
  22. * heavy traffic. Do not confuse this handler with an appropriate monitoring solution!
  23. *
  24. * If you understand these limitations, feel free to use this handler or borrow parts of the design
  25. * to implement your own!
  26. *
  27. * @class WC_Log_Handler_Email
  28. * @version 1.0.0
  29. * @package WooCommerce/Classes/Log_Handlers
  30. */
  31. class WC_Log_Handler_Email extends WC_Log_Handler {
  32. /**
  33. * Minimum log level this handler will process.
  34. *
  35. * @var int Integer representation of minimum log level to handle.
  36. */
  37. protected $threshold;
  38. /**
  39. * Stores email recipients.
  40. *
  41. * @var array
  42. */
  43. protected $recipients = array();
  44. /**
  45. * Stores log messages.
  46. *
  47. * @var array
  48. */
  49. protected $logs = array();
  50. /**
  51. * Stores integer representation of maximum logged level.
  52. *
  53. * @var int
  54. */
  55. protected $max_severity = null;
  56. /**
  57. * Constructor for log handler.
  58. *
  59. * @param string|array $recipients Optional. Email(s) to receive log messages. Defaults to site admin email.
  60. * @param string $threshold Optional. Minimum level that should receive log messages.
  61. * Default 'alert'. One of: emergency|alert|critical|error|warning|notice|info|debug.
  62. */
  63. public function __construct( $recipients = null, $threshold = 'alert' ) {
  64. if ( null === $recipients ) {
  65. $recipients = get_option( 'admin_email' );
  66. }
  67. if ( is_array( $recipients ) ) {
  68. foreach ( $recipients as $recipient ) {
  69. $this->add_email( $recipient );
  70. }
  71. } else {
  72. $this->add_email( $recipients );
  73. }
  74. $this->set_threshold( $threshold );
  75. add_action( 'shutdown', array( $this, 'send_log_email' ) );
  76. }
  77. /**
  78. * Set handler severity threshold.
  79. *
  80. * @param string $level emergency|alert|critical|error|warning|notice|info|debug.
  81. */
  82. public function set_threshold( $level ) {
  83. $this->threshold = WC_Log_Levels::get_level_severity( $level );
  84. }
  85. /**
  86. * Determine whether handler should handle log.
  87. *
  88. * @param string $level emergency|alert|critical|error|warning|notice|info|debug.
  89. * @return bool True if the log should be handled.
  90. */
  91. protected function should_handle( $level ) {
  92. return $this->threshold <= WC_Log_Levels::get_level_severity( $level );
  93. }
  94. /**
  95. * Handle a log entry.
  96. *
  97. * @param int $timestamp Log timestamp.
  98. * @param string $level emergency|alert|critical|error|warning|notice|info|debug.
  99. * @param string $message Log message.
  100. * @param array $context Optional. Additional information for log handlers.
  101. *
  102. * @return bool False if value was not handled and true if value was handled.
  103. */
  104. public function handle( $timestamp, $level, $message, $context ) {
  105. if ( $this->should_handle( $level ) ) {
  106. $this->add_log( $timestamp, $level, $message, $context );
  107. return true;
  108. }
  109. return false;
  110. }
  111. /**
  112. * Send log email.
  113. *
  114. * @return bool True if email is successfully sent otherwise false.
  115. */
  116. public function send_log_email() {
  117. $result = false;
  118. if ( ! empty( $this->logs ) ) {
  119. $subject = $this->get_subject();
  120. $body = $this->get_body();
  121. $result = wp_mail( $this->recipients, $subject, $body );
  122. $this->clear_logs();
  123. }
  124. return $result;
  125. }
  126. /**
  127. * Build subject for log email.
  128. *
  129. * @return string subject
  130. */
  131. protected function get_subject() {
  132. $site_name = get_bloginfo( 'name' );
  133. $max_level = strtoupper( WC_Log_Levels::get_severity_level( $this->max_severity ) );
  134. $log_count = count( $this->logs );
  135. return sprintf(
  136. /* translators: 1: Site name 2: Maximum level 3: Log count */
  137. _n(
  138. '[%1$s] %2$s: %3$s WooCommerce log message',
  139. '[%1$s] %2$s: %3$s WooCommerce log messages',
  140. $log_count,
  141. 'woocommerce'
  142. ),
  143. $site_name,
  144. $max_level,
  145. $log_count
  146. );
  147. }
  148. /**
  149. * Build body for log email.
  150. *
  151. * @return string body
  152. */
  153. protected function get_body() {
  154. $site_name = get_bloginfo( 'name' );
  155. $entries = implode( PHP_EOL, $this->logs );
  156. $log_count = count( $this->logs );
  157. return _n(
  158. 'You have received the following WooCommerce log message:',
  159. 'You have received the following WooCommerce log messages:',
  160. $log_count,
  161. 'woocommerce'
  162. ) . PHP_EOL
  163. . PHP_EOL
  164. . $entries
  165. . PHP_EOL
  166. . PHP_EOL
  167. /* translators: %s: Site name */
  168. . sprintf( __( 'Visit %s admin area:', 'woocommerce' ), $site_name )
  169. . PHP_EOL
  170. . admin_url();
  171. }
  172. /**
  173. * Adds an email to the list of recipients.
  174. *
  175. * @param string $email Email address to add.
  176. */
  177. public function add_email( $email ) {
  178. array_push( $this->recipients, $email );
  179. }
  180. /**
  181. * Add log message.
  182. *
  183. * @param int $timestamp Log timestamp.
  184. * @param string $level emergency|alert|critical|error|warning|notice|info|debug.
  185. * @param string $message Log message.
  186. * @param array $context Additional information for log handlers.
  187. */
  188. protected function add_log( $timestamp, $level, $message, $context ) {
  189. $this->logs[] = $this->format_entry( $timestamp, $level, $message, $context );
  190. $log_severity = WC_Log_Levels::get_level_severity( $level );
  191. if ( $this->max_severity < $log_severity ) {
  192. $this->max_severity = $log_severity;
  193. }
  194. }
  195. /**
  196. * Clear log messages.
  197. */
  198. protected function clear_logs() {
  199. $this->logs = array();
  200. }
  201. }