'E_ERROR', 4 => 'E_PARSE', 16 => 'E_CORE_ERROR', 64 => 'E_COMPILE_ERROR' ); public static function boot() { // DATPCO_EC có thể đã được định nghĩa bởi một bộ bắt lỗi nạp sớm hơn, khi đó không đăng ký trùng if ( defined( 'DATPCO_EC' ) ) { return; } define( 'DATPCO_EC', 'plugin' ); $dir = self::dir_if_exists(); $root = wp_normalize_path( ABSPATH ); if ( $dir ) { register_shutdown_function( function () use ( $dir, $root ) { datpco_ec_record( $dir, $root ); } ); } } /** Thư mục sao lưu nếu đã có (không tạo mới chỉ vì một request thường). */ public static function dir_if_exists() { $name = get_option( 'datpco_backup_dir' ); if ( ! $name ) { return ''; } $up = wp_upload_dir( null, false ); $dir = trailingslashit( $up['basedir'] ) . $name; return is_dir( $dir ) ? $dir : ''; } /** 'mu' = bắt cả lỗi lúc nạp plugin; 'plugin' = chỉ bắt sau khi Connector nạp; '' = chưa bắt được. */ public static function mode() { return defined( 'DATPCO_EC' ) ? DATPCO_EC : ''; } /** * Lỗi từ thời điểm $since, gộp theo mã lỗi. Kèm plugin/theme nghi ngờ (theo đường dẫn) và phiên bản của nó. * @return array{mode:string,errors:array} */ public static function read( $since = 0, $limit = 50 ) { $dir = self::dir_if_exists(); $out = array(); if ( $dir ) { foreach ( array( $dir . '/' . self::LOG . '.1', $dir . '/' . self::LOG ) as $f ) { if ( ! file_exists( $f ) ) { continue; } foreach ( (array) file( $f, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES ) as $line ) { $e = json_decode( $line, true ); if ( ! is_array( $e ) || empty( $e['h'] ) || (int) $e['t'] <= $since ) { continue; } $h = $e['h']; if ( ! isset( $out[ $h ] ) ) { $out[ $h ] = $e + array( 'first' => (int) $e['t'], 'n' => 0 ) + self::suspect( $e['file'] ); } $out[ $h ]['n']++; $out[ $h ]['last'] = (int) $e['t']; $out[ $h ]['uri'] = $e['uri']; } } // dọn dấu chống lặp cũ foreach ( (array) glob( $dir . '/err-*.m' ) as $m ) { if ( time() - filemtime( $m ) > DAY_IN_SECONDS ) { wp_delete_file( $m ); } } } uasort( $out, function ( $a, $b ) { return $b['last'] - $a['last']; } ); return array( 'mode' => self::mode(), 'errors' => array_values( array_slice( $out, 0, $limit ) ) ); } /** Plugin/theme chứa file lỗi. */ private static function suspect( $file ) { if ( preg_match( '#^wp-content/(plugins|themes|mu-plugins)/([^/]+)#', (string) $file, $m ) ) { $ver = ''; if ( 'plugins' === $m[1] ) { require_once ABSPATH . 'wp-admin/includes/plugin.php'; foreach ( get_plugins( '/' . $m[2] ) as $p ) { $ver = (string) $p['Version']; break; } } elseif ( 'themes' === $m[1] ) { $t = wp_get_theme( $m[2] ); $ver = $t->exists() ? (string) $t->get( 'Version' ) : ''; } return array( 'kind' => rtrim( $m[1], 's' ), 'slug' => $m[2], 'version' => $ver ); } return array( 'kind' => 0 === strpos( (string) $file, 'wp-' ) ? 'core' : 'other', 'slug' => '', 'version' => '' ); } public static function clear() { $dir = self::dir_if_exists(); foreach ( $dir ? array( $dir . '/' . self::LOG, $dir . '/' . self::LOG . '.1' ) : array() as $f ) { if ( file_exists( $f ) ) { wp_delete_file( $f ); } } return true; } } if ( ! function_exists( 'datpco_ec_record' ) ) { require_once __DIR__ . '/error-record.php'; }