Merge branch 'wc-logger--rebased'
This commit is contained in:
commit
7b95988811
File diff suppressed because one or more lines are too long
|
@ -580,6 +580,74 @@ table.wc_status_table {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* DB log viewer
|
||||
*/
|
||||
.wp-list-table.logs {
|
||||
|
||||
.log-level {
|
||||
display: inline;
|
||||
padding: .2em .6em .3em;
|
||||
font-size: 80%;
|
||||
font-weight: bold;
|
||||
line-height: 1;
|
||||
color: #fff;
|
||||
text-align: center;
|
||||
white-space: nowrap;
|
||||
vertical-align: baseline;
|
||||
border-radius: .2em;
|
||||
|
||||
&:empty {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add color to levels
|
||||
*
|
||||
* Descending severity:
|
||||
* emergency, alert -> red
|
||||
* critical, error -> orange
|
||||
* warning, notice -> yellow
|
||||
* info -> blue
|
||||
* debug -> gree
|
||||
*/
|
||||
|
||||
.log-level--emergency,
|
||||
.log-level--alert {
|
||||
background-color: #ff4136;
|
||||
}
|
||||
.log-level--critical,
|
||||
.log-level--error {
|
||||
background-color: #ff851b;
|
||||
}
|
||||
.log-level--warning,
|
||||
.log-level--notice {
|
||||
color: #222;
|
||||
background-color: #ffdc00;
|
||||
}
|
||||
.log-level--info {
|
||||
background-color: #0074d9;
|
||||
}
|
||||
.log-level--debug {
|
||||
background-color: #3d9970;
|
||||
}
|
||||
|
||||
// Adjust log table columns only when table is not collapsed
|
||||
@media screen and ( min-width: 783px ) {
|
||||
.column-timestamp {
|
||||
width: 18%;
|
||||
}
|
||||
.column-level {
|
||||
width: 14%;
|
||||
}
|
||||
.column-source {
|
||||
width: 15%;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#log-viewer-select {
|
||||
padding: 10px 0 8px;
|
||||
line-height: 28px;
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Abstract WC Log Handler Class
|
||||
*
|
||||
* @version 1.0.0
|
||||
* @package WooCommerce/Abstracts
|
||||
* @category Abstract Class
|
||||
* @author WooThemes
|
||||
*/
|
||||
abstract class WC_Log_Handler {
|
||||
|
||||
|
||||
/**
|
||||
* Handle a log entry.
|
||||
*
|
||||
* @param int $timestamp Log timestamp.
|
||||
* @param string $level emergency|alert|critical|error|warning|notice|info|debug
|
||||
* @param string $message Log message.
|
||||
* @param array $context Additional information for log handlers.
|
||||
*
|
||||
* @return bool False if value was not handled and true if value was handled.
|
||||
*/
|
||||
abstract public function handle( $timestamp, $level, $message, $context );
|
||||
|
||||
/**
|
||||
* Formats a timestamp for use in log messages.
|
||||
*
|
||||
* @param int $timestamp Log timestamp.
|
||||
* @return string Formatted time for use in log entry.
|
||||
*/
|
||||
protected static function format_time( $timestamp ) {
|
||||
return date( 'c', $timestamp );
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a log entry text from level, timestamp and message.
|
||||
*
|
||||
* @param int $timestamp Log timestamp.
|
||||
* @param string $level emergency|alert|critical|error|warning|notice|info|debug
|
||||
* @param string $message Log message.
|
||||
* @param array $context Additional information for log handlers.
|
||||
*
|
||||
* @return string Formatted log entry.
|
||||
*/
|
||||
protected static function format_entry( $timestamp, $level, $message, $context ) {
|
||||
$time_string = self::format_time( $timestamp );
|
||||
$level_string = strtoupper( $level );
|
||||
$entry = "{$time_string} {$level_string} {$message}";
|
||||
|
||||
return apply_filters( 'woocommerce_format_log_entry', $entry, array(
|
||||
'timestamp' => $timestamp,
|
||||
'level' => $level,
|
||||
'message' => $message,
|
||||
'context' => $context,
|
||||
) );
|
||||
}
|
||||
}
|
|
@ -0,0 +1,355 @@
|
|||
<?php
|
||||
/**
|
||||
* WooCommerce Log Table List
|
||||
*
|
||||
* @author WooThemes
|
||||
* @category Admin
|
||||
* @package WooCommerce/Admin
|
||||
* @version 1.0.0
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
|
||||
if ( ! class_exists( 'WP_List_Table' ) ) {
|
||||
require_once( ABSPATH . 'wp-admin/includes/class-wp-list-table.php' );
|
||||
}
|
||||
|
||||
class WC_Admin_Log_Table_List extends WP_List_Table {
|
||||
|
||||
/**
|
||||
* Initialize the log table list.
|
||||
*/
|
||||
public function __construct() {
|
||||
parent::__construct( array(
|
||||
'singular' => __( 'log', 'woocommerce' ),
|
||||
'plural' => __( 'logs', 'woocommerce' ),
|
||||
'ajax' => false,
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Display level dropdown
|
||||
*
|
||||
* @global wpdb $wpdb
|
||||
*/
|
||||
public function level_dropdown() {
|
||||
|
||||
$levels = array(
|
||||
array( 'value' => WC_Log_Levels::EMERGENCY, 'label' => __( 'Emergency', 'woocommerce' ) ),
|
||||
array( 'value' => WC_Log_Levels::ALERT, 'label' => __( 'Alert', 'woocommerce' ) ),
|
||||
array( 'value' => WC_Log_Levels::CRITICAL, 'label' => __( 'Critical', 'woocommerce' ) ),
|
||||
array( 'value' => WC_Log_Levels::ERROR, 'label' => __( 'Error', 'woocommerce' ) ),
|
||||
array( 'value' => WC_Log_Levels::WARNING, 'label' => __( 'Warning', 'woocommerce' ) ),
|
||||
array( 'value' => WC_Log_Levels::NOTICE, 'label' => __( 'Notice', 'woocommerce' ) ),
|
||||
array( 'value' => WC_Log_Levels::INFO, 'label' => __( 'Info', 'woocommerce' ) ),
|
||||
array( 'value' => WC_Log_Levels::DEBUG, 'label' => __( 'Debug', 'woocommerce' ) ),
|
||||
);
|
||||
|
||||
$selected_level = isset( $_REQUEST['level'] ) ? $_REQUEST['level'] : '';
|
||||
?>
|
||||
<label for="filter-by-level" class="screen-reader-text"><?php _e( 'Filter by level', 'woocommerce' ); ?></label>
|
||||
<select name="level" id="filter-by-level">
|
||||
<option<?php selected( $selected_level, '' ); ?> value=""><?php _e( 'All levels', 'woocommerce' ); ?></option>
|
||||
<?php foreach ( $levels as $l ) {
|
||||
printf( '<option%1$s value="%2$s">%3$s</option>',
|
||||
selected( $selected_level, $l['value'], false ),
|
||||
esc_attr( $l['value'] ),
|
||||
esc_html( $l['label'] )
|
||||
);
|
||||
} ?>
|
||||
</select>
|
||||
<?php
|
||||
}
|
||||
|
||||
/**
|
||||
* Get list columns.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function get_columns() {
|
||||
return array(
|
||||
'cb' => '<input type="checkbox" />',
|
||||
'timestamp' => __( 'Timestamp', 'woocommerce' ),
|
||||
'level' => __( 'Level', 'woocommerce' ),
|
||||
'message' => __( 'Message', 'woocommerce' ),
|
||||
'source' => __( 'Source', 'woocommerce' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Column cb.
|
||||
*
|
||||
* @param array $log
|
||||
* @return string
|
||||
*/
|
||||
public function column_cb( $log ) {
|
||||
return sprintf( '<input type="checkbox" name="log[]" value="%1$s" />', esc_attr( $log['log_id'] ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Timestamp column.
|
||||
*
|
||||
* @param array $log
|
||||
* @return string
|
||||
*/
|
||||
public function column_timestamp( $log ) {
|
||||
return esc_html( mysql2date(
|
||||
get_option( 'date_format' ) . ' ' . get_option( 'time_format' ),
|
||||
$log['timestamp']
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Level column.
|
||||
*
|
||||
* @param array $log
|
||||
* @return string
|
||||
*/
|
||||
public function column_level( $log ) {
|
||||
$level_key = WC_Log_Levels::get_severity_level( $log['level'] );
|
||||
$levels = array(
|
||||
'emergency' => __( 'Emergency', 'woocommerce' ),
|
||||
'alert' => __( 'Alert', 'woocommerce' ),
|
||||
'critical' => __( 'Critical', 'woocommerce' ),
|
||||
'error' => __( 'Error', 'woocommerce' ),
|
||||
'warning' => __( 'Warning', 'woocommerce' ),
|
||||
'notice' => __( 'Notice', 'woocommerce' ),
|
||||
'info' => __( 'Info', 'woocommerce' ),
|
||||
'debug' => __( 'Debug', 'woocommerce' ),
|
||||
);
|
||||
|
||||
if ( isset( $levels[ $level_key ] ) ) {
|
||||
$level = $levels[ $level_key ];
|
||||
$level_class = sanitize_html_class( 'log-level--' . $level_key );
|
||||
return '<span class="log-level ' . $level_class . '">' . esc_html( $level ) . '</span>';
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Message column.
|
||||
*
|
||||
* @param array $log
|
||||
* @return string
|
||||
*/
|
||||
public function column_message( $log ) {
|
||||
return esc_html( $log['message'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Source column.
|
||||
*
|
||||
* @param array $log
|
||||
* @return string
|
||||
*/
|
||||
public function column_source( $log ) {
|
||||
return esc_html( $log['source'] );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get bulk actions.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_bulk_actions() {
|
||||
return array(
|
||||
'delete' => __( 'Delete', 'woocommerce' ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Extra controls to be displayed between bulk actions and pagination.
|
||||
*
|
||||
* @param string $which
|
||||
*/
|
||||
protected function extra_tablenav( $which ) {
|
||||
if ( 'top' === $which ) {
|
||||
echo '<div class="alignleft actions">';
|
||||
$this->level_dropdown();
|
||||
$this->source_dropdown();
|
||||
submit_button( __( 'Filter', 'woocommerce' ), '', 'filter-action', false );
|
||||
echo '</div>';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of sortable columns.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
protected function get_sortable_columns() {
|
||||
return array(
|
||||
'timestamp' => array( 'timestamp', true ),
|
||||
'level' => array( 'level', true ),
|
||||
'source' => array( 'source', true ),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Display source dropdown
|
||||
*
|
||||
* @global wpdb $wpdb
|
||||
*/
|
||||
protected function source_dropdown() {
|
||||
global $wpdb;
|
||||
|
||||
$sources = $wpdb->get_col( "
|
||||
SELECT DISTINCT source
|
||||
FROM {$wpdb->prefix}woocommerce_log
|
||||
WHERE source != ''
|
||||
ORDER BY source ASC
|
||||
" );
|
||||
|
||||
if ( ! empty( $sources ) ) {
|
||||
$selected_source = isset( $_REQUEST['source'] ) ? $_REQUEST['source'] : '';
|
||||
?>
|
||||
<label for="filter-by-source" class="screen-reader-text"><?php _e( 'Filter by source', 'woocommerce' ); ?></label>
|
||||
<select name="source" id="filter-by-source">
|
||||
<option<?php selected( $selected_source, '' ); ?> value=""><?php _e( 'All sources', 'woocommerce' ); ?></option>
|
||||
<?php foreach ( $sources as $s ) {
|
||||
printf( '<option%1$s value="%2$s">%3$s</option>',
|
||||
selected( $selected_source, $s, false ),
|
||||
esc_attr( $s ),
|
||||
esc_html( $s )
|
||||
);
|
||||
} ?>
|
||||
</select>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Prepare table list items.
|
||||
*
|
||||
* @global wpdb $wpdb
|
||||
*/
|
||||
public function prepare_items() {
|
||||
global $wpdb;
|
||||
|
||||
$this->prepare_column_headers();
|
||||
|
||||
$per_page = $this->get_items_per_page( 'woocommerce_status_log_items_per_page', 10 );
|
||||
|
||||
$where = $this->get_items_query_where();
|
||||
$order = $this->get_items_query_order();
|
||||
$limit = $this->get_items_query_limit();
|
||||
$offset = $this->get_items_query_offset();
|
||||
|
||||
$query_items = "
|
||||
SELECT log_id, timestamp, level, message, source
|
||||
FROM {$wpdb->prefix}woocommerce_log
|
||||
{$where} {$order} {$limit} {$offset}
|
||||
";
|
||||
|
||||
$this->items = $wpdb->get_results( $query_items, ARRAY_A );
|
||||
|
||||
$query_count = "SELECT COUNT(log_id) FROM {$wpdb->prefix}woocommerce_log {$where}";
|
||||
$total_items = $wpdb->get_var( $query_count );
|
||||
|
||||
$this->set_pagination_args( array(
|
||||
'total_items' => $total_items,
|
||||
'per_page' => $per_page,
|
||||
'total_pages' => ceil( $total_items / $per_page ),
|
||||
) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get prepared LIMIT clause for items query
|
||||
*
|
||||
* @global wpdb $wpdb
|
||||
*
|
||||
* @return string Prepared LIMIT clause for items query.
|
||||
*/
|
||||
protected function get_items_query_limit() {
|
||||
global $wpdb;
|
||||
|
||||
$per_page = $this->get_items_per_page( 'woocommerce_status_log_items_per_page', 10 );
|
||||
return $wpdb->prepare( 'LIMIT %d', $per_page );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get prepared OFFSET clause for items query
|
||||
*
|
||||
* @global wpdb $wpdb
|
||||
*
|
||||
* @return string Prepared OFFSET clause for items query.
|
||||
*/
|
||||
protected function get_items_query_offset() {
|
||||
global $wpdb;
|
||||
|
||||
$per_page = $this->get_items_per_page( 'woocommerce_status_log_items_per_page', 10 );
|
||||
$current_page = $this->get_pagenum();
|
||||
if ( 1 < $current_page ) {
|
||||
$offset = $per_page * ( $current_page - 1 );
|
||||
} else {
|
||||
$offset = 0;
|
||||
}
|
||||
|
||||
return $wpdb->prepare( 'OFFSET %d', $offset );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get prepared ORDER BY clause for items query
|
||||
*
|
||||
* @return string Prepared ORDER BY clause for items query.
|
||||
*/
|
||||
protected function get_items_query_order() {
|
||||
$valid_orders = array( 'level', 'source', 'timestamp' );
|
||||
if ( ! empty( $_REQUEST['orderby'] ) && in_array( $_REQUEST['orderby'], $valid_orders ) ) {
|
||||
$by = wc_clean( $_REQUEST['orderby'] );
|
||||
} else {
|
||||
$by = 'timestamp';
|
||||
}
|
||||
$by = esc_sql( $by );
|
||||
|
||||
if ( ! empty( $_REQUEST['order'] ) && 'asc' === strtolower( $_REQUEST['order'] ) ) {
|
||||
$order = 'ASC';
|
||||
} else {
|
||||
$order = 'DESC';
|
||||
}
|
||||
|
||||
return "ORDER BY {$by} {$order}";
|
||||
}
|
||||
|
||||
/**
|
||||
* Get prepared WHERE clause for items query
|
||||
*
|
||||
* @global wpdb $wpdb
|
||||
*
|
||||
* @return string Prepared WHERE clause for items query.
|
||||
*/
|
||||
protected function get_items_query_where() {
|
||||
global $wpdb;
|
||||
|
||||
$where_conditions = array();
|
||||
$where_values = array();
|
||||
if ( ! empty( $_REQUEST['level'] ) && WC_Log_Levels::is_valid_level( $_REQUEST['level'] ) ) {
|
||||
$where_conditions[] = 'level >= %d';
|
||||
$where_values[] = WC_Log_Levels::get_level_severity( $_REQUEST['level'] );
|
||||
}
|
||||
if ( ! empty( $_REQUEST['source'] ) ) {
|
||||
$where_conditions[] = 'source = %s';
|
||||
$where_values[] = wc_clean( $_REQUEST['source'] );
|
||||
}
|
||||
|
||||
if ( ! empty( $where_conditions ) ) {
|
||||
return $wpdb->prepare( 'WHERE 1 = 1 AND ' . implode( ' AND ', $where_conditions ), $where_values );
|
||||
} else {
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set _column_headers property for table list
|
||||
*/
|
||||
protected function prepare_column_headers() {
|
||||
$this->_column_headers = array(
|
||||
$this->get_columns(),
|
||||
array(),
|
||||
$this->get_sortable_columns(),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -77,6 +77,17 @@ class WC_Admin_Status {
|
|||
* Show the logs page.
|
||||
*/
|
||||
public static function status_logs() {
|
||||
if ( defined( 'WC_LOG_HANDLER' ) && 'WC_Log_Handler_DB' === WC_LOG_HANDLER ) {
|
||||
self::status_logs_db();
|
||||
} else {
|
||||
self::status_logs_file();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the log page contents for file log handler.
|
||||
*/
|
||||
public static function status_logs_file() {
|
||||
|
||||
$logs = self::scan_log_files();
|
||||
|
||||
|
@ -95,6 +106,27 @@ class WC_Admin_Status {
|
|||
include_once( 'views/html-admin-page-status-logs.php' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Show the log page contents for db log handler.
|
||||
*/
|
||||
public static function status_logs_db() {
|
||||
|
||||
// Flush
|
||||
if ( ! empty( $_REQUEST['flush-logs'] ) ) {
|
||||
self::flush_db_logs();
|
||||
}
|
||||
|
||||
// Bulk actions
|
||||
if ( isset( $_GET['action'] ) && isset( $_GET['log'] ) ) {
|
||||
self::log_table_bulk_actions();
|
||||
}
|
||||
|
||||
$log_table_list = new WC_Admin_Log_Table_List();
|
||||
$log_table_list->prepare_items();
|
||||
|
||||
include_once( 'views/html-admin-page-status-logs-db.php' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve metadata from a file. Based on WP Core's get_file_data function.
|
||||
* @since 2.1.1
|
||||
|
@ -250,11 +282,46 @@ class WC_Admin_Status {
|
|||
}
|
||||
|
||||
if ( ! empty( $_REQUEST['handle'] ) ) {
|
||||
$logger = wc_get_logger();
|
||||
$logger->remove( $_REQUEST['handle'] );
|
||||
$log_handler = new WC_Log_Handler_File();
|
||||
$log_handler->remove( $_REQUEST['handle'] );
|
||||
}
|
||||
|
||||
wp_safe_redirect( esc_url_raw( admin_url( 'admin.php?page=wc-status&tab=logs' ) ) );
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear DB log table.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
private static function flush_db_logs() {
|
||||
if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'woocommerce-status-logs' ) ) {
|
||||
wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
WC_Log_Handler_DB::flush();
|
||||
|
||||
wp_safe_redirect( esc_url_raw( admin_url( 'admin.php?page=wc-status&tab=logs' ) ) );
|
||||
exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk DB log table actions.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
private static function log_table_bulk_actions() {
|
||||
if ( empty( $_REQUEST['_wpnonce'] ) || ! wp_verify_nonce( $_REQUEST['_wpnonce'], 'woocommerce-status-logs' ) ) {
|
||||
wp_die( __( 'Action failed. Please refresh the page and retry.', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
$log_ids = array_map( 'absint', (array) $_GET['log'] );
|
||||
|
||||
if ( 'delete' === $_GET['action'] || 'delete' === $_GET['action2'] ) {
|
||||
WC_Log_Handler_DB::delete( $log_ids );
|
||||
wp_safe_redirect( esc_url_raw( admin_url( 'admin.php?page=wc-status&tab=logs' ) ) );
|
||||
exit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -324,7 +324,7 @@ class WC_Admin_Report {
|
|||
|
||||
if ( $debug ) {
|
||||
echo '<pre>';
|
||||
print_r( $query );
|
||||
wc_print_r( $query );
|
||||
echo '</pre>';
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
<?php
|
||||
/**
|
||||
* Admin View: Page - Status Database Logs
|
||||
*/
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit;
|
||||
}
|
||||
?>
|
||||
<form method="get" id="mainform" action="">
|
||||
|
||||
<?php $log_table_list->display(); ?>
|
||||
|
||||
<input type="hidden" name="page" value="wc-status" />
|
||||
<input type="hidden" name="tab" value="logs" />
|
||||
|
||||
<?php submit_button( __( 'Flush all logs', 'woocommerce' ), 'delete', 'flush-logs' ); ?>
|
||||
<?php wp_nonce_field( 'woocommerce-status-logs' ); ?>
|
||||
</form>
|
||||
<?php
|
||||
wc_enqueue_js( "
|
||||
jQuery( '#flush-logs' ).click( function() {
|
||||
if ( window.confirm('" . esc_js( __( 'Are you sure you want to clear all logs from the database?', 'woocommerce' ) ) . "') ) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
});
|
||||
" );
|
|
@ -83,8 +83,11 @@ class WC_Autoloader {
|
|||
$path = $this->include_path . 'admin/';
|
||||
} elseif ( strpos( $class, 'wc_payment_token_' ) === 0 ) {
|
||||
$path = $this->include_path . 'payment-tokens/';
|
||||
} elseif ( strpos( $class, 'wc_log_handler_' ) === 0 ) {
|
||||
$path = $this->include_path . 'log-handlers/';
|
||||
}
|
||||
|
||||
|
||||
if ( empty( $path ) || ( ! $this->load_file( $path . $file ) && strpos( $class, 'wc_' ) === 0 ) ) {
|
||||
$this->load_file( $this->include_path . $file );
|
||||
}
|
||||
|
|
|
@ -39,7 +39,10 @@ class WC_Background_Updater extends WP_Background_Process {
|
|||
$logger = wc_get_logger();
|
||||
|
||||
if ( is_wp_error( $dispatched ) ) {
|
||||
$logger->add( 'wc_db_updates', sprintf( 'Unable to dispatch WooCommerce updater: %s', $dispatched->get_error_message() ) );
|
||||
$logger->error(
|
||||
sprintf( 'Unable to dispatch WooCommerce updater: %s', $dispatched->get_error_message() ),
|
||||
array( 'source' => 'wc_db_updates' )
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -102,11 +105,11 @@ class WC_Background_Updater extends WP_Background_Process {
|
|||
include_once( dirname( __FILE__ ) . '/wc-update-functions.php' );
|
||||
|
||||
if ( is_callable( $callback ) ) {
|
||||
$logger->add( 'wc_db_updates', sprintf( 'Running %s callback', $callback ) );
|
||||
$logger->info( sprintf( 'Running %s callback', $callback ), array( 'source' => 'wc_db_updates' ) );
|
||||
call_user_func( $callback );
|
||||
$logger->add( 'wc_db_updates', sprintf( 'Finished %s callback', $callback ) );
|
||||
$logger->info( sprintf( 'Finished %s callback', $callback ), array( 'source' => 'wc_db_updates' ) );
|
||||
} else {
|
||||
$logger->add( 'wc_db_updates', sprintf( 'Could not find %s callback', $callback ) );
|
||||
$logger->notice( sprintf( 'Could not find %s callback', $callback ), array( 'source' => 'wc_db_updates' ) );
|
||||
}
|
||||
|
||||
return false;
|
||||
|
@ -120,7 +123,7 @@ class WC_Background_Updater extends WP_Background_Process {
|
|||
*/
|
||||
protected function complete() {
|
||||
$logger = wc_get_logger();
|
||||
$logger->add( 'wc_db_updates', 'Data update complete' );
|
||||
$logger->info( 'Data update complete', array( 'source' => 'wc_db_updates' ) );
|
||||
WC_Install::update_db_version();
|
||||
parent::complete();
|
||||
}
|
||||
|
|
|
@ -1165,13 +1165,15 @@ class WC_Geo_IP {
|
|||
/**
|
||||
* Logging method.
|
||||
*
|
||||
* @param string $message
|
||||
* @param string $message Log message.
|
||||
* @param string $level Optional. Default 'info'.
|
||||
* emergency|alert|critical|error|warning|notice|info|debug
|
||||
*/
|
||||
public static function log( $message ) {
|
||||
public static function log( $message, $level = 'info' ) {
|
||||
if ( empty( self::$log ) ) {
|
||||
self::$log = wc_get_logger();
|
||||
}
|
||||
self::$log->add( 'geoip', $message );
|
||||
self::$log->log( $level, $message, array( 'source' => 'geoip' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1191,7 +1193,7 @@ class WC_Geo_IP {
|
|||
$this->memory_buffer = fread( $this->filehandle, $s_array['size'] );
|
||||
}
|
||||
} else {
|
||||
$this->log( 'GeoIP API: Can not open ' . $filename );
|
||||
$this->log( 'GeoIP API: Can not open ' . $filename, 'error' );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1550,7 +1552,7 @@ class WC_Geo_IP {
|
|||
}
|
||||
}
|
||||
|
||||
$this->log( 'GeoIP API: Error traversing database - perhaps it is corrupt?' );
|
||||
$this->log( 'GeoIP API: Error traversing database - perhaps it is corrupt?', 'error' );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -1605,7 +1607,7 @@ class WC_Geo_IP {
|
|||
}
|
||||
}
|
||||
|
||||
$this->log( 'GeoIP API: Error traversing database - perhaps it is corrupt?' );
|
||||
$this->log( 'GeoIP API: Error traversing database - perhaps it is corrupt?', 'error' );
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -185,7 +185,7 @@ class WC_Geolocation {
|
|||
$logger = wc_get_logger();
|
||||
|
||||
if ( ! is_callable( 'gzopen' ) ) {
|
||||
$logger->add( 'geolocation', 'Server does not support gzopen' );
|
||||
$logger->notice( 'Server does not support gzopen', array( 'source' => 'geolocation' ) );
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -208,11 +208,14 @@ class WC_Geolocation {
|
|||
gzclose( $gzhandle );
|
||||
fclose( $handle );
|
||||
} else {
|
||||
$logger->add( 'geolocation', 'Unable to open database file' );
|
||||
$logger->notice( 'Unable to open database file', array( 'source' => 'geolocation' ) );
|
||||
}
|
||||
@unlink( $tmp_database_path );
|
||||
} else {
|
||||
$logger->add( 'geolocation', 'Unable to download GeoIP Database: ' . $tmp_database_path->get_error_message() );
|
||||
$logger->notice(
|
||||
'Unable to download GeoIP Database: ' . $tmp_database_path->get_error_message(),
|
||||
array( 'source' => 'geolocation' )
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -245,7 +245,10 @@ class WC_Install {
|
|||
foreach ( self::get_db_update_callbacks() as $version => $update_callbacks ) {
|
||||
if ( version_compare( $current_db_version, $version, '<' ) ) {
|
||||
foreach ( $update_callbacks as $update_callback ) {
|
||||
$logger->add( 'wc_db_updates', sprintf( 'Queuing %s - %s', $version, $update_callback ) );
|
||||
$logger->info(
|
||||
sprintf( 'Queuing %s - %s', $version, $update_callback ),
|
||||
array( 'source' => 'wc_db_updates' )
|
||||
);
|
||||
self::$background_updater->push_to_queue( $update_callback );
|
||||
$update_queued = true;
|
||||
}
|
||||
|
@ -601,6 +604,16 @@ CREATE TABLE {$wpdb->prefix}woocommerce_payment_tokenmeta (
|
|||
PRIMARY KEY (meta_id),
|
||||
KEY payment_token_id (payment_token_id),
|
||||
KEY meta_key (meta_key($max_index_length))
|
||||
) $collate;
|
||||
CREATE TABLE {$wpdb->prefix}woocommerce_log (
|
||||
log_id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT,
|
||||
timestamp datetime NOT NULL,
|
||||
level smallint(4) NOT NULL,
|
||||
source varchar(255) NOT NULL,
|
||||
message longtext NOT NULL,
|
||||
context longtext NULL,
|
||||
PRIMARY KEY (log_id),
|
||||
KEY level (level)
|
||||
) $collate;
|
||||
";
|
||||
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Standard log levels
|
||||
*
|
||||
* @class WC_Log_Levels
|
||||
* @version 1.0.0
|
||||
* @package WooCommerce/Classes
|
||||
* @category Class
|
||||
* @author WooThemes
|
||||
*/
|
||||
abstract class WC_Log_Levels {
|
||||
|
||||
/**
|
||||
* Log Levels
|
||||
*
|
||||
* Description of levels:
|
||||
* 'emergency': System is unusable.
|
||||
* 'alert': Action must be taken immediately.
|
||||
* 'critical': Critical conditions.
|
||||
* 'error': Error conditions.
|
||||
* 'warning': Warning conditions.
|
||||
* 'notice': Normal but significant condition.
|
||||
* 'informational': Informational messages.
|
||||
* 'debug': Debug-level messages.
|
||||
*
|
||||
* @see @link {https://tools.ietf.org/html/rfc5424}
|
||||
*/
|
||||
const EMERGENCY = 'emergency';
|
||||
const ALERT = 'alert';
|
||||
const CRITICAL = 'critical';
|
||||
const ERROR = 'error';
|
||||
const WARNING = 'warning';
|
||||
const NOTICE = 'notice';
|
||||
const INFO = 'info';
|
||||
const DEBUG = 'debug';
|
||||
|
||||
/**
|
||||
* Level strings mapped to integer severity.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $level_to_severity = array(
|
||||
self::EMERGENCY => 800,
|
||||
self::ALERT => 700,
|
||||
self::CRITICAL => 600,
|
||||
self::ERROR => 500,
|
||||
self::WARNING => 400,
|
||||
self::NOTICE => 300,
|
||||
self::INFO => 200,
|
||||
self::DEBUG => 100,
|
||||
);
|
||||
|
||||
/**
|
||||
* Severity integers mapped to level strings.
|
||||
*
|
||||
* This is the inverse of $level_severity.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected static $severity_to_level = array(
|
||||
800 => self::EMERGENCY,
|
||||
700 => self::ALERT,
|
||||
600 => self::CRITICAL,
|
||||
500 => self::ERROR,
|
||||
400 => self::WARNING,
|
||||
300 => self::NOTICE,
|
||||
200 => self::INFO,
|
||||
100 => self::DEBUG,
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Validate a level string.
|
||||
*
|
||||
* @param string $level
|
||||
* @return bool True if $level is a valid level.
|
||||
*/
|
||||
public static function is_valid_level( $level ) {
|
||||
return array_key_exists( strtolower( $level ), self::$level_to_severity );
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate level string to integer.
|
||||
*
|
||||
* @param string $level emergency|alert|critical|error|warning|notice|info|debug
|
||||
* @return int 100 (debug) - 800 (emergency) or 0 if not recognized
|
||||
*/
|
||||
public static function get_level_severity( $level ) {
|
||||
if ( self::is_valid_level( $level ) ) {
|
||||
$severity = self::$level_to_severity[ strtolower( $level ) ];
|
||||
} else {
|
||||
$severity = 0;
|
||||
}
|
||||
return $severity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Translate severity integer to level string.
|
||||
*
|
||||
* @param int $severity
|
||||
* @return bool|string False if not recognized. Otherwise string representation of level.
|
||||
*/
|
||||
public static function get_severity_level( $severity ) {
|
||||
if ( array_key_exists( $severity, self::$severity_to_level ) ) {
|
||||
return self::$severity_to_level[ $severity ];
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,14 +1,13 @@
|
|||
<?php
|
||||
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows log files to be written to for debugging purposes
|
||||
* Provides logging capabilities for debugging purposes.
|
||||
*
|
||||
* @class WC_Logger
|
||||
* @version 1.6.4
|
||||
* @version 2.0.0
|
||||
* @package WooCommerce/Classes
|
||||
* @category Class
|
||||
* @author WooThemes
|
||||
|
@ -16,147 +15,223 @@ if ( ! defined( 'ABSPATH' ) ) {
|
|||
class WC_Logger {
|
||||
|
||||
/**
|
||||
* Stores open file _handles.
|
||||
* Stores registered log handlers.
|
||||
*
|
||||
* @var array
|
||||
* @access private
|
||||
*/
|
||||
private $_handles;
|
||||
protected $handlers;
|
||||
|
||||
/**
|
||||
* Minimum log level this handler will process.
|
||||
*
|
||||
* @var int Integer representation of minimum log level to handle.
|
||||
*/
|
||||
protected $threshold;
|
||||
|
||||
/**
|
||||
* Constructor for the logger.
|
||||
*/
|
||||
public function __construct() {
|
||||
$this->_handles = array();
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*/
|
||||
public function __destruct() {
|
||||
foreach ( $this->_handles as $handle ) {
|
||||
if ( is_resource( $handle ) ) {
|
||||
fclose( $handle );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open log file for writing.
|
||||
*
|
||||
* @param string $handle
|
||||
* @param string $mode
|
||||
* @return bool success
|
||||
* @param array $handlers Optional. Array of log handlers. If $handlers is not provided,
|
||||
* the filter 'woocommerce_register_log_handlers' will be used to define the handlers.
|
||||
* If $handlers is provided, the filter will not be applied and the handlers will be
|
||||
* used directly.
|
||||
* @param string $threshold Optional. Define an explicit threshold. May be configured
|
||||
* via WC_LOG_THRESHOLD. By default, all logs will be processed.
|
||||
*/
|
||||
protected function open( $handle, $mode = 'a' ) {
|
||||
if ( isset( $this->_handles[ $handle ] ) ) {
|
||||
public function __construct( $handlers = null, $threshold = null ) {
|
||||
if ( null === $handlers ) {
|
||||
$handlers = apply_filters( 'woocommerce_register_log_handlers', array() );
|
||||
}
|
||||
|
||||
if ( null !== $threshold ) {
|
||||
$threshold = WC_Log_Levels::get_level_severity( $threshold );
|
||||
} elseif ( defined( 'WC_LOG_THRESHOLD' ) && WC_Log_Levels::is_valid_level( WC_LOG_THRESHOLD ) ) {
|
||||
$threshold = WC_Log_Levels::get_level_severity( WC_LOG_THRESHOLD );
|
||||
} else {
|
||||
$threshold = null;
|
||||
}
|
||||
|
||||
$this->handlers = $handlers;
|
||||
$this->threshold = $threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether to handle or ignore log.
|
||||
*
|
||||
* @param string $level emergency|alert|critical|error|warning|notice|info|debug
|
||||
* @return bool True if the log should be handled.
|
||||
*/
|
||||
public function should_handle( $level ) {
|
||||
if ( null === $this->threshold ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( ! file_exists( wc_get_log_file_path( $handle ) ) ) {
|
||||
$temphandle = @fopen( wc_get_log_file_path( $handle ), 'w+' );
|
||||
@fclose( $temphandle );
|
||||
|
||||
if ( defined( 'FS_CHMOD_FILE' ) ) {
|
||||
@chmod( wc_get_log_file_path( $handle ), FS_CHMOD_FILE );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->_handles[ $handle ] = @fopen( wc_get_log_file_path( $handle ), $mode ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return $this->threshold <= WC_Log_Levels::get_level_severity( $level );
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a handle.
|
||||
* Add a log entry.
|
||||
*
|
||||
* @param string $handle
|
||||
* @return bool success
|
||||
*/
|
||||
protected function close( $handle ) {
|
||||
$result = false;
|
||||
|
||||
if ( is_resource( $this->_handles[ $handle ] ) ) {
|
||||
$result = fclose( $this->_handles[ $handle ] );
|
||||
unset( $this->_handles[ $handle ] );
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a log entry to chosen file.
|
||||
* This is not the preferred method for adding log messages. Please use log() or any one of
|
||||
* the level methods (debug(), info(), etc.). This method may be deprecated in the future.
|
||||
*
|
||||
* @param string $handle
|
||||
* @param string $message
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function add( $handle, $message ) {
|
||||
$result = false;
|
||||
public function add( $handle, $message, $level = WC_Log_Levels::NOTICE ) {
|
||||
$message = apply_filters( 'woocommerce_logger_add_message', $message, $handle );
|
||||
$this->log( $level, $message, array( 'source' => $handle, '_legacy' => true ) );
|
||||
wc_do_deprecated_action( 'woocommerce_log_add', array( $handle, $message ), '2.7', 'This action has been deprecated with no alternative.' );
|
||||
return true;
|
||||
}
|
||||
|
||||
if ( $this->open( $handle ) && is_resource( $this->_handles[ $handle ] ) ) {
|
||||
$message = apply_filters( 'woocommerce_logger_add_message', $message, $handle );
|
||||
$time = date_i18n( 'm-d-Y @ H:i:s -' ); // Grab Time
|
||||
$result = fwrite( $this->_handles[ $handle ], $time . " " . $message . "\n" );
|
||||
/**
|
||||
* Add a log entry.
|
||||
*
|
||||
* @param string $level One of the following:
|
||||
* 'emergency': System is unusable.
|
||||
* 'alert': Action must be taken immediately.
|
||||
* 'critical': Critical conditions.
|
||||
* 'error': Error conditions.
|
||||
* 'warning': Warning conditions.
|
||||
* 'notice': Normal but significant condition.
|
||||
* 'informational': Informational messages.
|
||||
* 'debug': Debug-level messages.
|
||||
* @param string $message Log message.
|
||||
* @param array $context Optional. Additional information for log handlers.
|
||||
*/
|
||||
public function log( $level, $message, $context = array() ) {
|
||||
if ( ! WC_Log_Levels::is_valid_level( $level ) ) {
|
||||
$class = __CLASS__;
|
||||
$method = __FUNCTION__;
|
||||
wc_doing_it_wrong( "{$class}::{$method}", sprintf( __( 'WC_Logger::log was called with an invalid level "%s".', 'woocommerce' ), $level ), '2.7' );
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_log_add', $handle, $message );
|
||||
if ( $this->should_handle( $level ) ) {
|
||||
$timestamp = current_time( 'timestamp' );
|
||||
|
||||
return false !== $result;
|
||||
foreach ( $this->handlers as $handler ) {
|
||||
$handler->handle( $timestamp, $level, $message, $context );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an emergency level message.
|
||||
*
|
||||
* System is unusable.
|
||||
*
|
||||
* @see WC_Logger::log
|
||||
*/
|
||||
public function emergency( $message, $context = array() ) {
|
||||
$this->log( WC_Log_Levels::EMERGENCY, $message, $context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an alert level message.
|
||||
*
|
||||
* Action must be taken immediately.
|
||||
* Example: Entire website down, database unavailable, etc.
|
||||
*
|
||||
* @see WC_Logger::log
|
||||
*/
|
||||
public function alert( $message, $context = array() ) {
|
||||
$this->log( WC_Log_Levels::ALERT, $message, $context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a critical level message.
|
||||
*
|
||||
* Critical conditions.
|
||||
* Example: Application component unavailable, unexpected exception.
|
||||
*
|
||||
* @see WC_Logger::log
|
||||
*/
|
||||
public function critical( $message, $context = array() ) {
|
||||
$this->log( WC_Log_Levels::CRITICAL, $message, $context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an error level message.
|
||||
*
|
||||
* Runtime errors that do not require immediate action but should typically be logged
|
||||
* and monitored.
|
||||
*
|
||||
* @see WC_Logger::log
|
||||
*/
|
||||
public function error( $message, $context = array() ) {
|
||||
$this->log( WC_Log_Levels::ERROR, $message, $context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a warning level message.
|
||||
*
|
||||
* Exceptional occurrences that are not errors.
|
||||
*
|
||||
* Example: Use of deprecated APIs, poor use of an API, undesirable things that are not
|
||||
* necessarily wrong.
|
||||
*
|
||||
* @see WC_Logger::log
|
||||
*/
|
||||
public function warning( $message, $context = array() ) {
|
||||
$this->log( WC_Log_Levels::WARNING, $message, $context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a notice level message.
|
||||
*
|
||||
* Normal but significant events.
|
||||
*
|
||||
* @see WC_Logger::log
|
||||
*/
|
||||
public function notice( $message, $context = array() ) {
|
||||
$this->log( WC_Log_Levels::NOTICE, $message, $context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a info level message.
|
||||
*
|
||||
* Interesting events.
|
||||
* Example: User logs in, SQL logs.
|
||||
*
|
||||
* @see WC_Logger::log
|
||||
*/
|
||||
public function info( $message, $context = array() ) {
|
||||
$this->log( WC_Log_Levels::INFO, $message, $context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a debug level message.
|
||||
*
|
||||
* Detailed debug information.
|
||||
*
|
||||
* @see WC_Logger::log
|
||||
*/
|
||||
public function debug( $message, $context = array() ) {
|
||||
$this->log( WC_Log_Levels::DEBUG, $message, $context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear entries from chosen file.
|
||||
*
|
||||
* @param string $handle
|
||||
* @deprecated 2.7.0
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function clear( $handle ) {
|
||||
$result = false;
|
||||
|
||||
// Close the file if it's already open.
|
||||
$this->close( $handle );
|
||||
|
||||
/**
|
||||
* $this->open( $handle, 'w' ) == Open the file for writing only. Place the file pointer at the beginning of the file,
|
||||
* and truncate the file to zero length.
|
||||
*/
|
||||
if ( $this->open( $handle, 'w' ) && is_resource( $this->_handles[ $handle ] ) ) {
|
||||
$result = true;
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_log_clear', $handle );
|
||||
|
||||
return $result;
|
||||
public function clear() {
|
||||
wc_deprecated_function( 'WC_Logger::clear', '2.7', 'WC_Log_Handler_File::clear' );
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove/delete the chosen file.
|
||||
*
|
||||
* @param string $handle
|
||||
* @deprecated 2.7.0
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function remove( $handle ) {
|
||||
$removed = false;
|
||||
$handle = wc_clean( $handle );
|
||||
$file = wc_get_log_file_path( $handle );
|
||||
|
||||
if ( is_file( $file ) && is_writable( $file ) ) {
|
||||
// Close first to be certain no processes keep it alive after it is unlinked.
|
||||
$this->close( $handle );
|
||||
$removed = unlink( $file );
|
||||
} elseif ( is_file( trailingslashit( WC_LOG_DIR ) . sanitize_file_name( $handle . '.log' ) ) && is_writable( trailingslashit( WC_LOG_DIR ) . sanitize_file_name( $handle . '.log' ) ) ) {
|
||||
$this->close( $handle );
|
||||
$removed = unlink( trailingslashit( WC_LOG_DIR ) . sanitize_file_name( $handle . '.log' ) );
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_log_remove', $handle, $removed );
|
||||
|
||||
return $removed;
|
||||
public function remove() {
|
||||
wc_deprecated_function( 'WC_Logger::remove', '2.7', 'WC_Log_Handler_File::remove' );
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -418,7 +418,7 @@ class WC_Email extends WC_Settings_API {
|
|||
$content = $emogrifier->emogrify();
|
||||
} catch ( Exception $e ) {
|
||||
$logger = wc_get_logger();
|
||||
$logger->add( 'emogrifier', $e->getMessage() );
|
||||
$logger->error( $e->getMessage(), array( 'source' => 'emogrifier' ) );
|
||||
}
|
||||
}
|
||||
return $content;
|
||||
|
|
|
@ -74,14 +74,17 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
|
|||
|
||||
/**
|
||||
* Logging method.
|
||||
* @param string $message
|
||||
*
|
||||
* @param string $message Log message.
|
||||
* @param string $level Optional. Default 'info'.
|
||||
* emergency|alert|critical|error|warning|notice|info|debug
|
||||
*/
|
||||
public static function log( $message ) {
|
||||
public static function log( $message, $level = 'info' ) {
|
||||
if ( self::$log_enabled ) {
|
||||
if ( empty( self::$log ) ) {
|
||||
self::$log = wc_get_logger();
|
||||
}
|
||||
self::$log->add( 'paypal', $message );
|
||||
self::$log->log( $level, $message, array( 'source' => 'paypal' ) );
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -281,7 +284,7 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
|
|||
$order = wc_get_order( $order_id );
|
||||
|
||||
if ( ! $this->can_refund_order( $order ) ) {
|
||||
$this->log( 'Refund Failed: No transaction ID' );
|
||||
$this->log( 'Refund Failed: No transaction ID', 'error' );
|
||||
return new WP_Error( 'error', __( 'Refund failed: No transaction ID', 'woocommerce' ) );
|
||||
}
|
||||
|
||||
|
@ -290,11 +293,11 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
|
|||
$result = WC_Gateway_Paypal_API_Handler::refund_transaction( $order, $amount, $reason );
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
$this->log( 'Refund Failed: ' . $result->get_error_message() );
|
||||
$this->log( 'Refund Failed: ' . $result->get_error_message(), 'error' );
|
||||
return new WP_Error( 'error', $result->get_error_message() );
|
||||
}
|
||||
|
||||
$this->log( 'Refund Result: ' . print_r( $result, true ) );
|
||||
$this->log( 'Refund Result: ' . wc_print_r( $result, true ) );
|
||||
|
||||
switch ( strtolower( $result->ACK ) ) {
|
||||
case 'success':
|
||||
|
@ -320,12 +323,12 @@ class WC_Gateway_Paypal extends WC_Payment_Gateway {
|
|||
$result = WC_Gateway_Paypal_API_Handler::do_capture( $order );
|
||||
|
||||
if ( is_wp_error( $result ) ) {
|
||||
$this->log( 'Capture Failed: ' . $result->get_error_message() );
|
||||
$this->log( 'Capture Failed: ' . $result->get_error_message(), 'error' );
|
||||
$order->add_order_note( sprintf( __( 'Payment could not captured: %s', 'woocommerce' ), $result->get_error_message() ) );
|
||||
return;
|
||||
}
|
||||
|
||||
$this->log( 'Capture Result: ' . print_r( $result, true ) );
|
||||
$this->log( 'Capture Result: ' . wc_print_r( $result, true ) );
|
||||
|
||||
if ( ! empty( $result->PAYMENTSTATUS ) ) {
|
||||
switch ( $result->PAYMENTSTATUS ) {
|
||||
|
|
|
@ -88,7 +88,7 @@ class WC_Gateway_Paypal_API_Handler {
|
|||
)
|
||||
);
|
||||
|
||||
WC_Gateway_Paypal::log( 'DoCapture Response: ' . print_r( $raw_response, true ) );
|
||||
WC_Gateway_Paypal::log( 'DoCapture Response: ' . wc_print_r( $raw_response, true ) );
|
||||
|
||||
if ( empty( $raw_response['body'] ) ) {
|
||||
return new WP_Error( 'paypal-api', 'Empty Response' );
|
||||
|
@ -120,7 +120,7 @@ class WC_Gateway_Paypal_API_Handler {
|
|||
)
|
||||
);
|
||||
|
||||
WC_Gateway_Paypal::log( 'Refund Response: ' . print_r( $raw_response, true ) );
|
||||
WC_Gateway_Paypal::log( 'Refund Response: ' . wc_print_r( $raw_response, true ) );
|
||||
|
||||
if ( empty( $raw_response['body'] ) ) {
|
||||
return new WP_Error( 'paypal-api', 'Empty Response' );
|
||||
|
|
|
@ -91,8 +91,8 @@ class WC_Gateway_Paypal_IPN_Handler extends WC_Gateway_Paypal_Response {
|
|||
// Post back to get a response.
|
||||
$response = wp_safe_remote_post( $this->sandbox ? 'https://www.sandbox.paypal.com/cgi-bin/webscr' : 'https://www.paypal.com/cgi-bin/webscr', $params );
|
||||
|
||||
WC_Gateway_Paypal::log( 'IPN Request: ' . print_r( $params, true ) );
|
||||
WC_Gateway_Paypal::log( 'IPN Response: ' . print_r( $response, true ) );
|
||||
WC_Gateway_Paypal::log( 'IPN Request: ' . wc_print_r( $params, true ) );
|
||||
WC_Gateway_Paypal::log( 'IPN Response: ' . wc_print_r( $response, true ) );
|
||||
|
||||
// Check to see if the request was valid.
|
||||
if ( ! is_wp_error( $response ) && $response['response']['code'] >= 200 && $response['response']['code'] < 300 && strstr( $response['body'], 'VERIFIED' ) ) {
|
||||
|
|
|
@ -88,7 +88,7 @@ class WC_Gateway_Paypal_PDT_Handler extends WC_Gateway_Paypal_Response {
|
|||
|
||||
$transaction_result = $this->validate_transaction( $transaction );
|
||||
|
||||
WC_Gateway_Paypal::log( 'PDT Transaction Result: ' . print_r( $transaction_result, true ) );
|
||||
WC_Gateway_Paypal::log( 'PDT Transaction Result: ' . wc_print_r( $transaction_result, true ) );
|
||||
|
||||
update_post_meta( $order->get_id(), '_paypal_status', $status );
|
||||
update_post_meta( $order->get_id(), '_transaction_id', $transaction );
|
||||
|
@ -96,7 +96,7 @@ class WC_Gateway_Paypal_PDT_Handler extends WC_Gateway_Paypal_Response {
|
|||
if ( $transaction_result ) {
|
||||
if ( 'completed' === $status ) {
|
||||
if ( $order->get_total() != $amount ) {
|
||||
WC_Gateway_Paypal::log( 'Payment error: Amounts do not match (amt ' . $amount . ')' );
|
||||
WC_Gateway_Paypal::log( 'Payment error: Amounts do not match (amt ' . $amount . ')', 'error' );
|
||||
$this->payment_on_hold( $order, sprintf( __( 'Validation error: PayPal amounts do not match (amt %s).', 'woocommerce' ), $amount ) );
|
||||
} else {
|
||||
$this->payment_complete( $order, $transaction, __( 'PDT payment completed', 'woocommerce' ) );
|
||||
|
|
|
@ -45,7 +45,7 @@ class WC_Gateway_Paypal_Request {
|
|||
public function get_request_url( $order, $sandbox = false ) {
|
||||
$paypal_args = http_build_query( array_filter( $this->get_paypal_args( $order ) ), '', '&' );
|
||||
|
||||
WC_Gateway_Paypal::log( 'PayPal Request Args for order ' . $order->get_order_number() . ': ' . print_r( $paypal_args, true ) );
|
||||
WC_Gateway_Paypal::log( 'PayPal Request Args for order ' . $order->get_order_number() . ': ' . wc_print_r( $paypal_args, true ) );
|
||||
|
||||
if ( $sandbox ) {
|
||||
return 'https://www.sandbox.paypal.com/cgi-bin/webscr?test_ipn=1&' . $paypal_args;
|
||||
|
|
|
@ -30,7 +30,7 @@ abstract class WC_Gateway_Paypal_Response {
|
|||
|
||||
// Nothing was found.
|
||||
} else {
|
||||
WC_Gateway_Paypal::log( 'Error: Order ID and key were not found in "custom".' );
|
||||
WC_Gateway_Paypal::log( 'Order ID and key were not found in "custom".', 'error' );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ abstract class WC_Gateway_Paypal_Response {
|
|||
}
|
||||
|
||||
if ( ! $order || $order->get_order_key() !== $order_key ) {
|
||||
WC_Gateway_Paypal::log( 'Error: Order Keys do not match.' );
|
||||
WC_Gateway_Paypal::log( 'Order Keys do not match.', 'error' );
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ return array(
|
|||
'type' => 'checkbox',
|
||||
'label' => __( 'Enable logging', 'woocommerce' ),
|
||||
'default' => 'no',
|
||||
'description' => sprintf( __( 'Log PayPal events, such as IPN requests, inside %s', 'woocommerce' ), '<code>' . wc_get_log_file_path( 'paypal' ) . '</code>' ),
|
||||
'description' => sprintf( __( 'Log PayPal events, such as IPN requests, inside %s', 'woocommerce' ), '<code>' . WC_Log_Handler_File::get_log_file_path( 'paypal' ) . '</code>' ),
|
||||
),
|
||||
'advanced' => array(
|
||||
'title' => __( 'Advanced options', 'woocommerce' ),
|
||||
|
|
|
@ -0,0 +1,153 @@
|
|||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles log entries by writing to database.
|
||||
*
|
||||
* @class WC_Log_Handler_DB
|
||||
* @version 1.0.0
|
||||
* @package WooCommerce/Classes/Log_Handlers
|
||||
* @category Class
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_Log_Handler_DB extends WC_Log_Handler {
|
||||
|
||||
/**
|
||||
* Handle a log entry.
|
||||
*
|
||||
* @param int $timestamp Log timestamp.
|
||||
* @param string $level emergency|alert|critical|error|warning|notice|info|debug
|
||||
* @param string $message Log message.
|
||||
* @param array $context {
|
||||
* Additional information for log handlers.
|
||||
*
|
||||
* @type string $source Optional. Source will be available in log table.
|
||||
* If no source is provided, attempt to provide sensible default.
|
||||
* }
|
||||
*
|
||||
* @see WC_Log_Handler_DB::get_log_source() for default source.
|
||||
*
|
||||
* @return bool False if value was not handled and true if value was handled.
|
||||
*/
|
||||
public function handle( $timestamp, $level, $message, $context ) {
|
||||
|
||||
if ( isset( $context['source'] ) && $context['source'] ) {
|
||||
$source = $context['source'];
|
||||
} else {
|
||||
$source = $this->get_log_source();
|
||||
}
|
||||
|
||||
return $this->add( $timestamp, $level, $message, $source, $context );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a log entry to chosen file.
|
||||
*
|
||||
* @param int $timestamp Log timestamp.
|
||||
* @param string $level emergency|alert|critical|error|warning|notice|info|debug
|
||||
* @param string $message Log message.
|
||||
* @param string $source Log source. Useful for filtering and sorting.
|
||||
* @param array $context {
|
||||
* Context will be serialized and stored in database.
|
||||
* }
|
||||
*
|
||||
* @return bool True if write was successful.
|
||||
*/
|
||||
protected static function add( $timestamp, $level, $message, $source, $context ) {
|
||||
global $wpdb;
|
||||
|
||||
$insert = array(
|
||||
'timestamp' => date( 'Y-m-d H:i:s', $timestamp ),
|
||||
'level' => WC_Log_Levels::get_level_severity( $level ),
|
||||
'message' => $message,
|
||||
'source' => $source,
|
||||
);
|
||||
|
||||
$format = array(
|
||||
'%s',
|
||||
'%d',
|
||||
'%s',
|
||||
'%s',
|
||||
'%s', // possible serialized context
|
||||
);
|
||||
|
||||
if ( ! empty( $context ) ) {
|
||||
$insert['context'] = serialize( $context );
|
||||
}
|
||||
|
||||
return false !== $wpdb->insert( "{$wpdb->prefix}woocommerce_log", $insert, $format );
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all logs from the DB.
|
||||
*
|
||||
* @return bool True if flush was successful.
|
||||
*/
|
||||
public static function flush() {
|
||||
global $wpdb;
|
||||
|
||||
return $wpdb->query( "TRUNCATE TABLE {$wpdb->prefix}woocommerce_log" );
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete selected logs from DB.
|
||||
*
|
||||
* @param int|string|array Log ID or array of Log IDs to be deleted.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public static function delete( $log_ids ) {
|
||||
global $wpdb;
|
||||
|
||||
if ( ! is_array( $log_ids ) ) {
|
||||
$log_ids = array( $log_ids );
|
||||
}
|
||||
|
||||
$format = array_fill( 0, count( $log_ids ), '%d' );
|
||||
|
||||
$query_in = '(' . implode( ',', $format ) . ')';
|
||||
|
||||
$query = $wpdb->prepare(
|
||||
"DELETE FROM {$wpdb->prefix}woocommerce_log WHERE log_id IN {$query_in}",
|
||||
$log_ids
|
||||
);
|
||||
|
||||
return $wpdb->query( $query );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get appropriate source based on file name.
|
||||
*
|
||||
* Try to provide an appropriate source in case none is provided.
|
||||
*
|
||||
* @return string Text to use as log source. "" (empty string) if none is found.
|
||||
*/
|
||||
protected static function get_log_source() {
|
||||
static $ignore_files = array( 'class-wc-log-handler-db', 'class-wc-logger' );
|
||||
|
||||
/**
|
||||
* PHP < 5.3.6 correct behavior
|
||||
* @see http://php.net/manual/en/function.debug-backtrace.php#refsect1-function.debug-backtrace-parameters
|
||||
*/
|
||||
if ( defined( 'DEBUG_BACKTRACE_IGNORE_ARGS' ) ) {
|
||||
$debug_backtrace_arg = DEBUG_BACKTRACE_IGNORE_ARGS;
|
||||
} else {
|
||||
$debug_backtrace_arg = false;
|
||||
}
|
||||
|
||||
$trace = debug_backtrace( $debug_backtrace_arg );
|
||||
foreach ( $trace as $t ) {
|
||||
if ( isset( $t['file'] ) ) {
|
||||
$filename = pathinfo( $t['file'], PATHINFO_FILENAME );
|
||||
if ( ! in_array( $filename, $ignore_files ) ) {
|
||||
return $filename;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,216 @@
|
|||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles log entries by sending an email.
|
||||
*
|
||||
* WARNING!
|
||||
* This log handler has known limitations.
|
||||
*
|
||||
* Log messages are aggregated and sent once per request (if necessary). If the site experiences a
|
||||
* problem, the log email may never be sent. This handler should be used with another handler which
|
||||
* stores logs in order to prevent loss.
|
||||
*
|
||||
* It is not recommended to use this handler on a high traffic site. There will be a maximum of 1
|
||||
* email sent per request per handler, but that could still be a dangerous amount of emails under
|
||||
* heavy traffic. Do not confuse this handler with an appropriate monitoring solution!
|
||||
*
|
||||
* If you understand these limitations, feel free to use this handler or borrow parts of the design
|
||||
* to implement your own!
|
||||
*
|
||||
* @class WC_Log_Handler_Email
|
||||
* @version 1.0.0
|
||||
* @package WooCommerce/Classes/Log_Handlers
|
||||
* @category Class
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_Log_Handler_Email extends WC_Log_Handler {
|
||||
|
||||
/**
|
||||
* Minimum log level this handler will process.
|
||||
*
|
||||
* @var int Integer representation of minimum log level to handle.
|
||||
*/
|
||||
protected $threshold;
|
||||
|
||||
/**
|
||||
* Stores email recipients.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $recipients = array();
|
||||
|
||||
/**
|
||||
* Stores log messages.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $logs = array();
|
||||
|
||||
/**
|
||||
* Stores integer representation of maximum logged level.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $max_severity = null;
|
||||
|
||||
/**
|
||||
* Constructor for log handler.
|
||||
*
|
||||
* @param string|array $recipients Optional. Email(s) to receive log messages. Defaults to site admin email.
|
||||
* @param string $threshold Optional. Minimum level that should receive log messages.
|
||||
* Default 'alert'. One of: emergency|alert|critical|error|warning|notice|info|debug
|
||||
*/
|
||||
public function __construct( $recipients = null, $threshold = 'alert' ) {
|
||||
if ( null === $recipients ) {
|
||||
$recipients = get_option( 'admin_email' );
|
||||
}
|
||||
|
||||
if ( is_array( $recipients ) ) {
|
||||
foreach ( $recipients as $recipient ) {
|
||||
$this->add_email( $recipient );
|
||||
}
|
||||
} else {
|
||||
$this->add_email( $recipients );
|
||||
}
|
||||
|
||||
$this->set_threshold( $threshold );
|
||||
add_action( 'shutdown', array( $this, 'send_log_email' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Set handler severity threshold.
|
||||
*
|
||||
* @param string $level emergency|alert|critical|error|warning|notice|info|debug
|
||||
*/
|
||||
public function set_threshold( $level ) {
|
||||
$this->threshold = WC_Log_Levels::get_level_severity( $level );
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether handler should handle log.
|
||||
*
|
||||
* @param string $level emergency|alert|critical|error|warning|notice|info|debug
|
||||
* @return bool True if the log should be handled.
|
||||
*/
|
||||
protected function should_handle( $level ) {
|
||||
return $this->threshold <= WC_Log_Levels::get_level_severity( $level );
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a log entry.
|
||||
*
|
||||
* @param int $timestamp Log timestamp.
|
||||
* @param string $level emergency|alert|critical|error|warning|notice|info|debug
|
||||
* @param string $message Log message.
|
||||
* @param array $context Optional. Additional information for log handlers.
|
||||
*
|
||||
* @return bool False if value was not handled and true if value was handled.
|
||||
*/
|
||||
public function handle( $timestamp, $level, $message, $context ) {
|
||||
|
||||
if ( $this->should_handle( $level ) ) {
|
||||
$this->add_log( $timestamp, $level, $message, $context );
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Send log email.
|
||||
*
|
||||
* @return bool True if email is successfully sent otherwise false.
|
||||
*/
|
||||
public function send_log_email() {
|
||||
$result = false;
|
||||
|
||||
if ( ! empty( $this->logs ) ) {
|
||||
$subject = $this->get_subject();
|
||||
$body = $this->get_body();
|
||||
$result = wp_mail( $this->recipients, $subject, $body );
|
||||
$this->clear_logs();
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Build subject for log email.
|
||||
*
|
||||
* @return string subject
|
||||
*/
|
||||
protected function get_subject() {
|
||||
$site_name = get_bloginfo( 'name' );
|
||||
$max_level = strtoupper( WC_Log_Levels::get_severity_level( $this->max_severity ) );
|
||||
$log_count = count( $this->logs );
|
||||
|
||||
return sprintf(
|
||||
_n(
|
||||
'[%1$s] %2$s: %3$s WooCommerce log message',
|
||||
'[%1$s] %2$s: %3$s WooCommerce log messages',
|
||||
$log_count,
|
||||
'woocommerce'
|
||||
),
|
||||
$site_name,
|
||||
$max_level,
|
||||
$log_count
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Build body for log email.
|
||||
*
|
||||
* @return string body
|
||||
*/
|
||||
protected function get_body() {
|
||||
$site_name = get_bloginfo( 'name' );
|
||||
$entries = implode( PHP_EOL, $this->logs );
|
||||
$log_count = count( $this->logs );
|
||||
return _n(
|
||||
'You have received the following WooCommerce log message:',
|
||||
'You have received the following WooCommerce log messages:',
|
||||
$log_count,
|
||||
'woocommerce'
|
||||
)
|
||||
. PHP_EOL
|
||||
. PHP_EOL
|
||||
. $entries
|
||||
. PHP_EOL
|
||||
. PHP_EOL
|
||||
. sprintf( __( 'Visit %s admin area:', 'woocommerce' ), $site_name )
|
||||
. PHP_EOL
|
||||
. admin_url();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an email to the list of recipients.
|
||||
*
|
||||
* @param string email Email address to add
|
||||
*/
|
||||
public function add_email( $email ) {
|
||||
array_push( $this->recipients, $email );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add log message.
|
||||
*/
|
||||
protected function add_log( $timestamp, $level, $message, $context ) {
|
||||
$this->logs[] = $this->format_entry( $timestamp, $level, $message, $context );
|
||||
|
||||
$log_severity = WC_Log_Levels::get_level_severity( $level );
|
||||
if ( $this->max_severity < $log_severity ) {
|
||||
$this->max_severity = $log_severity;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear log messages.
|
||||
*/
|
||||
protected function clear_logs() {
|
||||
$this->logs = array();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,374 @@
|
|||
<?php
|
||||
if ( ! defined( 'ABSPATH' ) ) {
|
||||
exit; // Exit if accessed directly
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles log entries by writing to a file.
|
||||
*
|
||||
* @class WC_Log_Handler_File
|
||||
* @version 1.0.0
|
||||
* @package WooCommerce/Classes/Log_Handlers
|
||||
* @category Class
|
||||
* @author WooThemes
|
||||
*/
|
||||
class WC_Log_Handler_File extends WC_Log_Handler {
|
||||
|
||||
/**
|
||||
* Stores open file handles.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $handles = array();
|
||||
|
||||
/**
|
||||
* File size limit for log files in bytes.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $log_size_limit;
|
||||
|
||||
/**
|
||||
* Cache logs that could not be written.
|
||||
*
|
||||
* If a log is written too early in the request, pluggable functions may be unavailable. These
|
||||
* logs will be cached and written on 'plugins_loaded' action.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $cached_logs = array();
|
||||
|
||||
/**
|
||||
* Constructor for the logger.
|
||||
*
|
||||
* @param int $log_size_limit Optional. Size limit for log files. Default 5mb.
|
||||
*/
|
||||
public function __construct( $log_size_limit = null ) {
|
||||
|
||||
if ( null === $log_size_limit ) {
|
||||
$log_size_limit = 5 * 1024 * 1024;
|
||||
}
|
||||
|
||||
$this->log_size_limit = $log_size_limit;
|
||||
|
||||
add_action( 'plugins_loaded', array( $this, 'write_cached_logs' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Destructor.
|
||||
*
|
||||
* Cleans up open file handles.
|
||||
*/
|
||||
public function __destruct() {
|
||||
foreach ( $this->handles as $handle ) {
|
||||
if ( is_resource( $handle ) ) {
|
||||
fclose( $handle );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle a log entry.
|
||||
*
|
||||
* @param int $timestamp Log timestamp.
|
||||
* @param string $level emergency|alert|critical|error|warning|notice|info|debug
|
||||
* @param string $message Log message.
|
||||
* @param array $context {
|
||||
* Additional information for log handlers.
|
||||
*
|
||||
* @type string $source Optional. Determines log file to write to. Default 'log'.
|
||||
* @type bool $_legacy Optional. Default false. True to use outdated log format
|
||||
* orignally used in deprecated WC_Logger::add calls.
|
||||
* }
|
||||
*
|
||||
* @return bool False if value was not handled and true if value was handled.
|
||||
*/
|
||||
public function handle( $timestamp, $level, $message, $context ) {
|
||||
|
||||
if ( isset( $context['source'] ) && $context['source'] ) {
|
||||
$handle = $context['source'];
|
||||
} else {
|
||||
$handle = 'log';
|
||||
}
|
||||
|
||||
$entry = self::format_entry( $timestamp, $level, $message, $context );
|
||||
|
||||
return $this->add( $entry, $handle );
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds a log entry text from timestamp, level and message.
|
||||
*
|
||||
* @param int $timestamp Log timestamp.
|
||||
* @param string $level emergency|alert|critical|error|warning|notice|info|debug
|
||||
* @param string $message Log message.
|
||||
* @param array $context Additional information for log handlers.
|
||||
*
|
||||
* @return string Formatted log entry.
|
||||
*/
|
||||
protected static function format_entry( $timestamp, $level, $message, $context ) {
|
||||
|
||||
if ( isset( $context['_legacy'] ) && true === $context['_legacy'] ) {
|
||||
if ( isset( $context['source'] ) && $context['source'] ) {
|
||||
$handle = $context['source'];
|
||||
} else {
|
||||
$handle = 'log';
|
||||
}
|
||||
$message = apply_filters( 'woocommerce_logger_add_message', $message, $handle );
|
||||
$time = date_i18n( 'm-d-Y @ H:i:s' );
|
||||
$entry = "{$time} - {$message}";
|
||||
} else {
|
||||
$entry = parent::format_entry( $timestamp, $level, $message, $context );
|
||||
}
|
||||
|
||||
return $entry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open log file for writing.
|
||||
*
|
||||
* @param string $handle Log handle.
|
||||
* @param string $mode Optional. File mode. Default 'a'.
|
||||
* @return bool Success.
|
||||
*/
|
||||
protected function open( $handle, $mode = 'a' ) {
|
||||
if ( $this->is_open( $handle ) ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
$file = self::get_log_file_path( $handle );
|
||||
|
||||
if ( $file ) {
|
||||
if ( ! file_exists( $file ) ) {
|
||||
$temphandle = @fopen( $file, 'w+' );
|
||||
@fclose( $temphandle );
|
||||
|
||||
if ( defined( 'FS_CHMOD_FILE' ) ) {
|
||||
@chmod( $file, FS_CHMOD_FILE );
|
||||
}
|
||||
}
|
||||
|
||||
if ( $this->handles[ $handle ] = @fopen( $file, $mode ) ) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a handle is open.
|
||||
*
|
||||
* @param string $handle Log handle.
|
||||
* @return bool True if $handle is open.
|
||||
*/
|
||||
protected function is_open( $handle ) {
|
||||
return array_key_exists( $handle, $this->handles );
|
||||
}
|
||||
|
||||
/**
|
||||
* Close a handle.
|
||||
*
|
||||
* @param string $handle
|
||||
* @return bool success
|
||||
*/
|
||||
protected function close( $handle ) {
|
||||
$result = false;
|
||||
|
||||
if ( $this->is_open( $handle ) && is_resource( $this->handles[ $handle ] ) ) {
|
||||
$result = fclose( $this->handles[ $handle ] );
|
||||
unset( $this->handles[ $handle ] );
|
||||
}
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a log entry to chosen file.
|
||||
*
|
||||
* @param string $entry Log entry text
|
||||
* @param string $handle Log entry handle
|
||||
*
|
||||
* @return bool True if write was successful.
|
||||
*/
|
||||
protected function add( $entry, $handle ) {
|
||||
$result = false;
|
||||
|
||||
if ( $this->should_rotate( $handle ) ) {
|
||||
$this->log_rotate( $handle );
|
||||
}
|
||||
|
||||
if ( $this->open( $handle ) && is_resource( $this->handles[ $handle ] ) ) {
|
||||
$result = fwrite( $this->handles[ $handle ], $entry . PHP_EOL );
|
||||
} else {
|
||||
$this->cache_log( $entry, $handle );
|
||||
}
|
||||
|
||||
return false !== $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear entries from chosen file.
|
||||
*
|
||||
* @param string $handle
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function clear( $handle ) {
|
||||
$result = false;
|
||||
|
||||
// Close the file if it's already open.
|
||||
$this->close( $handle );
|
||||
|
||||
/**
|
||||
* $this->open( $handle, 'w' ) == Open the file for writing only. Place the file pointer at
|
||||
* the beginning of the file, and truncate the file to zero length.
|
||||
*/
|
||||
if ( $this->open( $handle, 'w' ) && is_resource( $this->handles[ $handle ] ) ) {
|
||||
$result = true;
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_log_clear', $handle );
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove/delete the chosen file.
|
||||
*
|
||||
* @param string $handle
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function remove( $handle ) {
|
||||
$removed = false;
|
||||
$file = self::get_log_file_path( $handle );
|
||||
|
||||
if ( $file ) {
|
||||
if ( is_file( $file ) && is_writable( $file ) ) {
|
||||
// Close first to be certain no processes keep it alive after it is unlinked.
|
||||
$this->close( $handle );
|
||||
$removed = unlink( $file );
|
||||
} elseif ( is_file( trailingslashit( WC_LOG_DIR ) . $handle . '.log' ) && is_writable( trailingslashit( WC_LOG_DIR ) . $handle . '.log' ) ) {
|
||||
$this->close( $handle );
|
||||
$removed = unlink( trailingslashit( WC_LOG_DIR ) . $handle . '.log' );
|
||||
}
|
||||
|
||||
do_action( 'woocommerce_log_remove', $handle, $removed );
|
||||
}
|
||||
|
||||
return $removed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if log file should be rotated.
|
||||
*
|
||||
* Compares the size of the log file to determine whether it is over the size limit.
|
||||
*
|
||||
* @param string $handle Log handle
|
||||
* @return bool True if if should be rotated.
|
||||
*/
|
||||
protected function should_rotate( $handle ) {
|
||||
$file = self::get_log_file_path( $handle );
|
||||
if ( $file ) {
|
||||
if ( $this->is_open( $handle ) ) {
|
||||
$file_stat = fstat( $this->handles[ $handle ] );
|
||||
return $file_stat['size'] > $this->log_size_limit;
|
||||
} elseif ( file_exists( $file ) ) {
|
||||
return filesize( $file ) > $this->log_size_limit;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Rotate log files.
|
||||
*
|
||||
* Logs are rotatated by prepending '.x' to the '.log' suffix.
|
||||
* The current log plus 10 historical logs are maintained.
|
||||
* For example:
|
||||
* base.9.log -> [ REMOVED ]
|
||||
* base.8.log -> base.9.log
|
||||
* ...
|
||||
* base.0.log -> base.1.log
|
||||
* base.log -> base.0.log
|
||||
*
|
||||
* @param string $handle Log handle
|
||||
*/
|
||||
protected function log_rotate( $handle ) {
|
||||
for ( $i = 8; $i >= 0; $i-- ) {
|
||||
$this->increment_log_infix( $handle, $i );
|
||||
}
|
||||
$this->increment_log_infix( $handle );
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment a log file suffix.
|
||||
*
|
||||
* @param string $handle Log handle
|
||||
* @param null|int $number Optional. Default null. Log suffix number to be incremented.
|
||||
* @return bool True if increment was successful, otherwise false.
|
||||
*/
|
||||
protected function increment_log_infix( $handle, $number = null ) {
|
||||
if ( null === $number ) {
|
||||
$suffix = '';
|
||||
$next_suffix = '.0';
|
||||
} else {
|
||||
$suffix = '.' . $number;
|
||||
$next_suffix = '.' . ($number + 1);
|
||||
}
|
||||
|
||||
$rename_from = self::get_log_file_path( "{$handle}{$suffix}" );
|
||||
$rename_to = self::get_log_file_path( "{$handle}{$next_suffix}" );
|
||||
|
||||
if ( $this->is_open( $rename_from ) ) {
|
||||
$this->close( $rename_from );
|
||||
}
|
||||
|
||||
if ( is_writable( $rename_from ) ) {
|
||||
return rename( $rename_from, $rename_to );
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a log file path.
|
||||
*
|
||||
* @param string $handle Log name.
|
||||
* @return bool|string The log file path or false if path cannot be determined.
|
||||
*/
|
||||
public static function get_log_file_path( $handle ) {
|
||||
if ( function_exists( 'wp_hash' ) ) {
|
||||
return trailingslashit( WC_LOG_DIR ) . $handle . '-' . sanitize_file_name( wp_hash( $handle ) ) . '.log';
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cache log to write later.
|
||||
*
|
||||
* @param string $entry Log entry text
|
||||
* @param string $handle Log entry handle
|
||||
*/
|
||||
protected function cache_log( $entry, $handle ) {
|
||||
$this->cached_logs[] = array(
|
||||
'entry' => $entry,
|
||||
'handle' => $handle,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Write cached logs.
|
||||
*/
|
||||
public function write_cached_logs() {
|
||||
foreach ( $this->cached_logs as $log ) {
|
||||
$this->add( $log['entry'], $log['handle'] );
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -757,11 +757,12 @@ function get_woocommerce_api_url( $path ) {
|
|||
* Get a log file path.
|
||||
*
|
||||
* @since 2.2
|
||||
*
|
||||
* @param string $handle name.
|
||||
* @return string the log file path.
|
||||
*/
|
||||
function wc_get_log_file_path( $handle ) {
|
||||
return trailingslashit( WC_LOG_DIR ) . sanitize_file_name( $handle ) . '-' . sanitize_file_name( wp_hash( $handle ) ) . '.log';
|
||||
return WC_Log_Handler_File::get_log_file_path( $handle );
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1416,13 +1417,74 @@ function wc_get_rounding_precision() {
|
|||
* @return WC_Logger
|
||||
*/
|
||||
function wc_get_logger() {
|
||||
if ( ! class_exists( 'WC_Logger' ) ) {
|
||||
include_once( dirname( __FILE__ ) . '/class-wc-logger.php' );
|
||||
static $logger = null;
|
||||
if ( null === $logger ) {
|
||||
$class = apply_filters( 'woocommerce_logging_class', 'WC_Logger' );
|
||||
$logger = new $class;
|
||||
}
|
||||
$class = apply_filters( 'woocommerce_logging_class', 'WC_Logger' );
|
||||
return new $class;
|
||||
return $logger;
|
||||
}
|
||||
|
||||
/**
|
||||
* Prints human-readable information about a variable.
|
||||
*
|
||||
* Some server environments blacklist some debugging functions. This function provides a safe way to
|
||||
* turn an expression into a printable, readable form without calling blacklisted functions.
|
||||
*
|
||||
* @since 2.7
|
||||
*
|
||||
* @param mixed $expression The expression to be printed.
|
||||
* @param bool $return Optional. Default false. Set to true to return the human-readable string.
|
||||
* @return string|bool False if expression could not be printed. True if the expression was printed.
|
||||
* If $return is true, a string representation will be returned.
|
||||
*/
|
||||
function wc_print_r( $expression, $return = false ) {
|
||||
$alternatives = array(
|
||||
array( 'func' => 'print_r', 'args' => array( $expression, true ) ),
|
||||
array( 'func' => 'var_export', 'args' => array( $expression, true ) ),
|
||||
array( 'func' => 'json_encode', 'args' => array( $expression ) ),
|
||||
array( 'func' => 'serialize', 'args' => array( $expression ) ),
|
||||
);
|
||||
|
||||
$alternatives = apply_filters( 'woocommerce_print_r_alternatives', $alternatives, $expression );
|
||||
|
||||
foreach ( $alternatives as $alternative ) {
|
||||
if ( function_exists( $alternative['func'] ) ) {
|
||||
$res = call_user_func_array( $alternative['func'], $alternative['args'] );
|
||||
if ( $return ) {
|
||||
return $res;
|
||||
} else {
|
||||
echo $res;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers the default log handler.
|
||||
*
|
||||
* @since 2.7
|
||||
* @param array $handlers
|
||||
* @return array
|
||||
*/
|
||||
function wc_register_default_log_handler( $handlers ) {
|
||||
|
||||
if ( defined( 'WC_LOG_HANDLER' ) && class_exists( WC_LOG_HANDLER ) ) {
|
||||
$handler_class = WC_LOG_HANDLER;
|
||||
$default_handler = new $handler_class();
|
||||
} else {
|
||||
$default_handler = new WC_Log_Handler_File();
|
||||
}
|
||||
|
||||
array_push( $handlers, $default_handler );
|
||||
|
||||
return $handlers;
|
||||
}
|
||||
add_filter( 'woocommerce_register_log_handlers', 'wc_register_default_log_handler' );
|
||||
|
||||
/**
|
||||
* Store user agents. Used for tracker.
|
||||
* @since 2.7.0
|
||||
|
|
|
@ -0,0 +1,137 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class WC_Tests_Log_Handler_DB
|
||||
* @package WooCommerce\Tests\Log
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class WC_Tests_Log_Handler_DB extends WC_Unit_Test_Case {
|
||||
public function setUp() {
|
||||
parent::setUp();
|
||||
WC_Log_Handler_DB::flush();
|
||||
}
|
||||
|
||||
public function tearDown() {
|
||||
WC_Log_Handler_DB::flush();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test handle writes to database correctly.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_handle() {
|
||||
global $wpdb;
|
||||
|
||||
$handler = new WC_Log_Handler_DB( array( 'threshold' => 'debug' ) );
|
||||
$time = time();
|
||||
$context = array( 1, 2, 'a', 'b', 'key' => 'value' );
|
||||
|
||||
$handler->handle( $time, 'debug', 'msg_debug', array( 'source' => 'source_debug' ) );
|
||||
$handler->handle( $time, 'info', 'msg_info', array( 'source' => 'source_info' ) );
|
||||
$handler->handle( $time, 'notice', 'msg_notice', array( 'source' => 'source_notice' ) );
|
||||
$handler->handle( $time, 'warning', 'msg_warning', array( 'source' => 'source_warning' ) );
|
||||
$handler->handle( $time, 'error', 'msg_error', array( 'source' => 'source_error' ) );
|
||||
$handler->handle( $time, 'critical', 'msg_critical', array( 'source' => 'source_critical' ) );
|
||||
$handler->handle( $time, 'alert', 'msg_alert', array( 'source' => 'source_alert' ) );
|
||||
$handler->handle( $time, 'emergency', 'msg_emergency', array( 'source' => 'source_emergency' ) );
|
||||
|
||||
$handler->handle( $time, 'debug', 'context_test', $context );
|
||||
|
||||
$log_entries = $wpdb->get_results( "SELECT timestamp, level, message, source, context FROM {$wpdb->prefix}woocommerce_log", ARRAY_A );
|
||||
|
||||
$expected_ts = date( 'Y-m-d H:i:s', $time );
|
||||
$expected = array(
|
||||
array(
|
||||
'timestamp' => $expected_ts,
|
||||
'level' => WC_Log_Levels::get_level_severity( 'debug' ),
|
||||
'message' => 'msg_debug',
|
||||
'source' => 'source_debug',
|
||||
'context' => serialize( array( 'source' => 'source_debug' ) ),
|
||||
),
|
||||
array(
|
||||
'timestamp' => $expected_ts,
|
||||
'level' => WC_Log_Levels::get_level_severity( 'info' ),
|
||||
'message' => 'msg_info',
|
||||
'source' => 'source_info',
|
||||
'context' => serialize( array( 'source' => 'source_info' ) ),
|
||||
),
|
||||
array(
|
||||
'timestamp' => $expected_ts,
|
||||
'level' => WC_Log_Levels::get_level_severity( 'notice' ),
|
||||
'message' => 'msg_notice',
|
||||
'source' => 'source_notice',
|
||||
'context' => serialize( array( 'source' => 'source_notice' ) ),
|
||||
),
|
||||
array(
|
||||
'timestamp' => $expected_ts,
|
||||
'level' => WC_Log_Levels::get_level_severity( 'warning' ),
|
||||
'message' => 'msg_warning',
|
||||
'source' => 'source_warning',
|
||||
'context' => serialize( array( 'source' => 'source_warning' ) ),
|
||||
),
|
||||
array(
|
||||
'timestamp' => $expected_ts,
|
||||
'level' => WC_Log_Levels::get_level_severity( 'error' ),
|
||||
'message' => 'msg_error',
|
||||
'source' => 'source_error',
|
||||
'context' => serialize( array( 'source' => 'source_error' ) ),
|
||||
),
|
||||
array(
|
||||
'timestamp' => $expected_ts,
|
||||
'level' => WC_Log_Levels::get_level_severity( 'critical' ),
|
||||
'message' => 'msg_critical',
|
||||
'source' => 'source_critical',
|
||||
'context' => serialize( array( 'source' => 'source_critical' ) ),
|
||||
),
|
||||
array(
|
||||
'timestamp' => $expected_ts,
|
||||
'level' => WC_Log_Levels::get_level_severity( 'alert' ),
|
||||
'message' => 'msg_alert',
|
||||
'source' => 'source_alert',
|
||||
'context' => serialize( array( 'source' => 'source_alert' ) ),
|
||||
),
|
||||
array(
|
||||
'timestamp' => $expected_ts,
|
||||
'level' => WC_Log_Levels::get_level_severity( 'emergency' ),
|
||||
'message' => 'msg_emergency',
|
||||
'source' => 'source_emergency',
|
||||
'context' => serialize( array( 'source' => 'source_emergency' ) ),
|
||||
),
|
||||
array(
|
||||
'timestamp' => $expected_ts,
|
||||
'level' => WC_Log_Levels::get_level_severity( 'debug' ),
|
||||
'message' => 'context_test',
|
||||
'source' => pathinfo( __FILE__, PATHINFO_FILENAME ),
|
||||
'context' => serialize( $context ),
|
||||
),
|
||||
);
|
||||
|
||||
$this->assertEquals( $log_entries, $expected );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test flush.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_flush() {
|
||||
global $wpdb;
|
||||
|
||||
$handler = new WC_Log_Handler_DB( array( 'threshold' => 'debug' ) );
|
||||
$time = time();
|
||||
|
||||
$handler->handle( $time, 'debug', '', array() );
|
||||
|
||||
$log_entries = $wpdb->get_results( "SELECT timestamp, level, message, source FROM {$wpdb->prefix}woocommerce_log" );
|
||||
$this->assertCount( 1, $log_entries );
|
||||
|
||||
WC_Log_Handler_DB::flush();
|
||||
|
||||
$log_entries = $wpdb->get_results( "SELECT timestamp, level, message, source FROM {$wpdb->prefix}woocommerce_log" );
|
||||
$this->assertCount( 0, $log_entries );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,245 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class WC_Tests_Log_Handler_Email
|
||||
* @package WooCommerce\Tests\Log
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class WC_Tests_Log_Handler_Email extends WC_Unit_Test_Case {
|
||||
|
||||
function setUp() {
|
||||
parent::setUp();
|
||||
reset_phpmailer_instance();
|
||||
}
|
||||
|
||||
function tearDown() {
|
||||
reset_phpmailer_instance();
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test handle sends email correctly.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_handle() {
|
||||
$mailer = tests_retrieve_phpmailer_instance();
|
||||
$time = time();
|
||||
$site_name = get_bloginfo( 'name' );
|
||||
|
||||
$handler = new WC_Log_Handler_Email();
|
||||
$handler->handle( $time, 'emergency', 'msg_emergency', array() );
|
||||
$handler->handle( $time, 'emergency', 'msg_emergency 2', array() );
|
||||
$handler->send_log_email();
|
||||
|
||||
$this->assertEquals(
|
||||
(
|
||||
'You have received the following WooCommerce log messages:'
|
||||
. PHP_EOL
|
||||
. PHP_EOL
|
||||
. date( 'c', $time ) . ' EMERGENCY msg_emergency'
|
||||
. PHP_EOL
|
||||
. date( 'c', $time ) . ' EMERGENCY msg_emergency 2'
|
||||
. PHP_EOL
|
||||
. PHP_EOL
|
||||
. "Visit {$site_name} admin area:"
|
||||
. PHP_EOL
|
||||
. admin_url()
|
||||
. PHP_EOL
|
||||
),
|
||||
$mailer->get_sent( 0 )->body
|
||||
);
|
||||
$this->assertEquals(
|
||||
"[{$site_name}] EMERGENCY: 2 WooCommerce log messages",
|
||||
$mailer->get_sent( 0 )->subject
|
||||
);
|
||||
$this->assertEquals( get_option( 'admin_email' ), $mailer->get_recipient( 'to' )->address );
|
||||
|
||||
$handler->handle( $time, 'emergency', 'msg_emergency', array() );
|
||||
$handler->send_log_email();
|
||||
$this->assertEquals(
|
||||
(
|
||||
'You have received the following WooCommerce log message:'
|
||||
. PHP_EOL
|
||||
. PHP_EOL
|
||||
. date( 'c', $time ) . ' EMERGENCY msg_emergency'
|
||||
. PHP_EOL
|
||||
. PHP_EOL
|
||||
. "Visit {$site_name} admin area:"
|
||||
. PHP_EOL
|
||||
. admin_url()
|
||||
. PHP_EOL
|
||||
),
|
||||
$mailer->get_sent( 1 )->body
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test email subject
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_email_subject() {
|
||||
$mailer = tests_retrieve_phpmailer_instance();
|
||||
$time = time();
|
||||
$site_name = get_bloginfo( 'name' );
|
||||
|
||||
$handler = new WC_Log_Handler_Email( null, WC_Log_Levels::DEBUG );
|
||||
$handler->handle( $time, 'debug', '', array() );
|
||||
$handler->send_log_email();
|
||||
|
||||
$handler->handle( $time, 'alert', '', array() );
|
||||
$handler->handle( $time, 'critical', '', array() );
|
||||
$handler->handle( $time, 'debug', '', array() );
|
||||
$handler->send_log_email();
|
||||
|
||||
$this->assertEquals(
|
||||
"[{$site_name}] DEBUG: 1 WooCommerce log message",
|
||||
$mailer->get_sent( 0 )->subject
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
"[{$site_name}] ALERT: 3 WooCommerce log messages",
|
||||
$mailer->get_sent( 1 )->subject
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test multiple recipients receive emails.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_multiple_recipients() {
|
||||
$mailer = tests_retrieve_phpmailer_instance();
|
||||
|
||||
$handler = new WC_Log_Handler_Email( array(
|
||||
'first@test.com',
|
||||
'Second Recipient <second@test.com>',
|
||||
) );
|
||||
$handler->handle( time(), 'emergency', '', array() );
|
||||
$handler->send_log_email();
|
||||
|
||||
$first_recipient = $mailer->get_recipient( 'to', 0, 0 );
|
||||
$second_recipient = $mailer->get_recipient( 'to', 0, 1 );
|
||||
|
||||
$this->assertEquals( 'first@test.com', $first_recipient->address );
|
||||
$this->assertEquals( 'second@test.com', $second_recipient->address );
|
||||
$this->assertEquals( 'Second Recipient', $second_recipient->name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test single recipient receives emails.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_single_recipient() {
|
||||
$mailer = tests_retrieve_phpmailer_instance();
|
||||
|
||||
$handler = new WC_Log_Handler_Email( 'User <user@test.com>' );
|
||||
$handler->handle( time(), 'emergency', '', array() );
|
||||
$handler->send_log_email();
|
||||
|
||||
$recipient = $mailer->get_recipient( 'to' );
|
||||
$this->assertEquals( 'user@test.com', $recipient->address );
|
||||
$this->assertEquals( 'User', $recipient->name );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test threshold.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_threshold() {
|
||||
$mailer = tests_retrieve_phpmailer_instance();
|
||||
|
||||
$handler = new WC_Log_Handler_Email( null, 'notice' );
|
||||
$handler->handle( time(), 'info', '', array() );
|
||||
$handler->send_log_email();
|
||||
|
||||
// Info should not be handled, get_sent is false
|
||||
$this->assertFalse( $mailer->get_sent( 0 ) );
|
||||
|
||||
$handler->handle( time(), 'notice', '', array() );
|
||||
$handler->send_log_email();
|
||||
$this->assertObjectHasAttribute( 'body', $mailer->get_sent( 0 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test set_threshold().
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_set_threshold() {
|
||||
$mailer = tests_retrieve_phpmailer_instance();
|
||||
|
||||
$handler = new WC_Log_Handler_Email( null, 'notice' );
|
||||
$handler->handle( time(), 'info', '', array() );
|
||||
$handler->send_log_email();
|
||||
|
||||
// Info should not be handled, get_sent is false
|
||||
$this->assertFalse( $mailer->get_sent( 0 ) );
|
||||
|
||||
$handler->set_threshold( 'info' );
|
||||
$handler->handle( time(), 'info', '', array() );
|
||||
$handler->send_log_email();
|
||||
|
||||
$this->assertObjectHasAttribute( 'body', $mailer->get_sent( 0 ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test send_log_email clears logs.
|
||||
*
|
||||
* Send log email could be called multiple times during a request. The same log should not be
|
||||
* sent multiple times.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_multiple_send_log() {
|
||||
$mailer = tests_retrieve_phpmailer_instance();
|
||||
|
||||
$handler = new WC_Log_Handler_Email();
|
||||
$time = time();
|
||||
$handler->handle( $time, 'emergency', 'message 1', array() );
|
||||
$handler->send_log_email();
|
||||
$handler->handle( $time, 'emergency', 'message 2', array() );
|
||||
$handler->send_log_email();
|
||||
|
||||
$site_name = get_bloginfo( 'name' );
|
||||
|
||||
$this->assertEquals(
|
||||
(
|
||||
'You have received the following WooCommerce log message:'
|
||||
. PHP_EOL
|
||||
. PHP_EOL
|
||||
. date( 'c', $time ) . ' EMERGENCY message 1'
|
||||
. PHP_EOL
|
||||
. PHP_EOL
|
||||
. "Visit {$site_name} admin area:"
|
||||
. PHP_EOL
|
||||
. admin_url()
|
||||
. PHP_EOL
|
||||
),
|
||||
$mailer->get_sent( 0 )->body
|
||||
);
|
||||
|
||||
$this->assertEquals(
|
||||
(
|
||||
'You have received the following WooCommerce log message:'
|
||||
. PHP_EOL
|
||||
. PHP_EOL
|
||||
. date( 'c', $time ) . ' EMERGENCY message 2'
|
||||
. PHP_EOL
|
||||
. PHP_EOL
|
||||
. "Visit {$site_name} admin area:"
|
||||
. PHP_EOL
|
||||
. admin_url()
|
||||
. PHP_EOL
|
||||
),
|
||||
$mailer->get_sent( 1 )->body
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,204 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class WC_Tests_Log_Handler_File
|
||||
* @package WooCommerce\Tests\Log
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class WC_Tests_Log_Handler_File extends WC_Unit_Test_Case {
|
||||
|
||||
public function tearDown() {
|
||||
$log_files = array(
|
||||
'unit-tests',
|
||||
'log',
|
||||
'_test_clear',
|
||||
'_test_remove',
|
||||
'_test_log_rotate',
|
||||
'_test_log_rotate.0',
|
||||
'_test_log_rotate.1',
|
||||
'_test_log_rotate.2',
|
||||
'_test_log_rotate.3',
|
||||
'_test_log_rotate.4',
|
||||
'_test_log_rotate.5',
|
||||
'_test_log_rotate.6',
|
||||
'_test_log_rotate.7',
|
||||
'_test_log_rotate.8',
|
||||
'_test_log_rotate.9',
|
||||
);
|
||||
|
||||
foreach ( $log_files as $file ) {
|
||||
$file_path = WC_Log_Handler_File::get_log_file_path( $file );
|
||||
if ( file_exists( $file_path ) && is_writable( $file_path ) ) {
|
||||
unlink( $file_path );
|
||||
}
|
||||
}
|
||||
parent::tearDown();
|
||||
}
|
||||
|
||||
public function read_content( $handle ) {
|
||||
return file_get_contents( WC_Log_Handler_File::get_log_file_path( $handle ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test _legacy format.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_legacy_format() {
|
||||
$handler = new WC_Log_Handler_File( array( 'threshold' => 'debug' ) );
|
||||
|
||||
$handler->handle( time(), 'info', 'this is a message', array( 'source' => 'unit-tests', '_legacy' => true ) );
|
||||
|
||||
$this->assertStringMatchesFormat( '%d-%d-%d @ %d:%d:%d - %s', $this->read_content( 'unit-tests' ) );
|
||||
$this->assertStringEndsWith( ' - this is a message' . PHP_EOL, $this->read_content( 'unit-tests' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test clear().
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_clear() {
|
||||
$handler = new WC_Log_Handler_File();
|
||||
$log_name = '_test_clear';
|
||||
$handler->handle( time(), 'debug', 'debug', array( 'source' => $log_name ) );
|
||||
$handler->clear( $log_name );
|
||||
$this->assertEquals( '', $this->read_content( $log_name ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test remove().
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_remove() {
|
||||
$handler = new WC_Log_Handler_File();
|
||||
$log_name = '_test_remove';
|
||||
$handler->handle( time(), 'debug', 'debug', array( 'source' => $log_name ) );
|
||||
$handler->remove( $log_name );
|
||||
$this->assertFileNotExists( WC_Log_Handler_File::get_log_file_path( $log_name ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test handle writes to default file correctly.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_writes_file() {
|
||||
$handler = new WC_Log_Handler_File();
|
||||
$time = time();
|
||||
|
||||
$handler->handle( $time, 'debug', 'debug', array() );
|
||||
$handler->handle( $time, 'info', 'info', array() );
|
||||
$handler->handle( $time, 'notice', 'notice', array() );
|
||||
$handler->handle( $time, 'warning', 'warning', array() );
|
||||
$handler->handle( $time, 'error', 'error', array() );
|
||||
$handler->handle( $time, 'critical', 'critical', array() );
|
||||
$handler->handle( $time, 'alert', 'alert', array() );
|
||||
$handler->handle( $time, 'emergency', 'emergency', array() );
|
||||
|
||||
$log_content = $this->read_content( 'log' );
|
||||
$this->assertStringMatchesFormatFile( dirname( __FILE__ ) . '/test_log_expected.txt', $log_content );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test 'source' context determines log file.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_log_file_source() {
|
||||
$handler = new WC_Log_Handler_File();
|
||||
$time = time();
|
||||
$context_source = array( 'source' => 'unit-tests' );
|
||||
|
||||
$handler->handle( $time, 'debug', 'debug', $context_source );
|
||||
$handler->handle( $time, 'info', 'info', $context_source );
|
||||
$handler->handle( $time, 'notice', 'notice', $context_source );
|
||||
$handler->handle( $time, 'warning', 'warning', $context_source );
|
||||
$handler->handle( $time, 'error', 'error', $context_source );
|
||||
$handler->handle( $time, 'critical', 'critical', $context_source );
|
||||
$handler->handle( $time, 'alert', 'alert', $context_source );
|
||||
$handler->handle( $time, 'emergency', 'emergency', $context_source );
|
||||
|
||||
$log_content = $this->read_content( 'unit-tests' );
|
||||
$this->assertStringMatchesFormatFile( dirname( __FILE__ ) . '/test_log_expected.txt', $log_content );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test multiple handlers don't conflict on log writing.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_multiple_handlers() {
|
||||
$handler_a = new WC_Log_Handler_File();
|
||||
$handler_b = new WC_Log_Handler_File();
|
||||
$time = time();
|
||||
$context_source = array( 'source' => 'unit-tests' );
|
||||
|
||||
// Different loggers should not conflict.
|
||||
$handler_a->handle( $time, 'debug', 'debug', $context_source );
|
||||
$handler_b->handle( $time, 'info', 'info', $context_source );
|
||||
$handler_a->handle( $time, 'notice', 'notice', $context_source );
|
||||
$handler_b->handle( $time, 'warning', 'warning', $context_source );
|
||||
$handler_a->handle( $time, 'error', 'error', $context_source );
|
||||
$handler_b->handle( $time, 'critical', 'critical', $context_source );
|
||||
$handler_a->handle( $time, 'alert', 'alert', $context_source );
|
||||
$handler_b->handle( $time, 'emergency', 'emergency', $context_source );
|
||||
|
||||
$log_content = $this->read_content( 'unit-tests' );
|
||||
$this->assertStringMatchesFormatFile( dirname( __FILE__ ) . '/test_log_expected.txt', $log_content );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test log_rotate()
|
||||
*
|
||||
* Ensure logs are rotated correctly when limit is surpassed.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_log_rotate() {
|
||||
|
||||
// Handler with log size limit of 5mb
|
||||
$handler = new WC_Log_Handler_File( 5 * 1024 * 1024 );
|
||||
$time = time();
|
||||
$log_name = '_test_log_rotate';
|
||||
$base_log_file = WC_Log_Handler_File::get_log_file_path( $log_name );
|
||||
|
||||
// Create log file larger than 5mb to ensure log is rotated
|
||||
$handle = fopen( $base_log_file, 'w' );
|
||||
fseek( $handle, 5 * 1024 * 1024 );
|
||||
fwrite( $handle, '_base_log_file_contents_' );
|
||||
fclose( $handle );
|
||||
|
||||
// Write some files to ensure they've rotated correctly
|
||||
for ( $i = 0; $i < 10; $i++ ) {
|
||||
file_put_contents( WC_Log_Handler_File::get_log_file_path( $log_name . ".{$i}" ), $i );
|
||||
}
|
||||
|
||||
$context_source = array( 'source' => $log_name );
|
||||
$handler->handle( $time, 'emergency', 'emergency', $context_source );
|
||||
|
||||
$this->assertFileExists( WC_Log_Handler_File::get_log_file_path( $log_name ) );
|
||||
|
||||
// Ensure the handled log is correct
|
||||
$this->assertStringEndsWith( 'EMERGENCY emergency' . PHP_EOL, $this->read_content( $log_name ) );
|
||||
|
||||
// Ensure other logs have rotated correctly
|
||||
$this->assertEquals( '_base_log_file_contents_', trim( $this->read_content( $log_name . '.0' ) ) );
|
||||
for ( $i = 1; $i < 10; $i++ ) {
|
||||
$this->assertEquals( $i - 1, $this->read_content( $log_name . ".{$i}" ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get_log_file_path().
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_get_log_file_path() {
|
||||
$log_dir = trailingslashit( WC_LOG_DIR );
|
||||
$hash_name = sanitize_file_name( wp_hash( 'unit-tests' ) );
|
||||
$this->assertEquals( $log_dir . 'unit-tests-' . $hash_name . '.log', WC_Log_Handler_File::get_log_file_path( 'unit-tests' ) );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class WC_Tests_Logger
|
||||
* @package WooCommerce\Tests\Log
|
||||
* @since 2.7.0
|
||||
*/
|
||||
class WC_Tests_Log_Levels extends WC_Unit_Test_Case {
|
||||
|
||||
/**
|
||||
* Test get_level_severity().
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_get_level_severity() {
|
||||
$this->assertEquals( 0, WC_Log_Levels::get_level_severity( 'unrecognized level' ) );
|
||||
$this->assertEquals( 100, WC_Log_Levels::get_level_severity( 'debug' ) );
|
||||
$this->assertEquals( 200, WC_Log_Levels::get_level_severity( 'info' ) );
|
||||
$this->assertEquals( 300, WC_Log_Levels::get_level_severity( 'notice' ) );
|
||||
$this->assertEquals( 400, WC_Log_Levels::get_level_severity( 'warning' ) );
|
||||
$this->assertEquals( 500, WC_Log_Levels::get_level_severity( 'error' ) );
|
||||
$this->assertEquals( 600, WC_Log_Levels::get_level_severity( 'critical' ) );
|
||||
$this->assertEquals( 700, WC_Log_Levels::get_level_severity( 'alert' ) );
|
||||
$this->assertEquals( 800, WC_Log_Levels::get_level_severity( 'emergency' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test get_severity_level().
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_get_severity_level() {
|
||||
$this->assertFalse( WC_Log_Levels::get_severity_level( 0 ) );
|
||||
$this->assertEquals( 'debug', WC_Log_Levels::get_severity_level( 100 ) );
|
||||
$this->assertEquals( 'info', WC_Log_Levels::get_severity_level( 200 ) );
|
||||
$this->assertEquals( 'notice', WC_Log_Levels::get_severity_level( 300 ) );
|
||||
$this->assertEquals( 'warning', WC_Log_Levels::get_severity_level( 400 ) );
|
||||
$this->assertEquals( 'error', WC_Log_Levels::get_severity_level( 500 ) );
|
||||
$this->assertEquals( 'critical', WC_Log_Levels::get_severity_level( 600 ) );
|
||||
$this->assertEquals( 'alert', WC_Log_Levels::get_severity_level( 700 ) );
|
||||
$this->assertEquals( 'emergency', WC_Log_Levels::get_severity_level( 800 ) );
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test is_valid_level().
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_is_valid_level() {
|
||||
$this->assertFalse( WC_Log_Levels::is_valid_level( 'unrecognized level' ) );
|
||||
$this->assertTrue( WC_Log_Levels::is_valid_level( 'debug' ) );
|
||||
$this->assertTrue( WC_Log_Levels::is_valid_level( 'info' ) );
|
||||
$this->assertTrue( WC_Log_Levels::is_valid_level( 'notice' ) );
|
||||
$this->assertTrue( WC_Log_Levels::is_valid_level( 'warning' ) );
|
||||
$this->assertTrue( WC_Log_Levels::is_valid_level( 'error' ) );
|
||||
$this->assertTrue( WC_Log_Levels::is_valid_level( 'critical' ) );
|
||||
$this->assertTrue( WC_Log_Levels::is_valid_level( 'alert' ) );
|
||||
$this->assertTrue( WC_Log_Levels::is_valid_level( 'emergency' ) );
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,303 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class WC_Tests_Logger
|
||||
* @package WooCommerce\Tests\Log
|
||||
* @since 2.3
|
||||
*/
|
||||
class WC_Tests_Logger extends WC_Unit_Test_Case {
|
||||
|
||||
/**
|
||||
* Test add().
|
||||
*
|
||||
* @since 2.4
|
||||
*/
|
||||
public function test_add() {
|
||||
$time = time();
|
||||
$handler = $this
|
||||
->getMockBuilder( 'WC_Log_Handler' )
|
||||
->setMethods( array( 'handle' ) )
|
||||
->getMock();
|
||||
$handler
|
||||
->expects( $this->once() )
|
||||
->method( 'handle' )
|
||||
->with(
|
||||
$this->greaterThanOrEqual( $time ),
|
||||
$this->equalTo( 'notice' ),
|
||||
$this->equalTo( 'this is a message' ),
|
||||
$this->equalTo( array( 'source' => 'unit-tests', '_legacy' => true ) )
|
||||
);
|
||||
$log = new WC_Logger( array( $handler ), 'debug' );
|
||||
|
||||
$log->add( 'unit-tests', 'this is a message' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test clear().
|
||||
*
|
||||
* @since 2.4
|
||||
*/
|
||||
public function test_clear() {
|
||||
$log = new WC_Logger( null, 'debug' );
|
||||
$log->clear( 'log' );
|
||||
$this->setExpectedDeprecated( 'WC_Logger::clear' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test log() complains for bad levels.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_bad_level() {
|
||||
$log = new WC_Logger( null, 'debug' );
|
||||
$log->log( 'this-is-an-invalid-level', '' );
|
||||
$this->setExpectedIncorrectUsage( 'WC_Logger::log' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test log().
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_log() {
|
||||
$handler = $this->create_mock_handler();
|
||||
$log = new WC_Logger( array( $handler ), 'debug' );
|
||||
$log->log( 'debug', 'debug message' );
|
||||
$log->log( 'info', 'info message' );
|
||||
$log->log( 'notice', 'notice message' );
|
||||
$log->log( 'warning', 'warning message' );
|
||||
$log->log( 'error', 'error message' );
|
||||
$log->log( 'critical', 'critical message' );
|
||||
$log->log( 'alert', 'alert message' );
|
||||
$log->log( 'emergency', 'emergency message' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test logs passed to all handlers.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_log_handlers() {
|
||||
$false_handler = $this
|
||||
->getMockBuilder( 'WC_Log_Handler' )
|
||||
->setMethods( array( 'handle' ) )
|
||||
->getMock();
|
||||
$false_handler->expects( $this->exactly( 8 ) )->method( 'handle' )->will( $this->returnValue( false ) );
|
||||
|
||||
$true_handler = $this
|
||||
->getMockBuilder( 'WC_Log_Handler' )
|
||||
->setMethods( array( 'handle' ) )
|
||||
->getMock();
|
||||
$false_handler->expects( $this->exactly( 8 ) )->method( 'handle' )->will( $this->returnValue( true ) );
|
||||
|
||||
$final_handler = $this
|
||||
->getMockBuilder( 'WC_Log_Handler' )
|
||||
->setMethods( array( 'handle' ) )
|
||||
->getMock();
|
||||
$final_handler->expects( $this->exactly( 8 ) )->method( 'handle' );
|
||||
|
||||
$log = new WC_Logger( array( $false_handler, $true_handler, $final_handler ), 'debug' );
|
||||
|
||||
$log->debug( 'debug' );
|
||||
$log->info( 'info' );
|
||||
$log->notice( 'notice' );
|
||||
$log->warning( 'warning' );
|
||||
$log->error( 'error' );
|
||||
$log->critical( 'critical' );
|
||||
$log->alert( 'alert' );
|
||||
$log->emergency( 'emergency' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test WC_Logger->[debug..emergency] methods
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_level_methods() {
|
||||
$handler = $this->create_mock_handler();
|
||||
$log = new WC_Logger( array( $handler ), 'debug' );
|
||||
$log->debug( 'debug message' );
|
||||
$log->info( 'info message' );
|
||||
$log->notice( 'notice message' );
|
||||
$log->warning( 'warning message' );
|
||||
$log->error( 'error message' );
|
||||
$log->critical( 'critical message' );
|
||||
$log->alert( 'alert message' );
|
||||
$log->emergency( 'emergency message' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test 'woocommerce_register_log_handlers' filter.
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_woocommerce_register_log_handlers_filter() {
|
||||
add_filter( 'woocommerce_register_log_handlers', array( $this, 'return_assertion_handlers' ) );
|
||||
$log = new WC_Logger( null, 'debug' );
|
||||
$log->debug( 'debug' );
|
||||
$log->info( 'info' );
|
||||
$log->notice( 'notice' );
|
||||
$log->warning( 'warning' );
|
||||
$log->error( 'error' );
|
||||
$log->critical( 'critical' );
|
||||
$log->alert( 'alert' );
|
||||
$log->emergency( 'emergency' );
|
||||
remove_filter( 'woocommerce_register_log_handlers', array( $this, 'return_assertion_handlers' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test no filtering by default
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_threshold_defaults() {
|
||||
$time = time();
|
||||
|
||||
// Test no filtering by default
|
||||
delete_option( 'woocommerce_log_threshold' );
|
||||
$handler = $this
|
||||
->getMockBuilder( 'WC_Log_Handler' )
|
||||
->setMethods( array( 'handle' ) )
|
||||
->getMock();
|
||||
$handler
|
||||
->expects( $this->at( 0 ) )
|
||||
->method( 'handle' )
|
||||
->with(
|
||||
$this->greaterThanOrEqual( $time ),
|
||||
$this->equalTo( 'bad-level' ),
|
||||
$this->equalTo( 'bad-level message' ),
|
||||
$this->equalTo( array() )
|
||||
);
|
||||
$handler
|
||||
->expects( $this->at( 1 ) )
|
||||
->method( 'handle' )
|
||||
->with(
|
||||
$this->greaterThanOrEqual( $time ),
|
||||
$this->equalTo( 'debug' ),
|
||||
$this->equalTo( 'debug message' ),
|
||||
$this->equalTo( array() )
|
||||
);
|
||||
|
||||
$log = new WC_Logger( array( $handler ) );
|
||||
|
||||
// An invalid level has the minimum severity, but should not be filtered.
|
||||
$log->log( 'bad-level', 'bad-level message' );
|
||||
// Bad level also complains.
|
||||
$this->setExpectedIncorrectUsage( 'WC_Logger::log' );
|
||||
|
||||
// Debug is lowest recognized level
|
||||
$log->debug( 'debug message' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper for 'woocommerce_register_log_handlers' filter test.
|
||||
*
|
||||
* Returns an array of 1 mocked handler.
|
||||
* The handler expects to receive exactly 8 messages (1 for each level).
|
||||
*
|
||||
* @since 2.7.0
|
||||
*
|
||||
* @return WC_Log_Handler[] array of mocked handlers.
|
||||
*/
|
||||
public function return_assertion_handlers() {
|
||||
$handler = $this
|
||||
->getMockBuilder( 'WC_Log_Handler' )
|
||||
->setMethods( array( 'handle' ) )
|
||||
->getMock();
|
||||
$handler->expects( $this->exactly( 8 ) )->method( 'handle' );
|
||||
|
||||
return array( $handler );
|
||||
}
|
||||
|
||||
/**
|
||||
* Mock handler that expects sequential calls to each level.
|
||||
*
|
||||
* Calls should have the message '[level] message'
|
||||
*
|
||||
* @since 2.7.0
|
||||
*
|
||||
* @return WC_Log_Handler mock object
|
||||
*/
|
||||
public function create_mock_handler() {
|
||||
$time = time();
|
||||
$handler = $this
|
||||
->getMockBuilder( 'WC_Log_Handler' )
|
||||
->setMethods( array( 'handle' ) )
|
||||
->getMock();
|
||||
|
||||
$handler
|
||||
->expects( $this->at( 0 ) )
|
||||
->method( 'handle' )
|
||||
->with(
|
||||
$this->greaterThanOrEqual( $time ),
|
||||
$this->equalTo( 'debug' ),
|
||||
$this->equalTo( 'debug message' ),
|
||||
$this->equalTo( array() )
|
||||
);
|
||||
$handler
|
||||
->expects( $this->at( 1 ) )
|
||||
->method( 'handle' )
|
||||
->with(
|
||||
$this->greaterThanOrEqual( $time ),
|
||||
$this->equalTo( 'info' ),
|
||||
$this->equalTo( 'info message' ),
|
||||
$this->equalTo( array() )
|
||||
);
|
||||
$handler
|
||||
->expects( $this->at( 2 ) )
|
||||
->method( 'handle' )
|
||||
->with(
|
||||
$this->greaterThanOrEqual( $time ),
|
||||
$this->equalTo( 'notice' ),
|
||||
$this->equalTo( 'notice message' ),
|
||||
$this->equalTo( array() )
|
||||
);
|
||||
$handler
|
||||
->expects( $this->at( 3 ) )
|
||||
->method( 'handle' )
|
||||
->with(
|
||||
$this->greaterThanOrEqual( $time ),
|
||||
$this->equalTo( 'warning' ),
|
||||
$this->equalTo( 'warning message' ),
|
||||
$this->equalTo( array() )
|
||||
);
|
||||
$handler
|
||||
->expects( $this->at( 4 ) )
|
||||
->method( 'handle' )
|
||||
->with(
|
||||
$this->greaterThanOrEqual( $time ),
|
||||
$this->equalTo( 'error' ),
|
||||
$this->equalTo( 'error message' ),
|
||||
$this->equalTo( array() )
|
||||
);
|
||||
$handler
|
||||
->expects( $this->at( 5 ) )
|
||||
->method( 'handle' )
|
||||
->with(
|
||||
$this->greaterThanOrEqual( $time ),
|
||||
$this->equalTo( 'critical' ),
|
||||
$this->equalTo( 'critical message' ),
|
||||
$this->equalTo( array() )
|
||||
);
|
||||
$handler
|
||||
->expects( $this->at( 6 ) )
|
||||
->method( 'handle' )
|
||||
->with(
|
||||
$this->greaterThanOrEqual( $time ),
|
||||
$this->equalTo( 'alert' ),
|
||||
$this->equalTo( 'alert message' ),
|
||||
$this->equalTo( array() )
|
||||
);
|
||||
$handler
|
||||
->expects( $this->at( 7 ) )
|
||||
->method( 'handle' )
|
||||
->with(
|
||||
$this->greaterThanOrEqual( $time ),
|
||||
$this->equalTo( 'emergency' ),
|
||||
$this->equalTo( 'emergency message' ),
|
||||
$this->equalTo( array() )
|
||||
);
|
||||
|
||||
return $handler;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,8 @@
|
|||
%d-%d-%dT%d:%d:%d+%d:%d DEBUG debug
|
||||
%d-%d-%dT%d:%d:%d+%d:%d INFO info
|
||||
%d-%d-%dT%d:%d:%d+%d:%d NOTICE notice
|
||||
%d-%d-%dT%d:%d:%d+%d:%d WARNING warning
|
||||
%d-%d-%dT%d:%d:%d+%d:%d ERROR error
|
||||
%d-%d-%dT%d:%d:%d+%d:%d CRITICAL critical
|
||||
%d-%d-%dT%d:%d:%d+%d:%d ALERT alert
|
||||
%d-%d-%dT%d:%d:%d+%d:%d EMERGENCY emergency
|
|
@ -238,6 +238,20 @@ class WC_Tests_Core_Functions extends WC_Unit_Test_Case {
|
|||
$this->assertEquals( $log_dir . 'unit-tests-' . $hash_name . '.log', wc_get_log_file_path( 'unit-tests' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test wc_get_logger().
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_wc_get_logger() {
|
||||
$log_a = wc_get_logger();
|
||||
$log_b = wc_get_logger();
|
||||
|
||||
$this->assertInstanceOf( 'WC_Logger', $log_a );
|
||||
$this->assertInstanceOf( 'WC_Logger', $log_b );
|
||||
$this->assertSame( $log_a, $log_b, '`wc_get_logger()` should return the same instance' );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test wc_get_core_supported_themes().
|
||||
*
|
||||
|
@ -286,4 +300,84 @@ class WC_Tests_Core_Functions extends WC_Unit_Test_Case {
|
|||
// With legacy methods.
|
||||
$this->assertEquals( 0, wc_get_shipping_method_count( true ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test wc_print_r()
|
||||
*
|
||||
* @since 2.7.0
|
||||
*/
|
||||
public function test_wc_print_r() {
|
||||
$arr = array( 1, 2, 'a', 'b', 'c' => 'd' );
|
||||
|
||||
// This filter will sequentially remove handlers, allowing us to test as though our
|
||||
// functions were accumulatively blacklisted, adding one on each call.
|
||||
add_filter( 'woocommerce_print_r_alternatives', array( $this, 'filter_wc_print_r_alternatives' ) );
|
||||
|
||||
$this->expectOutputString(
|
||||
print_r( $arr, true ),
|
||||
$return_value = wc_print_r( $arr )
|
||||
);
|
||||
$this->assertTrue( $return_value );
|
||||
ob_clean();
|
||||
|
||||
$this->expectOutputString(
|
||||
var_export( $arr, true ),
|
||||
$return_value = wc_print_r( $arr )
|
||||
);
|
||||
$this->assertTrue( $return_value );
|
||||
ob_clean();
|
||||
|
||||
$this->expectOutputString(
|
||||
json_encode( $arr ),
|
||||
$return_value = wc_print_r( $arr )
|
||||
);
|
||||
$this->assertTrue( $return_value );
|
||||
ob_clean();
|
||||
|
||||
$this->expectOutputString(
|
||||
serialize( $arr ),
|
||||
$return_value = wc_print_r( $arr )
|
||||
);
|
||||
$this->assertTrue( $return_value );
|
||||
ob_clean();
|
||||
|
||||
$this->expectOutputString(
|
||||
'',
|
||||
$return_value = wc_print_r( $arr )
|
||||
);
|
||||
$this->assertFalse( $return_value );
|
||||
ob_clean();
|
||||
|
||||
// Reset filter to include all handlers
|
||||
$this->filter_wc_print_r_alternatives( array(), true );
|
||||
|
||||
$this->assertEquals( print_r( $arr, true ), wc_print_r( $arr, true ) );
|
||||
$this->assertEquals( var_export( $arr, true ), wc_print_r( $arr, true ) );
|
||||
$this->assertEquals( json_encode( $arr ), wc_print_r( $arr, true ) );
|
||||
$this->assertEquals( serialize( $arr ), wc_print_r( $arr, true ) );
|
||||
$this->assertFalse( wc_print_r( $arr, true ) );
|
||||
|
||||
remove_filter( 'woocommerce_print_r_alternatives', array( $this, 'filter_wc_print_r_alternatives' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter function to help test wc_print_r alternatives via filter.
|
||||
*
|
||||
* On the first run, all alternatives are returned.
|
||||
* On each successive run, an alternative is excluded from the beginning.
|
||||
* Eventually, no handlers are returned.
|
||||
*
|
||||
* @param array $alternatives Input array of alternatives.
|
||||
* @param bool $reset Optional. Default false. True to reset excluded alternatives.
|
||||
* @return array|bool Alternatives. True on reset.
|
||||
*/
|
||||
public function filter_wc_print_r_alternatives( $alternatives, $reset = false ) {
|
||||
static $skip = 0;
|
||||
if ( $reset ) {
|
||||
$skip = 0;
|
||||
return true;
|
||||
}
|
||||
return array_slice( $alternatives, $skip++ );
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,40 +0,0 @@
|
|||
<?php
|
||||
|
||||
/**
|
||||
* Class Log.
|
||||
* @package WooCommerce\Tests\Util
|
||||
* @since 2.3
|
||||
*/
|
||||
class WC_Tests_Log extends WC_Unit_Test_Case {
|
||||
public function read_content( $handle ) {
|
||||
return file_get_contents( wc_get_log_file_path( $handle ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test add().
|
||||
*
|
||||
* @since 2.4
|
||||
*/
|
||||
public function test_add() {
|
||||
$log = wc_get_logger();
|
||||
|
||||
$log->add( 'unit-tests', 'this is a message' );
|
||||
|
||||
$this->assertStringMatchesFormat( '%d-%d-%d @ %d:%d:%d - %s', $this->read_content( 'unit-tests' ) );
|
||||
$this->assertStringEndsWith( ' - this is a message' . PHP_EOL, $this->read_content( 'unit-tests' ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Test clear().
|
||||
*
|
||||
* @since 2.4
|
||||
*/
|
||||
public function test_clear() {
|
||||
$log = wc_get_logger();
|
||||
|
||||
$log->add( 'unit-tests', 'this is a message' );
|
||||
$log->clear( 'unit-tests' );
|
||||
|
||||
$this->assertEquals( '', $this->read_content( 'unit-tests' ) );
|
||||
}
|
||||
}
|
|
@ -286,6 +286,7 @@ final class WooCommerce {
|
|||
include_once( WC_ABSPATH . 'includes/abstracts/abstract-wc-shipping-method.php' ); // A Shipping method
|
||||
include_once( WC_ABSPATH . 'includes/abstracts/abstract-wc-payment-gateway.php' ); // A Payment gateway
|
||||
include_once( WC_ABSPATH . 'includes/abstracts/abstract-wc-integration.php' ); // An integration with a service
|
||||
include_once( WC_ABSPATH . 'includes/abstracts/abstract-wc-log-handler.php' );
|
||||
include_once( WC_ABSPATH . 'includes/class-wc-product-factory.php' ); // Product factory
|
||||
include_once( WC_ABSPATH . 'includes/class-wc-payment-tokens.php' ); // Payment tokens controller
|
||||
include_once( WC_ABSPATH . 'includes/class-wc-shipping-zone.php' );
|
||||
|
|
Loading…
Reference in New Issue