Current Path : /home/ncdcgo/public_html/wp-content/plugins backup/document-gallery/inc/ |
Current File : /home/ncdcgo/public_html/wp-content/plugins backup/document-gallery/inc/class-logger.php |
<?php defined( 'WPINC' ) OR exit; /** * Encapsulates the logic required to maintain and read log files. */ class DG_Logger { /** * @var string Name of the log purge action. */ const PurgeLogsAction = 'document-gallery_purge-logs'; /** * Appends DG log file if logging is enabled. * * @param int $level The level of serverity (should be passed using DG_LogLevel consts). * @param string $entry Value to be logged. * @param bool $stacktrace Whether to include full stack trace. * @param bool $force Whether to ignore logging flag and log no matter what. * Only should be used when the user *must* know about something. */ public static function writeLog( $level, $entry, $stacktrace = false, $force = false ) { if ( $force || self::logEnabled() ) { $fp = fopen( self::getLogFileName(), 'a' ); if ( false !== $fp ) { $fields = array( time(), $level, $entry ); $trace = debug_backtrace( false ); if ( $stacktrace ) { unset( $trace[0] ); $fields[] = self::getStackTraceString( $trace ); } else { // Ignore first item from backtrace as it's this function which is redundant. $caller = $trace[1]; $class = isset( $caller['class'] ) ? $caller['class'] : ''; $type = isset( $caller['type'] ) ? $caller['type'] : ''; $caller = $class . $type . $caller['function']; $fields[2] = '(' . $caller . ') ' . $fields[2]; } fputcsv( $fp, $fields ); fclose( $fp ); } // TODO: else } } /** * Reads the current blog's log file, placing the values in to a 2-dimensional array. * * @param int $skip How many lines to skip before returning rows. * @param int $limit Max number of lines to read. * * @return string[][]|null The rows from the log file or null if failed to open log. */ public static function readLog( $skip = 0, $limit = PHP_INT_MAX ) { $ret = null; $fp = @fopen( self::getLogFileName(), 'r' ); if ( $fp !== false ) { $ret = array(); while ( count( $ret ) < $limit && false !== ( $fields = fgetcsv( $fp ) ) ) { if ( $skip > 0 ) { $skip --; continue; } if ( ! is_null( $fields ) ) { $ret[] = $fields; } } @fclose( $fp ); } return $ret; } /** * Clears the log file for the active blog. */ public static function clearLog() { // we don't care if the file actually exists -- it won't when we're done @unlink( self::getLogFileName() ); } /** * Clears the log file for all blogs. */ public static function clearLogs() { // we don't care if the files actually exist -- they won't when we're done foreach ( DG_Util::getBlogIds() as $id ) { @unlink( self::getLogFileName( $id ) ); } } /** * Truncates all blog logs to the current purge interval. * * TODO: This is a memory hog. Consider switching to stream filter. */ public static function purgeExpiredEntries() { self::writeLog( DG_LogLevel::Detail, 'Beginning scheduled log file purge.' ); $blogs = array( null ); if ( is_multisite() ) { $blogs = DG_Util::getBlogIds(); } // truncate each blog's log file $time = time(); foreach ( $blogs as $blog ) { $blog_num = ! is_null( $blog ) ? $blog : get_current_blog_id(); $options = self::getOptions( $blog ); $purge_time = $time - $options['purge_interval'] * DAY_IN_SECONDS; // purging is disabled for this blog if ( $purge_time >= $time ) { continue; } // do purge for this blog $file = self::getLogFileName( $blog_num ); if ( file_exists( $file ) ) { $fp = @fopen( $file, 'r' ); if ( $fp !== false ) { $truncate = false; $offset = 0; // find the first non-expired entry while ( ( $fields = fgetcsv( $fp ) ) !== false ) { if ( ! is_null( $fields ) && intval( $fields[0] ) >= $purge_time ) { // we've reached the recent entries -- nothing beyond here will be removed break; } $offset = @ftell( $fp ); if ( false === $offset ) { break; } $truncate = true; } @fclose( $fp ); // if any expired entries exist -- remove them from the file if ( $truncate ) { self::writeLog( DG_LogLevel::Detail, "Purging log entries for blog #$blog_num." ); $data = file_get_contents( $file, false, null, $offset ); file_put_contents( $file, $data, LOCK_EX ); } } } } } /** * Generally not necessary to call external to this class -- only use if generating * log entry will take significant resources and you want to avoid this operation * if it will not actually be logged. * * @return bool Whether debug logging is currently enabled. */ public static function logEnabled() { $options = self::getOptions(); return $options['enabled']; } /** * Gets logging options. * * @param int $blog ID of the blog to be retrieved in multisite env. * * @return mixed[] Logger options for the blog. */ public static function getOptions( $blog = null ) { $options = DocumentGallery::getOptions( $blog ); return $options['logging']; } /** * @param $id int The ID of the blog to retrieve log file name for. Defaults to current blog. * * @return string Full path to log file for current blog. */ private static function getLogFileName( $id = null ) { $id = ! is_null( $id ) ? $id : get_current_blog_id(); return DG_PATH . 'log/' . $id . '.log'; } /** * @param mixed[][] $trace Array containing stack trace to be converted to string. * * @return string The stack trace in human-readable form. */ private static function getStackTraceString( $trace ) { $trace_str = ''; $i = 1; foreach ( $trace as $node ) { $trace_str .= "#$i "; $file = ''; if ( isset( $node['file'] ) ) { // convert to relative path from WP root $file = str_replace( ABSPATH, '', $node['file'] ); } if ( isset( $node['line'] ) ) { $file .= "({$node['line']})"; } if ( $file ) { $trace_str .= "$file: "; } if ( isset( $node['class'] ) ) { $trace_str .= "{$node['class']}{$node['type']}"; } if ( isset( $node['function'] ) ) { // only include args for first item in stack trace $args = ''; if ( 1 === $i && isset( $node['args'] ) ) { $args = implode( ', ', array_map( array( __CLASS__, 'print_r' ), $node['args'] ) ); } $trace_str .= "{$node['function']}($args)" . PHP_EOL; } $i ++; } return $trace_str; } /** * Wraps print_r passing true for the return argument. * * @param mixed $v Value to be printed. * * @return string Printed value. */ private static function print_r( $v ) { return preg_replace( '/\s+/', ' ', print_r( $v, true ) ); } /** * Blocks instantiation. All functions are static. */ private function __construct() { } } /** * LogLevel acts as an enumeration of all possible log levels. */ class DG_LogLevel { /** * @var int Log level for anything that doesn't indicate a problem. */ const Detail = 0; /** * @var int Log level for anything that is a minor issue. */ const Warning = 1; /** * @var int Log level for when something went wrong. */ const Error = 2; /** * @var ReflectionClass Backs the getter. */ private static $ref = null; /** * @return ReflectionClass Instance of reflection class for this class. */ private static function getReflectionClass() { if ( is_null( self::$ref ) ) { self::$ref = new ReflectionClass( __CLASS__ ); } return self::$ref; } /** * @var int[] Backs the getter. */ private static $levels = null; /** * @return int[] Associative array containing all log level names mapped to their int value. */ public static function getLogLevels() { if ( is_null( self::$levels ) ) { $ref = self::getReflectionClass(); self::$levels = $ref->getConstants(); } return self::$levels; } /** * @param string $name Name to be checked for validity. * * @return bool Whether given name represents valid log level. */ public static function isValidName( $name ) { return array_key_exists( $name, self::getLogLevels() ); } /** * @param int $value Value to be checked for validity. * * @return bool Whether given value represents valid log level. */ public static function isValidValue( $value ) { return ( false !== array_search( $value, self::getLogLevels() ) ); } /** * @param string $name The name for which to retrieve a value. * * @return int|null The value associated with the given name. */ public static function getValueByName( $name ) { $levels = self::getLogLevels(); return array_key_exists( $name, self::getLogLevels() ) ? $levels[ $name ] : null; } /** * @param int $value The value for which to retrieve a name. * * @return string|null The name associated with the given value. */ public static function getNameByValue( $value ) { $ret = array_search( $value, self::getLogLevels() ); return ( false !== $ret ) ? $ret : null; } /** * Blocks instantiation. All functions are static. */ private function __construct() { } }