'S', 'warning' => 'W', 'progress' => 'P', 'error' => 'E', 'generic' => '-', 'info' => 'I', ); /** * Log file path. * * @var string */ private $log_file_path; /** * Log file path url. * * @var string */ private $log_file_path_url; /** * Log file name. * * @var string */ private $log_file_name = 'ti-theme-onboarding.log'; /** * Log transient name. * * @var string */ public static $log_transient_name = 'ti_theme_onboarding'; /** * The expiration time for the transient. * * @var float|int */ private $log_transient_expiration = 2 * WEEK_IN_SECONDS; /** * @var string */ private $log_string = ''; /** * @var Logger */ private static $_instance; /** * Logger constructor. */ public function __construct() { if ( ! defined( 'TI_OB_DEBUG_LOG' ) ) { define( 'TI_OB_DEBUG_LOG', true ); } if ( TI_OB_DEBUG_LOG !== true ) { return; } require_once( ABSPATH . 'wp-admin/includes/file.php' ); // you have to load this file add_action( 'shutdown', array( $this, 'log_to_transient' ) ); $this->set_log_path(); $this->migrate_from_file_to_transient(); $this->log_client_info(); } /** * Log info. * * @param string $label log label. * @param string|int|null $value log value. */ public function log_info( $label, $value = null ) { if ( $value === null ) { $this->log( "{$label}", 'info' ); return; } $this->log( "{$label} : {$value}", 'info' ); } /** * Log client info for debug purposes. */ private function log_client_info() { $this->log_info( "WordPress Instance Info:\n" ); $this->log_info( 'Home URL', home_url() ); $this->log_info( 'Site URL', site_url() ); $this->log_info( 'WordPress Version', get_bloginfo( 'version' ) ); $this->log_info( 'Onboarding Version', Main::VERSION ); $this->log_info( 'Multisite', is_multisite() ? 'Yes' : 'No' ); $this->log_info( 'Server Info', isset( $_SERVER['SERVER_SOFTWARE'] ) ? wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) : '' ); $this->log_info( 'PHP Version', phpversion() ); $this->log_info( 'HTTPS', is_ssl() ? 'Yes' : 'No' ); $this->log_info( 'PHP Max Execution Time', ini_get( 'max_execution_time' ) ); $this->log_info( 'PHP Max Input Vars', ini_get( 'max_input_vars' ) ); $this->log_info( 'Max Upload Size', wp_max_upload_size() ); $this->log_info( 'Plugins:' ); foreach ( $this->get_plugins() as $plugin ) { $author = strip_tags( $plugin['Author'] ); $this->log_info( '[PLUGIN] ' . $plugin['Name'], 'v' . $plugin['Version'] . " ({$author}) " ); } } /** * Get active plugins. * * @return array */ private function get_plugins() { require_once ABSPATH . 'wp-admin/includes/plugin.php'; $active_plugins = (array) get_option( 'active_plugins', array() ); if ( is_multisite() ) { $network_activated_plugins = array_keys( get_site_option( 'active_sitewide_plugins', array() ) ); $active_plugins = array_merge( $active_plugins, $network_activated_plugins ); } $active_plugins_data = array(); foreach ( $active_plugins as $plugin ) { $data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ); $active_plugins_data[] = $data; } return $active_plugins_data; } /** * Returns the instance of the class. * * @return Logger */ public static function get_instance() { if ( null === self::$_instance ) { self::$_instance = new self(); } return self::$_instance; } /** * Set the log path. */ private function set_log_path() { $wp_upload_dir = wp_upload_dir( null, false ); $this->log_file_path = $wp_upload_dir['basedir'] . DIRECTORY_SEPARATOR; $this->log_file_path_url = $wp_upload_dir['baseurl'] . DIRECTORY_SEPARATOR; } /** * Log entry. * * @param string $message log message. * @param string $type log type. */ public function log( $message = 'No message provided.', $type = 'error' ) { $log_entry = array( 'message' => $message, 'type' => array_key_exists( $type, $this->icon_map ) ? $this->icon_map[ $type ] : $this->icon_map['generic'], 'time' => gmdate( '[d/M/Y:H:i:s]' ), ); $this->log_string .= $this->get_log_entry( $log_entry ); } /** * Log to file. */ public function log_to_transient() { $transient_data = get_transient( self::$log_transient_name ); if ( ! $transient_data ) { $transient_data = ''; } $transient_data .= $this->log_string; set_transient( self::$log_transient_name, $transient_data, $this->log_transient_expiration ); } /** * Get the formatted log entry. * * @return string */ private function get_log_entry( $log_entry ) { if ( ! is_string( $log_entry['message'] ) ) { $log_entry['message'] = json_encode( $log_entry['message'] ); } return trim( preg_replace( '/\s\s+/', ' ', "{$log_entry['time']} ({$log_entry['type']}): {$log_entry['message']}" ) ) . PHP_EOL; } /** * Get the log URL. */ public function get_log_url() { return $this->log_file_path_url . self::$log_transient_name; } /** * Migrate from file to transient. */ public function migrate_from_file_to_transient() { $log_file = $this->log_file_path . $this->log_file_name; global $wp_filesystem; WP_Filesystem(); $has_file = file_exists( $log_file ); if ( ! $has_file ) { return; } $content = $wp_filesystem->get_contents( $log_file ); $this->log_string .= $content; $this->log_to_transient(); if ( is_writable( $log_file ) ) { unlink( $log_file ); } } }