From 2a3283c0ad563a2de979b99480c03cdf0986dad4 Mon Sep 17 00:00:00 2001
From: tijmen
Date: Fri, 2 Jan 2026 11:19:28 +0100
Subject: [PATCH 01/23] chore: add settings view
- use include pattern instead of rendering in class
---
src/views/settings-diagnostics.php | 30 ++++++++++++++++++++++++++++++
src/views/settings.php | 3 +++
2 files changed, 33 insertions(+)
create mode 100644 src/views/settings-diagnostics.php
diff --git a/src/views/settings-diagnostics.php b/src/views/settings-diagnostics.php
new file mode 100644
index 0000000..464d638
--- /dev/null
+++ b/src/views/settings-diagnostics.php
@@ -0,0 +1,30 @@
+
+
\ No newline at end of file
diff --git a/src/views/settings.php b/src/views/settings.php
index 07946ac..0deb0e4 100644
--- a/src/views/settings.php
+++ b/src/views/settings.php
@@ -59,6 +59,9 @@
+
+
+
From 1625d03bd4ef7ffb69e4ac06d9a8eca553e02db2 Mon Sep 17 00:00:00 2001
From: tijmen
Date: Fri, 2 Jan 2026 11:20:53 +0100
Subject: [PATCH 02/23] chore: add logger singleton
---
src/class-tiny-logger.php | 270 ++++++++++++++++++++++++++++++++++++++
tiny-compress-images.php | 1 +
2 files changed, 271 insertions(+)
create mode 100644 src/class-tiny-logger.php
diff --git a/src/class-tiny-logger.php b/src/class-tiny-logger.php
new file mode 100644
index 0000000..d128a7a
--- /dev/null
+++ b/src/class-tiny-logger.php
@@ -0,0 +1,270 @@
+log_enabled = 'on' === get_option('tinypng_logging_enabled', false);
+ if ($this->log_enabled) {
+ $this->log_file_path = $this->get_log_file_path();
+ }
+
+ add_action('pre_update_option_tinypng_logging_enabled', array($this, 'on_save_log_enabled'), 10, 3);
+ }
+
+ /**
+ * Triggered when log_enabled is saved
+ * - set the setting on the instance
+ * - if turn off, clear the logs
+ * - if turned on, check if we can create the log file
+ *
+ * @since 3.7.0
+ */
+ public function on_save_log_enabled($new, $old, $option)
+ {
+ $this->log_enabled = 'on' === $new;
+ if ($this->log_enabled) {
+ $this->log_file_path = $this->get_log_file_path();
+ }
+ }
+
+ /**
+ * Gets the log file path.
+ *
+ * @since 3.7.0
+ *
+ * @return string The log file path.
+ */
+ private function get_log_file_path()
+ {
+ $upload_dir = wp_upload_dir();
+ $log_dir = trailingslashit($upload_dir['basedir']) . 'tiny-compress-logs';
+
+ if (! file_exists($log_dir)) {
+ wp_mkdir_p($log_dir);
+ // Add .htaccess to protect log files.
+ file_put_contents(trailingslashit($log_dir) . '.htaccess', 'Deny from all');
+ }
+
+ return trailingslashit($log_dir) . 'tiny-compress.log';
+ }
+
+ /**
+ * Gets the log directory path.
+ *
+ * @since 3.7.0
+ *
+ * @return string The log directory path.
+ */
+ public function get_log_dir()
+ {
+ return dirname($this->log_file_path);
+ }
+
+ /**
+ * Checks if logging is enabled.
+ *
+ * @since 3.7.0
+ *
+ * @return bool True if logging is enabled.
+ */
+ public function is_enabled()
+ {
+ return $this->log_enabled;
+ }
+
+ /**
+ * Logs an error message.
+ *
+ * @since 3.7.0
+ *
+ * @param string $message The message to log.
+ * @param array $context Optional. Additional context data. Default empty array.
+ */
+ public static function error($message, $context = array())
+ {
+ $instance = self::get_instance();
+ $instance->log(self::LOG_LEVEL_ERROR, $message, $context);
+ }
+
+ /**
+ * Logs a debug message.
+ *
+ * @since 3.7.0
+ *
+ * @param string $message The message to log.
+ * @param array $context Optional. Additional context data. Default empty array.
+ */
+ public static function debug($message, $context = array())
+ {
+ $instance = self::get_instance();
+ $instance->log(self::LOG_LEVEL_DEBUG, $message, $context);
+ }
+
+ /**
+ * Logs a message.
+ *
+ * @since 3.7.0
+ *
+ * @param string $level The log level.
+ * @param string $message The message to log.
+ * @param array $context Optional. Additional context data. Default empty array.
+ */
+ private function log($level, $message, $context = array())
+ {
+ if (! $this->log_enabled) {
+ return;
+ }
+
+ $this->rotate_logs();
+
+ $timestamp = current_time('Y-m-d H:i:s');
+ $level_str = strtoupper($level);
+ $context_str = ! empty($context) ? ' ' . wp_json_encode($context) : '';
+ $log_entry = "[{$timestamp}] [{$level_str}] {$message}{$context_str}\n";
+
+ $file = fopen($this->log_file_path, 'a');
+ if ($file) {
+ fwrite($file, $log_entry);
+ fclose($file);
+ }
+ }
+
+ /**
+ * Rotates log files when they exceed the max size.
+ *
+ * @since 3.7.0
+ */
+ private function rotate_logs()
+ {
+ if (! file_exists($this->log_file_path)) {
+ return;
+ }
+
+ $file_size = filesize($this->log_file_path);
+ if ($file_size < self::MAX_LOG_SIZE) {
+ return;
+ }
+
+ for ($i = self::MAX_LOG_FILES - 1; $i > 0; $i--) {
+ $old_file = $this->log_file_path . '.' . $i;
+ $new_file = $this->log_file_path . '.' . ($i + 1);
+
+ if (file_exists($old_file)) {
+ if ($i === self::MAX_LOG_FILES - 1) {
+ unlink($old_file);
+ } else {
+ rename($old_file, $new_file);
+ }
+ }
+ }
+
+ rename($this->log_file_path, $this->log_file_path . '.1');
+ }
+
+ /**
+ * Clears all log files.
+ *
+ * @since 3.7.0
+ *
+ * @return bool True if logs were cleared successfully.
+ */
+ public function clear_logs()
+ {
+ $cleared = true;
+
+ // Remove main log file.
+ if (file_exists($this->log_file_path)) {
+ $cleared = unlink($this->log_file_path) && $cleared;
+ }
+
+ // Remove rotated log files.
+ for ($i = 1; $i <= self::MAX_LOG_FILES; $i++) {
+ $log_file = $this->log_file_path . '.' . $i;
+ if (file_exists($log_file)) {
+ $cleared = unlink($log_file) && $cleared;
+ }
+ }
+
+ return $cleared;
+ }
+
+ /**
+ * Gets all log file paths.
+ *
+ * @since 3.7.0
+ *
+ * @return array Array of log file paths.
+ */
+ public function get_log_files()
+ {
+ $files = array();
+
+ if (file_exists($this->log_file_path)) {
+ $files[] = $this->log_file_path;
+ }
+
+ for ($i = 1; $i <= self::MAX_LOG_FILES; $i++) {
+ $log_file = $this->log_file_path . '.' . $i;
+ if (file_exists($log_file)) {
+ $files[] = $log_file;
+ }
+ }
+
+ return $files;
+ }
+}
diff --git a/tiny-compress-images.php b/tiny-compress-images.php
index 2efa12f..d5b8738 100644
--- a/tiny-compress-images.php
+++ b/tiny-compress-images.php
@@ -14,6 +14,7 @@
require dirname( __FILE__ ) . '/src/class-tiny-php.php';
require dirname( __FILE__ ) . '/src/class-tiny-wp-base.php';
require dirname( __FILE__ ) . '/src/class-tiny-exception.php';
+require dirname( __FILE__ ) . '/src/class-tiny-logger.php';
require dirname( __FILE__ ) . '/src/class-tiny-compress.php';
require dirname( __FILE__ ) . '/src/class-tiny-bulk-optimization.php';
require dirname( __FILE__ ) . '/src/class-tiny-image-size.php';
From d3e3be1ef90d9d921bcad07042f03e0b1fe5e0a8 Mon Sep 17 00:00:00 2001
From: tijmen
Date: Fri, 2 Jan 2026 11:21:39 +0100
Subject: [PATCH 03/23] chore: add diagnostics class
- download zip file including logs and information about setup
---
src/class-tiny-diagnostics.php | 279 +++++++++++++++++++++++++++++++++
src/class-tiny-settings.php | 4 +
tiny-compress-images.php | 1 +
3 files changed, 284 insertions(+)
create mode 100644 src/class-tiny-diagnostics.php
diff --git a/src/class-tiny-diagnostics.php b/src/class-tiny-diagnostics.php
new file mode 100644
index 0000000..34c56d0
--- /dev/null
+++ b/src/class-tiny-diagnostics.php
@@ -0,0 +1,279 @@
+settings = $settings;
+
+ add_action(
+ 'wp_ajax_tiny_download_diagnostics',
+ array($this, 'download_diagnostics')
+ );
+ }
+
+ /**
+ * Collects all diagnostic information.
+ *
+ * File contains:
+ * - timestamp of export
+ * - server information
+ * - site information
+ * - plugin list
+ * - tinify settings
+ * - image settings
+ * - logs
+ *
+ * @since 3.7.0
+ *
+ * @return array Array of diagnostic information.
+ */
+ public function collect_info()
+ {
+ $info = array(
+ 'timestamp' => current_time('Y-m-d H:i:s'),
+ 'server_info' => self::get_server_info(),
+ 'site_info' => self::get_site_info(),
+ 'active_plugins' => self::get_active_plugins(),
+ 'tiny_info' => $this->get_tiny_info(),
+ 'image_sizes' => $this->settings->get_active_tinify_sizes(),
+ );
+
+ return $info;
+ }
+
+ /**
+ * Gets site information.
+ *
+ * @since 3.7.0
+ *
+ * @return array Site information.
+ */
+ private static function get_site_info()
+ {
+ global $wp_version;
+ $theme = wp_get_theme();
+
+ return array(
+ 'wp_version' => $wp_version,
+ 'site_url' => get_site_url(),
+ 'home_url' => get_home_url(),
+ 'is_multisite' => is_multisite(),
+ 'site_language' => get_locale(),
+ 'timezone' => wp_timezone_string(),
+ 'theme_name' => $theme->get('Name'),
+ 'theme_version' => $theme->get('Version'),
+ 'theme_uri' => $theme->get('ThemeURI'),
+ );
+ }
+
+ /**
+ * Gets server information.
+ *
+ * @since 3.7.0
+ *
+ * @return array Server information.
+ */
+ private static function get_server_info()
+ {
+ global $wpdb;
+
+ return array(
+ 'php_version' => phpversion(),
+ 'server_software' => isset($_SERVER['SERVER_SOFTWARE']) ? sanitize_text_field(wp_unslash($_SERVER['SERVER_SOFTWARE'])) : 'Unknown',
+ 'mysql_version' => $wpdb->db_version(),
+ 'max_execution_time' => ini_get('max_execution_time'),
+ 'memory_limit' => ini_get('memory_limit'),
+ 'post_max_size' => ini_get('post_max_size'),
+ 'upload_max_filesize' => ini_get('upload_max_filesize'),
+ 'max_input_vars' => ini_get('max_input_vars'),
+ 'curl_version' => function_exists('curl_version') ? curl_version()['version'] : 'Not available',
+ 'disabled_functions' => ini_get('disable_functions'),
+ );
+ }
+
+ /**
+ * Gets list of active plugins.
+ *
+ * @since 3.7.0
+ *
+ * @return array List of active plugins.
+ */
+ private static function get_active_plugins()
+ {
+ $active_plugins = get_option('active_plugins', array());
+ $plugins = array();
+
+ foreach ($active_plugins as $plugin) {
+ $plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin);
+ $plugins[] = array(
+ 'name' => $plugin_data['Name'],
+ 'version' => $plugin_data['Version'],
+ 'author' => $plugin_data['Author'],
+ 'file' => $plugin,
+ );
+ }
+
+ return $plugins;
+ }
+
+ /**
+ * Gets TinyPNG plugin info & settings.
+ *
+ * @since 3.7.0
+ *
+ * @return array Plugin settings
+ */
+ private function get_tiny_info()
+ {
+ return array(
+ 'version' => Tiny_Plugin::version(),
+ 'status' => $this->settings->get_status(),
+ 'php_client_supported' => Tiny_PHP::client_supported(),
+
+ 'compression_count' => $this->settings->get_compression_count(),
+ 'compression_timing' => $this->settings->get_compression_timing(),
+ 'conversion' => $this->settings->get_conversion_options(),
+ 'paying_state' => $this->settings->get_paying_state(),
+ );
+ }
+
+ public function download_diagnostics()
+ {
+ $zippath = $this->create_diagnostic_zip();
+ return $this->download_zip($zippath);
+ }
+
+ /**
+ * Creates a diagnostic zip file.
+ *
+ * @since 3.7.0
+ *
+ * @return string|WP_Error Path to the created zip file or WP_Error on failure.
+ */
+ public function create_diagnostic_zip()
+ {
+ if (! class_exists('ZipArchive')) {
+ return new WP_Error('zip_not_available', __('ZipArchive class is not available on this server.', 'tiny-compress-images'));
+ }
+
+ $upload_dir = wp_upload_dir();
+ $temp_dir = trailingslashit($upload_dir['basedir']) . 'tiny-compress-temp';
+
+ if (! file_exists($temp_dir)) {
+ wp_mkdir_p($temp_dir);
+ }
+
+ $zip_filename = 'tiny-compress-diagnostics-' . gmdate('Y-m-d-His') . '.zip';
+ $zip_path = trailingslashit($temp_dir) . $zip_filename;
+
+ $zip = new ZipArchive();
+ if (true !== $zip->open($zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE)) {
+ return new WP_Error('zip_create_failed', __('Failed to create zip file.', 'tiny-compress-images'));
+ }
+
+ // Add diagnostic info.
+ $info = self::collect_info();
+ $zip->addFromString('diagnostics.json', wp_json_encode($info, JSON_PRETTY_PRINT));
+
+ // Add log files.
+ $logger = Tiny_Logger::get_instance();
+ $log_files = $logger->get_log_files();
+
+ foreach ($log_files as $log_file) {
+ if (file_exists($log_file)) {
+ $zip->addFile($log_file, 'logs/' . basename($log_file));
+ }
+ }
+
+ $zip->close();
+ return $zip_path;
+ }
+
+ /**
+ * Downloads and removes the zip
+ *
+ * @since 3.7.0
+ *
+ * @param string $zip_path Path to the zip file.
+ */
+ public static function download_zip($zip_path)
+ {
+ if (! file_exists($zip_path)) {
+ wp_die(esc_html__('Diagnostic file not found.', 'tiny-compress-images'));
+ }
+
+ header('Content-Type: application/zip');
+ header('Content-Disposition: attachment; filename="' . basename($zip_path) . '"');
+ header('Content-Length: ' . filesize($zip_path));
+ header('Pragma: no-cache');
+ header('Expires: 0');
+
+ // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_readfile
+ readfile($zip_path);
+
+ // Clean up.
+ // phpcs:ignore WordPress.WP.AlternativeFunctions.unlink_unlink
+ unlink($zip_path);
+
+ exit;
+ }
+
+ /**
+ * Cleans up old diagnostic zip files.
+ *
+ * @since 3.7.0
+ */
+ public static function cleanup_old_diagnostics()
+ {
+ $upload_dir = wp_upload_dir();
+ $temp_dir = trailingslashit($upload_dir['basedir']) . 'tiny-compress-temp';
+
+ if (! file_exists($temp_dir)) {
+ return;
+ }
+
+ $files = glob(trailingslashit($temp_dir) . 'tiny-compress-diagnostics-*.zip');
+ $max_age = DAY_IN_SECONDS; // 1 day.
+
+ foreach ($files as $file) {
+ if (file_exists($file) && (time() - filemtime($file)) > $max_age) {
+ // phpcs:ignore WordPress.WP.AlternativeFunctions.unlink_unlink
+ unlink($file);
+ }
+ }
+ }
+}
diff --git a/src/class-tiny-settings.php b/src/class-tiny-settings.php
index 19c3308..a0678cb 100644
--- a/src/class-tiny-settings.php
+++ b/src/class-tiny-settings.php
@@ -30,6 +30,7 @@ class Tiny_Settings extends Tiny_WP_Base {
public function __construct() {
parent::__construct();
$this->notices = new Tiny_Notices();
+ new Tiny_Diagnostics($this);
}
private function init_compressor() {
@@ -127,6 +128,9 @@ public function admin_init() {
$field = self::get_prefixed_name( 'convert_format' );
register_setting( 'tinify', $field );
+
+ $field = self::get_prefixed_name( 'logging_enabled' );
+ register_setting( 'tinify', $field );
}
public function admin_menu() {
diff --git a/tiny-compress-images.php b/tiny-compress-images.php
index d5b8738..95f8514 100644
--- a/tiny-compress-images.php
+++ b/tiny-compress-images.php
@@ -15,6 +15,7 @@
require dirname( __FILE__ ) . '/src/class-tiny-wp-base.php';
require dirname( __FILE__ ) . '/src/class-tiny-exception.php';
require dirname( __FILE__ ) . '/src/class-tiny-logger.php';
+require dirname( __FILE__ ) . '/src/class-tiny-diagnostics.php';
require dirname( __FILE__ ) . '/src/class-tiny-compress.php';
require dirname( __FILE__ ) . '/src/class-tiny-bulk-optimization.php';
require dirname( __FILE__ ) . '/src/class-tiny-image-size.php';
From f38b3c7e0aa76a419e5bca68a4343dd873ceecc4 Mon Sep 17 00:00:00 2001
From: tijmen
Date: Fri, 2 Jan 2026 11:21:54 +0100
Subject: [PATCH 04/23] chore: download zip file from settings page
---
src/js/admin.js | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/js/admin.js b/src/js/admin.js
index b8a972f..ad4e5e9 100644
--- a/src/js/admin.js
+++ b/src/js/admin.js
@@ -1,4 +1,10 @@
(function() {
+ function downloadDiagnostics() {
+ const downloadURL = `${ajaxurl}?action=tiny_download_diagnostics&security=${tinyCompress.nonce}`;
+ window.location.href = downloadURL;
+ }
+ jQuery('#tiny-download-diagnostics').click(downloadDiagnostics);
+
function compressImage(event) {
var element = jQuery(event.target);
var container = element.closest('div.tiny-ajax-container');
From 25bbc4640d64075d05c9361e9a4f271f664b1523 Mon Sep 17 00:00:00 2001
From: tijmen
Date: Fri, 2 Jan 2026 11:31:45 +0100
Subject: [PATCH 05/23] chore: add loader and improve markup
- added utility classes
---
src/css/admin.css | 8 ++++++++
src/js/admin.js | 13 ++++++++++---
src/views/settings-diagnostics.php | 7 +++++--
3 files changed, 23 insertions(+), 5 deletions(-)
diff --git a/src/css/admin.css b/src/css/admin.css
index f87d6dc..977dadf 100644
--- a/src/css/admin.css
+++ b/src/css/admin.css
@@ -473,4 +473,12 @@ fieldset.tinypng_convert_fields label span {
fieldset.tinypng_convert_fields[disabled] {
opacity: 0.6;
+}
+
+.tiny-d-flex {
+ display: flex;
+}
+
+.tiny-mt-2 {
+ margin-top: 10px;
}
\ No newline at end of file
diff --git a/src/js/admin.js b/src/js/admin.js
index ad4e5e9..0ead0f4 100644
--- a/src/js/admin.js
+++ b/src/js/admin.js
@@ -1,10 +1,17 @@
(function() {
function downloadDiagnostics() {
- const downloadURL = `${ajaxurl}?action=tiny_download_diagnostics&security=${tinyCompress.nonce}`;
- window.location.href = downloadURL;
+ try {
+ jQuery('#download-diagnostics-spinner').show();
+ jQuery('#tiny-download-diagnostics').attr('disabled', true);
+ const downloadURL = `${ajaxurl}?action=tiny_download_diagnostics&security=${tinyCompress.nonce}`;
+ window.location.href = downloadURL;
+ } finally {
+ jQuery('#tiny-download-diagnostics').attr('disabled', false);
+ jQuery('#download-diagnostics-spinner').hide();
+ }
}
jQuery('#tiny-download-diagnostics').click(downloadDiagnostics);
-
+
function compressImage(event) {
var element = jQuery(event.target);
var container = element.closest('div.tiny-ajax-container');
diff --git a/src/views/settings-diagnostics.php b/src/views/settings-diagnostics.php
index 464d638..2638e7e 100644
--- a/src/views/settings-diagnostics.php
+++ b/src/views/settings-diagnostics.php
@@ -21,9 +21,12 @@
-
+
From 47cd48f43a9ef97f5477130d7c382d46d88f6dfe Mon Sep 17 00:00:00 2001
From: tijmen
Date: Fri, 2 Jan 2026 22:11:20 +0100
Subject: [PATCH 06/23] Add various log points
---
src/class-tiny-compress-client.php | 6 +++++-
src/class-tiny-compress-fopen.php | 6 ++++++
src/class-tiny-image.php | 27 +++++++++++++++++++++++++++
src/class-tiny-logger.php | 18 ++++++++++--------
src/class-tiny-plugin.php | 26 +++++++++++++++++++++++++-
5 files changed, 73 insertions(+), 10 deletions(-)
diff --git a/src/class-tiny-compress-client.php b/src/class-tiny-compress-client.php
index 5bbf8c9..f868a23 100644
--- a/src/class-tiny-compress-client.php
+++ b/src/class-tiny-compress-client.php
@@ -92,7 +92,6 @@ protected function compress( $input, $resize_opts, $preserve_opts, $convert_to )
try {
$this->last_error_code = 0;
$this->set_request_options( \Tinify\Tinify::getClient() );
-
$source = \Tinify\fromBuffer( $input );
if ( $resize_opts ) {
@@ -137,6 +136,11 @@ protected function compress( $input, $resize_opts, $preserve_opts, $convert_to )
return $result;
} catch ( \Tinify\Exception $err ) {
$this->last_error_code = $err->status;
+
+ Tiny_Logger::error('client compress error', array(
+ "error" => $err->getMessage(),
+ "status" => $err->status,
+ ));
throw new Tiny_Exception(
$err->getMessage(),
diff --git a/src/class-tiny-compress-fopen.php b/src/class-tiny-compress-fopen.php
index 4e7a9cd..83a1928 100644
--- a/src/class-tiny-compress-fopen.php
+++ b/src/class-tiny-compress-fopen.php
@@ -86,6 +86,12 @@ protected function compress( $input, $resize_opts, $preserve_opts, $convert_to )
$params = $this->request_options( 'POST', $input );
list($details, $headers, $status_code) = $this->request( $params );
+ Tiny_Logger::debug('client fopen compress out', array(
+ 'details' => $details,
+ 'headers' => $headers,
+ 'status' => $status_code,
+ ));
+
$output_url = isset( $headers['location'] ) ? $headers['location'] : null;
if ( $status_code >= 400 && is_array( $details ) && isset( $details['error'] ) ) {
throw new Tiny_Exception(
diff --git a/src/class-tiny-image.php b/src/class-tiny-image.php
index 3a5a267..d8f803c 100644
--- a/src/class-tiny-image.php
+++ b/src/class-tiny-image.php
@@ -185,6 +185,10 @@ public function get_mime_type() {
}
public function compress() {
+ Tiny_Logger::debug('compress', array(
+ 'image_id' => $this->id,
+ 'name' => $this->name,
+ ));
if ( $this->settings->get_compressor() === null || ! $this->file_type_allowed() ) {
return;
}
@@ -207,6 +211,20 @@ public function compress() {
$convert_to = $this->convert_to();
foreach ( $unprocessed_sizes as $size_name => $size ) {
+ Tiny_Logger::debug('compress size', array(
+ 'image_id' => $this->id,
+ 'size' => $size_name,
+ 'resize' => $resize,
+ 'preserve' => $preserve,
+ 'convert' => $convert_to,
+ 'modified' => $size->modified(),
+ 'filename' => $size->filename,
+ 'is_duplicate' => $size->is_duplicate(),
+ 'exists' => $size->exists(),
+ 'has_been_compressed' => $size->has_been_compressed(),
+ 'filesize' => $size->filesize(),
+ 'mimetype' => $size->mimetype(),
+ ));
if ( ! $size->is_duplicate() ) {
$size->add_tiny_meta_start();
$this->update_tiny_post_meta();
@@ -227,9 +245,18 @@ public function compress() {
$size->add_tiny_meta( $response );
$success++;
+ Tiny_Logger::debug('compress success', array(
+ 'size' => $size_name,
+ 'image_id' => $this->id,
+ ));
} catch ( Tiny_Exception $e ) {
$size->add_tiny_meta_error( $e );
$failed++;
+ Tiny_Logger::error('compress failed', array(
+ 'error' => $e,
+ 'size' => $size_name,
+ 'image_id' => $this->id,
+ ));
}
$this->add_wp_metadata( $size_name, $size );
$this->update_tiny_post_meta();
diff --git a/src/class-tiny-logger.php b/src/class-tiny-logger.php
index d128a7a..2253ff1 100644
--- a/src/class-tiny-logger.php
+++ b/src/class-tiny-logger.php
@@ -59,11 +59,11 @@ public static function get_instance()
private function __construct()
{
$this->log_enabled = 'on' === get_option('tinypng_logging_enabled', false);
- if ($this->log_enabled) {
- $this->log_file_path = $this->get_log_file_path();
- }
+ $this->log_file_path = $this->get_log_file_path();
+ }
- add_action('pre_update_option_tinypng_logging_enabled', array($this, 'on_save_log_enabled'), 10, 3);
+ public static function init() {
+ add_filter('pre_update_option_tinypng_logging_enabled', 'Tiny_Logger::on_save_log_enabled', 10, 3);
}
/**
@@ -74,12 +74,14 @@ private function __construct()
*
* @since 3.7.0
*/
- public function on_save_log_enabled($new, $old, $option)
+ public static function on_save_log_enabled($log_enabled, $old, $option)
{
- $this->log_enabled = 'on' === $new;
- if ($this->log_enabled) {
- $this->log_file_path = $this->get_log_file_path();
+ if ($log_enabled !== "on") {
+ $instance = self::get_instance();
+ $instance->clear_logs();
}
+
+ return $log_enabled;
}
/**
diff --git a/src/class-tiny-plugin.php b/src/class-tiny-plugin.php
index f6ff1d1..078be44 100644
--- a/src/class-tiny-plugin.php
+++ b/src/class-tiny-plugin.php
@@ -178,6 +178,7 @@ public function admin_init() {
$this->tiny_compatibility();
add_thickbox();
+ Tiny_Logger::init();
}
public function admin_menu() {
@@ -314,6 +315,11 @@ public function process_attachment( $metadata, $attachment_id ) {
public function blocking_compress_on_upload( $metadata, $attachment_id ) {
if ( ! empty( $metadata ) ) {
$tiny_image = new Tiny_Image( $this->settings, $attachment_id, $metadata );
+
+ Tiny_Logger::debug('blocking compress on upload', array(
+ 'image_id' => $attachment_id,
+ ));
+
$result = $tiny_image->compress();
return $tiny_image->get_wp_metadata();
} else {
@@ -354,6 +360,10 @@ public function async_compress_on_upload( $metadata, $attachment_id ) {
set_transient( 'tiny_rpc_' . $rpc_hash, get_current_user_id(), 10 );
}
+ Tiny_Logger::debug('remote post', array(
+ 'image_id' => $attachment_id,
+ ));
+
if ( getenv( 'WORDPRESS_HOST' ) !== false ) {
wp_remote_post( getenv( 'WORDPRESS_HOST' ) . '/wp-admin/admin-ajax.php', $args );
} else {
@@ -406,6 +416,11 @@ public function compress_on_upload() {
$metadata = $_POST['metadata'];
if ( is_array( $metadata ) ) {
$tiny_image = new Tiny_Image( $this->settings, $attachment_id, $metadata );
+
+ Tiny_Logger::debug('compress on upload', array(
+ 'image_id' => $attachment_id,
+ ));
+
$result = $tiny_image->compress();
// The wp_update_attachment_metadata call is thrown because the
// dimensions of the original image can change. This will then
@@ -469,8 +484,12 @@ public function compress_image_from_library() {
echo $response['error'];
exit();
}
-
list($id, $metadata) = $response['data'];
+
+ Tiny_Logger::debug('compress from library', array(
+ 'image_id' => $id,
+ ));
+
$tiny_image = new Tiny_Image( $this->settings, $id, $metadata );
$result = $tiny_image->compress();
@@ -503,6 +522,11 @@ public function compress_image_for_bulk() {
$size_before = $image_statistics_before['compressed_total_size'];
$tiny_image = new Tiny_Image( $this->settings, $id, $metadata );
+
+ Tiny_Logger::debug('compress from bulk', array(
+ 'image_id' => $id,
+ ));
+
$result = $tiny_image->compress();
$image_statistics = $tiny_image->get_statistics(
$this->settings->get_sizes(),
From df29291890187dffc23e6601f680ef3f33a277b1 Mon Sep 17 00:00:00 2001
From: tijmen
Date: Mon, 5 Jan 2026 13:36:23 +0100
Subject: [PATCH 07/23] Set timeout and proxy options on curl client
---
src/class-tiny-compress-client.php | 14 ++++++++++++++
1 file changed, 14 insertions(+)
diff --git a/src/class-tiny-compress-client.php b/src/class-tiny-compress-client.php
index f868a23..e91922f 100644
--- a/src/class-tiny-compress-client.php
+++ b/src/class-tiny-compress-client.php
@@ -30,6 +30,14 @@
class Tiny_Compress_Client extends Tiny_Compress {
+ /**
+ * API request timeout in seconds.
+ *
+ * @since 3.6.8
+ * @var int
+ */
+ const API_TIMEOUT = 10;
+
private $last_error_code = 0;
private $last_message = '';
private $proxy;
@@ -176,6 +184,10 @@ private function set_request_options( $client ) {
$property->setAccessible( true );
$options = $property->getValue( $client );
+ // Set API request timeout to prevent indefinite hanging
+ $options[ CURLOPT_TIMEOUT ] = self::API_TIMEOUT;
+ $options[ CURLOPT_CONNECTTIMEOUT ] = self::API_TIMEOUT;
+
if ( TINY_DEBUG ) {
$file = fopen( dirname( __FILE__ ) . '/curl.log', 'w' );
if ( is_resource( $file ) ) {
@@ -194,5 +206,7 @@ private function set_request_options( $client ) {
$options[ CURLOPT_PROXYUSERPWD ] = $this->proxy->authentication();
}
}
+
+ $property->setValue( $client, $options );
}
}
From 98eade789c2c9113324a1ef839dc0852974c18a8 Mon Sep 17 00:00:00 2001
From: tijmen
Date: Mon, 5 Jan 2026 13:50:35 +0100
Subject: [PATCH 08/23] Scaffold tests
---
src/class-tiny-logger.php | 6 ------
test/unit/TinyDiagnosticsTest.php | 11 +++++++++++
test/unit/TinyLoggerTest.php | 11 +++++++++++
3 files changed, 22 insertions(+), 6 deletions(-)
create mode 100644 test/unit/TinyDiagnosticsTest.php
create mode 100644 test/unit/TinyLoggerTest.php
diff --git a/src/class-tiny-logger.php b/src/class-tiny-logger.php
index 2253ff1..fe3a3c0 100644
--- a/src/class-tiny-logger.php
+++ b/src/class-tiny-logger.php
@@ -96,12 +96,6 @@ private function get_log_file_path()
$upload_dir = wp_upload_dir();
$log_dir = trailingslashit($upload_dir['basedir']) . 'tiny-compress-logs';
- if (! file_exists($log_dir)) {
- wp_mkdir_p($log_dir);
- // Add .htaccess to protect log files.
- file_put_contents(trailingslashit($log_dir) . '.htaccess', 'Deny from all');
- }
-
return trailingslashit($log_dir) . 'tiny-compress.log';
}
diff --git a/test/unit/TinyDiagnosticsTest.php b/test/unit/TinyDiagnosticsTest.php
new file mode 100644
index 0000000..c9db2ed
--- /dev/null
+++ b/test/unit/TinyDiagnosticsTest.php
@@ -0,0 +1,11 @@
+
Date: Mon, 5 Jan 2026 19:09:12 +0100
Subject: [PATCH 09/23] formatting
---
src/class-tiny-compress-client.php | 6 +-
src/class-tiny-diagnostics.php | 128 +++++-----
src/class-tiny-image.php | 4 +-
src/class-tiny-logger.php | 108 ++++----
src/class-tiny-plugin.php | 6 +-
src/class-tiny-settings.php | 2 +-
src/views/settings-diagnostics.php | 58 ++---
src/views/settings.php | 2 +-
test/helpers/wordpress.php | 389 +++++++++++++++++------------
9 files changed, 380 insertions(+), 323 deletions(-)
diff --git a/src/class-tiny-compress-client.php b/src/class-tiny-compress-client.php
index e91922f..d4a8918 100644
--- a/src/class-tiny-compress-client.php
+++ b/src/class-tiny-compress-client.php
@@ -144,10 +144,10 @@ protected function compress( $input, $resize_opts, $preserve_opts, $convert_to )
return $result;
} catch ( \Tinify\Exception $err ) {
$this->last_error_code = $err->status;
-
+
Tiny_Logger::error('client compress error', array(
- "error" => $err->getMessage(),
- "status" => $err->status,
+ 'error' => $err->getMessage(),
+ 'status' => $err->status,
));
throw new Tiny_Exception(
diff --git a/src/class-tiny-diagnostics.php b/src/class-tiny-diagnostics.php
index 34c56d0..989e93b 100644
--- a/src/class-tiny-diagnostics.php
+++ b/src/class-tiny-diagnostics.php
@@ -23,8 +23,8 @@
*
* @since 3.7.0
*/
-class Tiny_Diagnostics
-{
+class Tiny_Diagnostics {
+
/**
* Tiny settings
*
@@ -35,19 +35,18 @@ class Tiny_Diagnostics
/**
* @param Tiny_Settings $settings
*/
- public function __construct($settings)
- {
+ public function __construct( $settings ) {
$this->settings = $settings;
add_action(
'wp_ajax_tiny_download_diagnostics',
- array($this, 'download_diagnostics')
+ array( $this, 'download_diagnostics' )
);
}
/**
* Collects all diagnostic information.
- *
+ *
* File contains:
* - timestamp of export
* - server information
@@ -56,15 +55,14 @@ public function __construct($settings)
* - tinify settings
* - image settings
* - logs
- *
+ *
* @since 3.7.0
*
* @return array Array of diagnostic information.
*/
- public function collect_info()
- {
+ public function collect_info() {
$info = array(
- 'timestamp' => current_time('Y-m-d H:i:s'),
+ 'timestamp' => current_time( 'Y-m-d H:i:s' ),
'server_info' => self::get_server_info(),
'site_info' => self::get_site_info(),
'active_plugins' => self::get_active_plugins(),
@@ -82,8 +80,7 @@ public function collect_info()
*
* @return array Site information.
*/
- private static function get_site_info()
- {
+ private static function get_site_info() {
global $wp_version;
$theme = wp_get_theme();
@@ -94,9 +91,9 @@ private static function get_site_info()
'is_multisite' => is_multisite(),
'site_language' => get_locale(),
'timezone' => wp_timezone_string(),
- 'theme_name' => $theme->get('Name'),
- 'theme_version' => $theme->get('Version'),
- 'theme_uri' => $theme->get('ThemeURI'),
+ 'theme_name' => $theme->get( 'Name' ),
+ 'theme_version' => $theme->get( 'Version' ),
+ 'theme_uri' => $theme->get( 'ThemeURI' ),
);
}
@@ -107,21 +104,20 @@ private static function get_site_info()
*
* @return array Server information.
*/
- private static function get_server_info()
- {
+ private static function get_server_info() {
global $wpdb;
return array(
'php_version' => phpversion(),
- 'server_software' => isset($_SERVER['SERVER_SOFTWARE']) ? sanitize_text_field(wp_unslash($_SERVER['SERVER_SOFTWARE'])) : 'Unknown',
+ 'server_software' => isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : 'Unknown',
'mysql_version' => $wpdb->db_version(),
- 'max_execution_time' => ini_get('max_execution_time'),
- 'memory_limit' => ini_get('memory_limit'),
- 'post_max_size' => ini_get('post_max_size'),
- 'upload_max_filesize' => ini_get('upload_max_filesize'),
- 'max_input_vars' => ini_get('max_input_vars'),
- 'curl_version' => function_exists('curl_version') ? curl_version()['version'] : 'Not available',
- 'disabled_functions' => ini_get('disable_functions'),
+ 'max_execution_time' => ini_get( 'max_execution_time' ),
+ 'memory_limit' => ini_get( 'memory_limit' ),
+ 'post_max_size' => ini_get( 'post_max_size' ),
+ 'upload_max_filesize' => ini_get( 'upload_max_filesize' ),
+ 'max_input_vars' => ini_get( 'max_input_vars' ),
+ 'curl_version' => function_exists( 'curl_version' ) ? curl_version()['version'] : 'Not available',
+ 'disabled_functions' => ini_get( 'disable_functions' ),
);
}
@@ -132,13 +128,12 @@ private static function get_server_info()
*
* @return array List of active plugins.
*/
- private static function get_active_plugins()
- {
- $active_plugins = get_option('active_plugins', array());
+ private static function get_active_plugins() {
+ $active_plugins = get_option( 'active_plugins', array() );
$plugins = array();
- foreach ($active_plugins as $plugin) {
- $plugin_data = get_plugin_data(WP_PLUGIN_DIR . '/' . $plugin);
+ foreach ( $active_plugins as $plugin ) {
+ $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin );
$plugins[] = array(
'name' => $plugin_data['Name'],
'version' => $plugin_data['Version'],
@@ -157,8 +152,7 @@ private static function get_active_plugins()
*
* @return array Plugin settings
*/
- private function get_tiny_info()
- {
+ private function get_tiny_info() {
return array(
'version' => Tiny_Plugin::version(),
'status' => $this->settings->get_status(),
@@ -171,10 +165,9 @@ private function get_tiny_info()
);
}
- public function download_diagnostics()
- {
+ public function download_diagnostics() {
$zippath = $this->create_diagnostic_zip();
- return $this->download_zip($zippath);
+ return $this->download_zip( $zippath );
}
/**
@@ -184,38 +177,37 @@ public function download_diagnostics()
*
* @return string|WP_Error Path to the created zip file or WP_Error on failure.
*/
- public function create_diagnostic_zip()
- {
- if (! class_exists('ZipArchive')) {
- return new WP_Error('zip_not_available', __('ZipArchive class is not available on this server.', 'tiny-compress-images'));
+ public function create_diagnostic_zip() {
+ if ( ! class_exists( 'ZipArchive' ) ) {
+ return new WP_Error( 'zip_not_available', __( 'ZipArchive class is not available on this server.', 'tiny-compress-images' ) );
}
$upload_dir = wp_upload_dir();
- $temp_dir = trailingslashit($upload_dir['basedir']) . 'tiny-compress-temp';
+ $temp_dir = trailingslashit( $upload_dir['basedir'] ) . 'tiny-compress-temp';
- if (! file_exists($temp_dir)) {
- wp_mkdir_p($temp_dir);
+ if ( ! file_exists( $temp_dir ) ) {
+ wp_mkdir_p( $temp_dir );
}
- $zip_filename = 'tiny-compress-diagnostics-' . gmdate('Y-m-d-His') . '.zip';
- $zip_path = trailingslashit($temp_dir) . $zip_filename;
+ $zip_filename = 'tiny-compress-diagnostics-' . gmdate( 'Y-m-d-His' ) . '.zip';
+ $zip_path = trailingslashit( $temp_dir ) . $zip_filename;
$zip = new ZipArchive();
- if (true !== $zip->open($zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE)) {
- return new WP_Error('zip_create_failed', __('Failed to create zip file.', 'tiny-compress-images'));
+ if ( true !== $zip->open( $zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE ) ) {
+ return new WP_Error( 'zip_create_failed', __( 'Failed to create zip file.', 'tiny-compress-images' ) );
}
// Add diagnostic info.
$info = self::collect_info();
- $zip->addFromString('diagnostics.json', wp_json_encode($info, JSON_PRETTY_PRINT));
+ $zip->addFromString( 'diagnostics.json', wp_json_encode( $info, JSON_PRETTY_PRINT ) );
// Add log files.
$logger = Tiny_Logger::get_instance();
$log_files = $logger->get_log_files();
- foreach ($log_files as $log_file) {
- if (file_exists($log_file)) {
- $zip->addFile($log_file, 'logs/' . basename($log_file));
+ foreach ( $log_files as $log_file ) {
+ if ( file_exists( $log_file ) ) {
+ $zip->addFile( $log_file, 'logs/' . basename( $log_file ) );
}
}
@@ -230,24 +222,23 @@ public function create_diagnostic_zip()
*
* @param string $zip_path Path to the zip file.
*/
- public static function download_zip($zip_path)
- {
- if (! file_exists($zip_path)) {
- wp_die(esc_html__('Diagnostic file not found.', 'tiny-compress-images'));
+ public static function download_zip( $zip_path ) {
+ if ( ! file_exists( $zip_path ) ) {
+ wp_die( esc_html__( 'Diagnostic file not found.', 'tiny-compress-images' ) );
}
- header('Content-Type: application/zip');
- header('Content-Disposition: attachment; filename="' . basename($zip_path) . '"');
- header('Content-Length: ' . filesize($zip_path));
- header('Pragma: no-cache');
- header('Expires: 0');
+ header( 'Content-Type: application/zip' );
+ header( 'Content-Disposition: attachment; filename="' . basename( $zip_path ) . '"' );
+ header( 'Content-Length: ' . filesize( $zip_path ) );
+ header( 'Pragma: no-cache' );
+ header( 'Expires: 0' );
// phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_readfile
- readfile($zip_path);
+ readfile( $zip_path );
// Clean up.
// phpcs:ignore WordPress.WP.AlternativeFunctions.unlink_unlink
- unlink($zip_path);
+ unlink( $zip_path );
exit;
}
@@ -257,22 +248,21 @@ public static function download_zip($zip_path)
*
* @since 3.7.0
*/
- public static function cleanup_old_diagnostics()
- {
+ public static function cleanup_old_diagnostics() {
$upload_dir = wp_upload_dir();
- $temp_dir = trailingslashit($upload_dir['basedir']) . 'tiny-compress-temp';
+ $temp_dir = trailingslashit( $upload_dir['basedir'] ) . 'tiny-compress-temp';
- if (! file_exists($temp_dir)) {
+ if ( ! file_exists( $temp_dir ) ) {
return;
}
- $files = glob(trailingslashit($temp_dir) . 'tiny-compress-diagnostics-*.zip');
+ $files = glob( trailingslashit( $temp_dir ) . 'tiny-compress-diagnostics-*.zip' );
$max_age = DAY_IN_SECONDS; // 1 day.
- foreach ($files as $file) {
- if (file_exists($file) && (time() - filemtime($file)) > $max_age) {
+ foreach ( $files as $file ) {
+ if ( file_exists( $file ) && (time() - filemtime( $file )) > $max_age ) {
// phpcs:ignore WordPress.WP.AlternativeFunctions.unlink_unlink
- unlink($file);
+ unlink( $file );
}
}
}
diff --git a/src/class-tiny-image.php b/src/class-tiny-image.php
index d8f803c..a77ab38 100644
--- a/src/class-tiny-image.php
+++ b/src/class-tiny-image.php
@@ -260,8 +260,8 @@ public function compress() {
}
$this->add_wp_metadata( $size_name, $size );
$this->update_tiny_post_meta();
- }
- }
+ }// End if().
+ }// End foreach().
/*
Other plugins can hook into this action to execute custom logic
diff --git a/src/class-tiny-logger.php b/src/class-tiny-logger.php
index fe3a3c0..0f833de 100644
--- a/src/class-tiny-logger.php
+++ b/src/class-tiny-logger.php
@@ -23,8 +23,8 @@
*
* @since 3.7.0
*/
-class Tiny_Logger
-{
+class Tiny_Logger {
+
const LOG_LEVEL_ERROR = 'error';
const LOG_LEVEL_DEBUG = 'debug';
@@ -43,9 +43,8 @@ class Tiny_Logger
*
* @return Tiny_Logger The logger instance.
*/
- public static function get_instance()
- {
- if (null === self::$instance) {
+ public static function get_instance() {
+ if ( null === self::$instance ) {
self::$instance = new self();
}
return self::$instance;
@@ -56,14 +55,13 @@ public static function get_instance()
*
* @since 3.7.0
*/
- private function __construct()
- {
- $this->log_enabled = 'on' === get_option('tinypng_logging_enabled', false);
+ private function __construct() {
+ $this->log_enabled = 'on' === get_option( 'tinypng_logging_enabled', false );
$this->log_file_path = $this->get_log_file_path();
}
public static function init() {
- add_filter('pre_update_option_tinypng_logging_enabled', 'Tiny_Logger::on_save_log_enabled', 10, 3);
+ add_filter( 'pre_update_option_tinypng_logging_enabled', 'Tiny_Logger::on_save_log_enabled', 10, 3 );
}
/**
@@ -74,9 +72,8 @@ public static function init() {
*
* @since 3.7.0
*/
- public static function on_save_log_enabled($log_enabled, $old, $option)
- {
- if ($log_enabled !== "on") {
+ public static function on_save_log_enabled( $log_enabled, $old, $option ) {
+ if ( $log_enabled !== 'on' ) {
$instance = self::get_instance();
$instance->clear_logs();
}
@@ -91,12 +88,11 @@ public static function on_save_log_enabled($log_enabled, $old, $option)
*
* @return string The log file path.
*/
- private function get_log_file_path()
- {
+ private function get_log_file_path() {
$upload_dir = wp_upload_dir();
- $log_dir = trailingslashit($upload_dir['basedir']) . 'tiny-compress-logs';
+ $log_dir = trailingslashit( $upload_dir['basedir'] ) . 'tiny-compress-logs';
- return trailingslashit($log_dir) . 'tiny-compress.log';
+ return trailingslashit( $log_dir ) . 'tiny-compress.log';
}
/**
@@ -106,9 +102,8 @@ private function get_log_file_path()
*
* @return string The log directory path.
*/
- public function get_log_dir()
- {
- return dirname($this->log_file_path);
+ public function get_log_dir() {
+ return dirname( $this->log_file_path );
}
/**
@@ -118,8 +113,7 @@ public function get_log_dir()
*
* @return bool True if logging is enabled.
*/
- public function is_enabled()
- {
+ public function is_enabled() {
return $this->log_enabled;
}
@@ -131,10 +125,9 @@ public function is_enabled()
* @param string $message The message to log.
* @param array $context Optional. Additional context data. Default empty array.
*/
- public static function error($message, $context = array())
- {
+ public static function error( $message, $context = array() ) {
$instance = self::get_instance();
- $instance->log(self::LOG_LEVEL_ERROR, $message, $context);
+ $instance->log( self::LOG_LEVEL_ERROR, $message, $context );
}
/**
@@ -145,10 +138,9 @@ public static function error($message, $context = array())
* @param string $message The message to log.
* @param array $context Optional. Additional context data. Default empty array.
*/
- public static function debug($message, $context = array())
- {
+ public static function debug( $message, $context = array() ) {
$instance = self::get_instance();
- $instance->log(self::LOG_LEVEL_DEBUG, $message, $context);
+ $instance->log( self::LOG_LEVEL_DEBUG, $message, $context );
}
/**
@@ -160,23 +152,22 @@ public static function debug($message, $context = array())
* @param string $message The message to log.
* @param array $context Optional. Additional context data. Default empty array.
*/
- private function log($level, $message, $context = array())
- {
- if (! $this->log_enabled) {
+ private function log( $level, $message, $context = array() ) {
+ if ( ! $this->log_enabled ) {
return;
}
$this->rotate_logs();
- $timestamp = current_time('Y-m-d H:i:s');
- $level_str = strtoupper($level);
- $context_str = ! empty($context) ? ' ' . wp_json_encode($context) : '';
+ $timestamp = current_time( 'Y-m-d H:i:s' );
+ $level_str = strtoupper( $level );
+ $context_str = ! empty( $context ) ? ' ' . wp_json_encode( $context ) : '';
$log_entry = "[{$timestamp}] [{$level_str}] {$message}{$context_str}\n";
- $file = fopen($this->log_file_path, 'a');
- if ($file) {
- fwrite($file, $log_entry);
- fclose($file);
+ $file = fopen( $this->log_file_path, 'a' );
+ if ( $file ) {
+ fwrite( $file, $log_entry );
+ fclose( $file );
}
}
@@ -185,31 +176,30 @@ private function log($level, $message, $context = array())
*
* @since 3.7.0
*/
- private function rotate_logs()
- {
- if (! file_exists($this->log_file_path)) {
+ private function rotate_logs() {
+ if ( ! file_exists( $this->log_file_path ) ) {
return;
}
- $file_size = filesize($this->log_file_path);
- if ($file_size < self::MAX_LOG_SIZE) {
+ $file_size = filesize( $this->log_file_path );
+ if ( $file_size < self::MAX_LOG_SIZE ) {
return;
}
- for ($i = self::MAX_LOG_FILES - 1; $i > 0; $i--) {
+ for ( $i = self::MAX_LOG_FILES - 1; $i > 0; $i-- ) {
$old_file = $this->log_file_path . '.' . $i;
$new_file = $this->log_file_path . '.' . ($i + 1);
- if (file_exists($old_file)) {
- if ($i === self::MAX_LOG_FILES - 1) {
- unlink($old_file);
+ if ( file_exists( $old_file ) ) {
+ if ( $i === self::MAX_LOG_FILES - 1 ) {
+ unlink( $old_file );
} else {
- rename($old_file, $new_file);
+ rename( $old_file, $new_file );
}
}
}
- rename($this->log_file_path, $this->log_file_path . '.1');
+ rename( $this->log_file_path, $this->log_file_path . '.1' );
}
/**
@@ -219,20 +209,19 @@ private function rotate_logs()
*
* @return bool True if logs were cleared successfully.
*/
- public function clear_logs()
- {
+ public function clear_logs() {
$cleared = true;
// Remove main log file.
- if (file_exists($this->log_file_path)) {
- $cleared = unlink($this->log_file_path) && $cleared;
+ if ( file_exists( $this->log_file_path ) ) {
+ $cleared = unlink( $this->log_file_path ) && $cleared;
}
// Remove rotated log files.
- for ($i = 1; $i <= self::MAX_LOG_FILES; $i++) {
+ for ( $i = 1; $i <= self::MAX_LOG_FILES; $i++ ) {
$log_file = $this->log_file_path . '.' . $i;
- if (file_exists($log_file)) {
- $cleared = unlink($log_file) && $cleared;
+ if ( file_exists( $log_file ) ) {
+ $cleared = unlink( $log_file ) && $cleared;
}
}
@@ -246,17 +235,16 @@ public function clear_logs()
*
* @return array Array of log file paths.
*/
- public function get_log_files()
- {
+ public function get_log_files() {
$files = array();
- if (file_exists($this->log_file_path)) {
+ if ( file_exists( $this->log_file_path ) ) {
$files[] = $this->log_file_path;
}
- for ($i = 1; $i <= self::MAX_LOG_FILES; $i++) {
+ for ( $i = 1; $i <= self::MAX_LOG_FILES; $i++ ) {
$log_file = $this->log_file_path . '.' . $i;
- if (file_exists($log_file)) {
+ if ( file_exists( $log_file ) ) {
$files[] = $log_file;
}
}
diff --git a/src/class-tiny-plugin.php b/src/class-tiny-plugin.php
index 078be44..8c9c05f 100644
--- a/src/class-tiny-plugin.php
+++ b/src/class-tiny-plugin.php
@@ -319,7 +319,7 @@ public function blocking_compress_on_upload( $metadata, $attachment_id ) {
Tiny_Logger::debug('blocking compress on upload', array(
'image_id' => $attachment_id,
));
-
+
$result = $tiny_image->compress();
return $tiny_image->get_wp_metadata();
} else {
@@ -489,7 +489,7 @@ public function compress_image_from_library() {
Tiny_Logger::debug('compress from library', array(
'image_id' => $id,
));
-
+
$tiny_image = new Tiny_Image( $this->settings, $id, $metadata );
$result = $tiny_image->compress();
@@ -522,7 +522,7 @@ public function compress_image_for_bulk() {
$size_before = $image_statistics_before['compressed_total_size'];
$tiny_image = new Tiny_Image( $this->settings, $id, $metadata );
-
+
Tiny_Logger::debug('compress from bulk', array(
'image_id' => $id,
));
diff --git a/src/class-tiny-settings.php b/src/class-tiny-settings.php
index a0678cb..4793a6a 100644
--- a/src/class-tiny-settings.php
+++ b/src/class-tiny-settings.php
@@ -30,7 +30,7 @@ class Tiny_Settings extends Tiny_WP_Base {
public function __construct() {
parent::__construct();
$this->notices = new Tiny_Notices();
- new Tiny_Diagnostics($this);
+ new Tiny_Diagnostics( $this );
}
private function init_compressor() {
diff --git a/src/views/settings-diagnostics.php b/src/views/settings-diagnostics.php
index 2638e7e..4a678a3 100644
--- a/src/views/settings-diagnostics.php
+++ b/src/views/settings-diagnostics.php
@@ -1,33 +1,33 @@
\ No newline at end of file
+ 'tiny-compress-images'
+ ) ?>
+
+
+ >
+
+
+
+
+
+
+
+
+
diff --git a/src/views/settings.php b/src/views/settings.php
index 0deb0e4..df06cb9 100644
--- a/src/views/settings.php
+++ b/src/views/settings.php
@@ -60,7 +60,7 @@
-
+
diff --git a/test/helpers/wordpress.php b/test/helpers/wordpress.php
index 184b57a..debe8aa 100644
--- a/test/helpers/wordpress.php
+++ b/test/helpers/wordpress.php
@@ -1,16 +1,19 @@
values = array(
+ public function __construct()
+ {
+ $this->values = array(
'thumbnail_size_w' => 150,
'thumbnail_size_h' => 150,
'medium_size_w' => 300,
@@ -19,26 +22,29 @@ public function __construct() {
'medium_large_size_h' => 0,
'large_size_w' => 1024,
'large_size_h' => 1024,
- );
+ );
}
- public function set( $key, $value ) {
- if ( preg_match( '#^(.+)\[(.+)\]$#', $key, $match ) ) {
- if ( ! isset( $this->values[ $match[1] ] ) ) {
- $this->values[ $match[1] ] = array();
+ public function set($key, $value)
+ {
+ if (preg_match('#^(.+)\[(.+)\]$#', $key, $match)) {
+ if (! isset($this->values[$match[1]])) {
+ $this->values[$match[1]] = array();
}
- $this->values[ $match[1] ][ $match[2] ] = $value;
+ $this->values[$match[1]][$match[2]] = $value;
} else {
- $this->values[ $key ] = $value;
+ $this->values[$key] = $value;
}
}
- public function get( $key, $default = null ) {
- return isset( $this->values[ $key ] ) ? $this->values[ $key ] : $default;
+ public function get($key, $default = null)
+ {
+ return isset($this->values[$key]) ? $this->values[$key] : $default;
}
}
-class WordPressStubs {
+class WordPressStubs
+{
const UPLOAD_DIR = 'wp-content/uploads';
private $vfs;
@@ -50,46 +56,60 @@ class WordPressStubs {
private $stubs;
private $filters;
- public function __construct( $vfs ) {
+ public function __construct($vfs)
+ {
$GLOBALS['wp'] = $this;
$this->vfs = $vfs;
- $this->addMethod( 'add_action' );
- $this->addMethod( 'do_action' );
- $this->addMethod( 'add_filter' );
- $this->addMethod( 'apply_filters' );
- $this->addMethod( 'register_setting' );
- $this->addMethod( 'add_settings_section' );
- $this->addMethod( 'add_settings_field' );
- $this->addMethod( 'get_option' );
- $this->addMethod( 'get_site_option' );
- $this->addMethod( 'update_site_option' );
- $this->addMethod( 'get_post_meta' );
- $this->addMethod( 'update_post_meta' );
- $this->addMethod( 'get_intermediate_image_sizes' );
- $this->addMethod( 'add_image_size' );
- $this->addMethod( 'translate' );
- $this->addMethod( 'load_plugin_textdomain' );
- $this->addMethod( 'get_post_mime_type' );
- $this->addMethod( 'get_plugin_data' );
- $this->addMethod( 'wp_upload_dir' );
- $this->addMethod( 'get_site_url' );
- $this->addMethod( 'plugin_basename' );
- $this->addMethod( 'is_multisite' );
- $this->addMethod( 'current_user_can' );
- $this->addMethod( 'wp_get_attachment_metadata' );
- $this->addMethod( 'is_admin' );
- $this->addMethod( 'is_customize_preview' );
- $this->addMethod( 'is_plugin_active' );
+ $this->addMethod('add_action');
+ $this->addMethod('do_action');
+ $this->addMethod('add_filter');
+ $this->addMethod('apply_filters');
+ $this->addMethod('register_setting');
+ $this->addMethod('add_settings_section');
+ $this->addMethod('add_settings_field');
+ $this->addMethod('get_option');
+ $this->addMethod('get_site_option');
+ $this->addMethod('update_site_option');
+ $this->addMethod('get_post_meta');
+ $this->addMethod('update_post_meta');
+ $this->addMethod('get_intermediate_image_sizes');
+ $this->addMethod('add_image_size');
+ $this->addMethod('translate');
+ $this->addMethod('load_plugin_textdomain');
+ $this->addMethod('get_post_mime_type');
+ $this->addMethod('get_plugin_data');
+ $this->addMethod('wp_upload_dir');
+ $this->addMethod('get_site_url');
+ $this->addMethod('plugin_basename');
+ $this->addMethod('is_multisite');
+ $this->addMethod('current_user_can');
+ $this->addMethod('wp_get_attachment_metadata');
+ $this->addMethod('is_admin');
+ $this->addMethod('is_customize_preview');
+ $this->addMethod('is_plugin_active');
+ $this->addMethod('trailingslashit');
$this->defaults();
$this->create_filesystem();
}
- public function create_filesystem() {
- vfsStream::newDirectory( self::UPLOAD_DIR )
- ->at( $this->vfs );
+ /**
+ * Mocked function for https://developer.wordpress.org/reference/functions/trailingslashit/
+ *
+ * @return void
+ */
+ public function trailingslashit($value)
+ {
+ return $value;
+ }
+
+ public function create_filesystem()
+ {
+ vfsStream::newDirectory(self::UPLOAD_DIR)
+ ->at($this->vfs);
}
- public function defaults() {
+ public function defaults()
+ {
$this->initFunctions = array();
$this->admin_initFunctions = array();
$this->options = new WordPressOptions();
@@ -98,49 +118,50 @@ public function defaults() {
$GLOBALS['_wp_additional_image_sizes'] = array();
}
- public function call( $method, $args ) {
- $this->calls[ $method ][] = $args;
- if ( 'add_action' === $method ) {
- if ( 'init' === $args[0] ) {
+ public function call($method, $args)
+ {
+ $this->calls[$method][] = $args;
+ if ('add_action' === $method) {
+ if ('init' === $args[0]) {
$this->initFunctions[] = $args[1];
- } elseif ( 'admin_init' === $args[0] ) {
+ } elseif ('admin_init' === $args[0]) {
$this->admin_initFunctions[] = $args[1];
}
}
// Allow explicit stubs to override defaults/behaviors
- if ( isset( $this->stubs[ $method ] ) && $this->stubs[ $method ] ) {
- return call_user_func_array( $this->stubs[ $method ], $args );
+ if (isset($this->stubs[$method]) && $this->stubs[$method]) {
+ return call_user_func_array($this->stubs[$method], $args);
}
- if ( 'add_filter' === $method ) {
- $tag = isset( $args[0] ) ? $args[0] : '';
- $function_to_add = isset( $args[1] ) ? $args[1] : '';
- $priority = isset( $args[2] ) ? intval( $args[2] ) : 10;
- $accepted_args = isset( $args[3] ) ? intval( $args[3] ) : 1;
- if ( ! isset( $this->filters[ $tag ] ) ) {
- $this->filters[ $tag ] = array();
+ if ('add_filter' === $method) {
+ $tag = isset($args[0]) ? $args[0] : '';
+ $function_to_add = isset($args[1]) ? $args[1] : '';
+ $priority = isset($args[2]) ? intval($args[2]) : 10;
+ $accepted_args = isset($args[3]) ? intval($args[3]) : 1;
+ if (! isset($this->filters[$tag])) {
+ $this->filters[$tag] = array();
}
- if ( ! isset( $this->filters[ $tag ][ $priority ] ) ) {
- $this->filters[ $tag ][ $priority ] = array();
+ if (! isset($this->filters[$tag][$priority])) {
+ $this->filters[$tag][$priority] = array();
}
- $this->filters[ $tag ][ $priority ][] = array(
+ $this->filters[$tag][$priority][] = array(
'function' => $function_to_add,
'accepted_args' => $accepted_args,
);
return true;
}
- if ( 'apply_filters' === $method ) {
- $tag = isset( $args[0] ) ? $args[0] : '';
+ if ('apply_filters' === $method) {
+ $tag = isset($args[0]) ? $args[0] : '';
// $value is the first value passed to filters
- $value = isset( $args[1] ) ? $args[1] : null;
- $call_args = array_slice( $args, 1 );
- if ( isset( $this->filters[ $tag ] ) ) {
- $priorities = array_keys( $this->filters[ $tag ] );
- sort( $priorities, SORT_NUMERIC );
- foreach ( $priorities as $priority ) {
- foreach ( $this->filters[ $tag ][ $priority ] as $callback ) {
- $accepted = max( 1, intval( $callback['accepted_args'] ) );
- $args_to_pass = array_slice( $call_args, 0, $accepted );
- $returned = call_user_func_array( $callback['function'], $args_to_pass );
+ $value = isset($args[1]) ? $args[1] : null;
+ $call_args = array_slice($args, 1);
+ if (isset($this->filters[$tag])) {
+ $priorities = array_keys($this->filters[$tag]);
+ sort($priorities, SORT_NUMERIC);
+ foreach ($priorities as $priority) {
+ foreach ($this->filters[$tag][$priority] as $callback) {
+ $accepted = max(1, intval($callback['accepted_args']));
+ $args_to_pass = array_slice($call_args, 0, $accepted);
+ $returned = call_user_func_array($callback['function'], $args_to_pass);
// Filters should return the (possibly modified) value as first argument.
$call_args[0] = $returned;
}
@@ -148,116 +169,130 @@ public function call( $method, $args ) {
}
return $call_args[0];
}
- if ( 'translate' === $method ) {
+ if ('translate' === $method) {
return $args[0];
- } elseif ( 'get_option' === $method ) {
- return call_user_func_array( array( $this->options, 'get' ), $args );
- } elseif ( 'get_post_meta' === $method ) {
- return call_user_func_array( array( $this, 'getMetadata' ), $args );
- } elseif ( 'add_image_size' === $method ) {
- return call_user_func_array( array( $this, 'addImageSize' ), $args );
- } elseif ( 'update_post_meta' === $method ) {
- return call_user_func_array( array( $this, 'updateMetadata' ), $args );
- } elseif ( 'get_intermediate_image_sizes' === $method ) {
- return array_merge( array( 'thumbnail', 'medium', 'medium_large', 'large' ), array_keys( $GLOBALS['_wp_additional_image_sizes'] ) );
- } elseif ( 'get_plugin_data' === $method ) {
- return array( 'Version' => '1.7.2' );
- } elseif ( 'plugin_basename' === $method ) {
+ } elseif ('get_option' === $method) {
+ return call_user_func_array(array($this->options, 'get'), $args);
+ } elseif ('get_post_meta' === $method) {
+ return call_user_func_array(array($this, 'getMetadata'), $args);
+ } elseif ('add_image_size' === $method) {
+ return call_user_func_array(array($this, 'addImageSize'), $args);
+ } elseif ('update_post_meta' === $method) {
+ return call_user_func_array(array($this, 'updateMetadata'), $args);
+ } elseif ('get_intermediate_image_sizes' === $method) {
+ return array_merge(array('thumbnail', 'medium', 'medium_large', 'large'), array_keys($GLOBALS['_wp_additional_image_sizes']));
+ } elseif ('get_plugin_data' === $method) {
+ return array('Version' => '1.7.2');
+ } elseif ('plugin_basename' === $method) {
return 'tiny-compress-images';
- } elseif ( 'wp_upload_dir' === $method ) {
- return array( 'basedir' => $this->vfs->url() . '/' . self::UPLOAD_DIR, 'baseurl' => '/' . self::UPLOAD_DIR );
- } elseif ( 'is_admin' === $method ) {
+ } elseif ('wp_upload_dir' === $method) {
+ return array('basedir' => $this->vfs->url() . '/' . self::UPLOAD_DIR, 'baseurl' => '/' . self::UPLOAD_DIR);
+ } elseif ('is_admin' === $method) {
return true;
}
}
- public function addMethod( $method ) {
- $this->calls[ $method ] = array();
- $this->stubs[ $method ] = array();
- if ( ! function_exists( $method ) ) {
- eval( "function $method() { return \$GLOBALS['wp']->call('$method', func_get_args()); }" );
+ public function addMethod($method)
+ {
+ $this->calls[$method] = array();
+ $this->stubs[$method] = array();
+ if (! function_exists($method)) {
+ eval("function $method() { return \$GLOBALS['wp']->call('$method', func_get_args()); }");
}
}
- public function addOption( $key, $value ) {
- $this->options->set( $key, $value );
+ public function addOption($key, $value)
+ {
+ $this->options->set($key, $value);
}
- public function addImageSize( $size, $values ) {
- $GLOBALS['_wp_additional_image_sizes'][ $size ] = $values;
+ public function addImageSize($size, $values)
+ {
+ $GLOBALS['_wp_additional_image_sizes'][$size] = $values;
}
- public function getMetadata( $id, $key, $single = false ) {
- $values = isset( $this->metadata[ $id ] ) ? $this->metadata[ $id ] : array();
- $value = isset( $values[ $key ] ) ? $values[ $key ] : '';
- return $single ? $value : array( $value );
+ public function getMetadata($id, $key, $single = false)
+ {
+ $values = isset($this->metadata[$id]) ? $this->metadata[$id] : array();
+ $value = isset($values[$key]) ? $values[$key] : '';
+ return $single ? $value : array($value);
}
- public function updateMetadata( $id, $key, $values ) {
- $this->metadata[ $id ][ $key ] = $values;
+ public function updateMetadata($id, $key, $values)
+ {
+ $this->metadata[$id][$key] = $values;
}
- public function setTinyMetadata( $id, $values ) {
- $this->metadata[ $id ] = array( Tiny_Config::META_KEY => $values );
+ public function setTinyMetadata($id, $values)
+ {
+ $this->metadata[$id] = array(Tiny_Config::META_KEY => $values);
}
- public function getCalls( $method ) {
- return $this->calls[ $method ];
+ public function getCalls($method)
+ {
+ return $this->calls[$method];
}
- public function init() {
- foreach ( $this->initFunctions as $func ) {
- call_user_func( $func );
+ public function init()
+ {
+ foreach ($this->initFunctions as $func) {
+ call_user_func($func);
}
}
- public function admin_init() {
- foreach ( $this->admin_initFunctions as $func ) {
- call_user_func( $func );
+ public function admin_init()
+ {
+ foreach ($this->admin_initFunctions as $func) {
+ call_user_func($func);
}
}
- public function stub( $method, $func ) {
- $this->stubs[ $method ] = $func;
+ public function stub($method, $func)
+ {
+ $this->stubs[$method] = $func;
}
- public function createImage( $file_size, $path, $name ) {
- if ( ! $this->vfs->hasChild( self::UPLOAD_DIR . "/$path" ) ) {
- vfsStream::newDirectory( self::UPLOAD_DIR . "/$path" )->at( $this->vfs );
+ public function createImage($file_size, $path, $name)
+ {
+ if (! $this->vfs->hasChild(self::UPLOAD_DIR . "/$path")) {
+ vfsStream::newDirectory(self::UPLOAD_DIR . "/$path")->at($this->vfs);
}
- $dir = $this->vfs->getChild( self::UPLOAD_DIR . "/$path" );
+ $dir = $this->vfs->getChild(self::UPLOAD_DIR . "/$path");
- vfsStream::newFile( $name )
- ->withContent( new LargeFileContent( $file_size ) )
- ->at( $dir );
+ vfsStream::newFile($name)
+ ->withContent(new LargeFileContent($file_size))
+ ->at($dir);
}
- public function createImages( $sizes = null, $original_size = 12345, $path = '14/01', $name = 'test' ) {
- vfsStream::newDirectory( self::UPLOAD_DIR . "/$path" )->at( $this->vfs );
- $dir = $this->vfs->getChild( self::UPLOAD_DIR . '/' . $path );
+ public function createImages($sizes = null, $original_size = 12345, $path = '14/01', $name = 'test')
+ {
+ vfsStream::newDirectory(self::UPLOAD_DIR . "/$path")->at($this->vfs);
+ $dir = $this->vfs->getChild(self::UPLOAD_DIR . '/' . $path);
- vfsStream::newFile( "$name.png" )
- ->withContent( new LargeFileContent( $original_size ) )
- ->at( $dir );
+ vfsStream::newFile("$name.png")
+ ->withContent(new LargeFileContent($original_size))
+ ->at($dir);
- if ( is_null( $sizes ) ) {
- $sizes = array( 'thumbnail' => 100, 'medium' => 1000 , 'large' => 10000, 'post-thumbnail' => 1234 );
+ if (is_null($sizes)) {
+ $sizes = array('thumbnail' => 100, 'medium' => 1000, 'large' => 10000, 'post-thumbnail' => 1234);
}
- foreach ( $sizes as $key => $size ) {
- vfsStream::newFile( "$name-$key.png" )
- ->withContent( new LargeFileContent( $size ) )
- ->at( $dir );
+ foreach ($sizes as $key => $size) {
+ vfsStream::newFile("$name-$key.png")
+ ->withContent(new LargeFileContent($size))
+ ->at($dir);
}
}
- public function createImagesFromJSON( $virtual_images ) {
- foreach ( $virtual_images['images'] as $image ) {
- self::createImage( $image['size'], $virtual_images['path'], $image['file'] );
+ public function createImagesFromJSON($virtual_images)
+ {
+ foreach ($virtual_images['images'] as $image) {
+ self::createImage($image['size'], $virtual_images['path'], $image['file']);
}
}
- public function getTestMetadata( $path = '14/01', $name = 'test' ) {
+ public function getTestMetadata($path = '14/01', $name = 'test')
+ {
$metadata = array(
'file' => "$path/$name.png",
'width' => 4000,
@@ -265,29 +300,73 @@ public function getTestMetadata( $path = '14/01', $name = 'test' ) {
'sizes' => array(),
);
- $regex = '#^' . preg_quote( $name ) . '-([^.]+)[.](png|jpe?g)$#';
- $dir = $this->vfs->getChild( self::UPLOAD_DIR . "/$path" );
- foreach ( $dir->getChildren() as $child ) {
+ $regex = '#^' . preg_quote($name) . '-([^.]+)[.](png|jpe?g)$#';
+ $dir = $this->vfs->getChild(self::UPLOAD_DIR . "/$path");
+ foreach ($dir->getChildren() as $child) {
$file = $child->getName();
- if ( preg_match( $regex, $file, $match ) ) {
- $metadata['sizes'][ $match[1] ] = array( 'file' => $file );
+ if (preg_match($regex, $file, $match)) {
+ $metadata['sizes'][$match[1]] = array('file' => $file);
}
}
return $metadata;
}
+
+ /**
+ * Testhelper to easily assert if a hook has been invoked
+ *
+ * @param string $hookname name of the filter or action
+ * @param mixed $expected_args arguments to the hook
+ */
+ public static function assertHook($hookname, $expected_args = null)
+ {
+ $hooks = array('add_action', 'add_filter');
+ $found = false;
+
+ foreach ($hooks as $method) {
+ if (! isset($GLOBALS['wp'])) {
+ break;
+ }
+
+ foreach ($GLOBALS['wp']->getCalls($method) as $call) {
+ if (! isset($call[0]) || $call[0] !== $hookname) {
+ continue;
+ }
+
+ if (is_null($expected_args)) {
+ $found = true;
+ break 2;
+ }
+
+ if ($expected_args === array_slice($call, 1)[0]) {
+ $found = true;
+ break 2;
+ }
+ }
+ }
+
+ $message = is_null($expected_args)
+ ? sprintf('Expected hook "%s" to be called.', $hookname)
+ : sprintf('Expected hook "%s" to be called with the given arguments.', $hookname);
+
+ Assert::assertTrue($found, $message);
+ }
}
-class WP_HTTP_Proxy {
- public function is_enabled() {
+class WP_HTTP_Proxy
+{
+ public function is_enabled()
+ {
return false;
}
}
-function __( $text, $domain = 'default' ) {
- return translate( $text, $domain );
+function __($text, $domain = 'default')
+{
+ return translate($text, $domain);
}
-function esc_html__( $text, $domain = 'default' ) {
- return translate( $text, $domain );
-}
\ No newline at end of file
+function esc_html__($text, $domain = 'default')
+{
+ return translate($text, $domain);
+}
From 178d63f8b360ad85e7d3009188f240fe7ed19d8e Mon Sep 17 00:00:00 2001
From: tijmen
Date: Mon, 5 Jan 2026 19:09:29 +0100
Subject: [PATCH 10/23] Add initial tests
---
test/unit/TinyDiagnosticsTest.php | 7 +++++++
test/unit/TinyLoggerTest.php | 9 +++++++++
2 files changed, 16 insertions(+)
diff --git a/test/unit/TinyDiagnosticsTest.php b/test/unit/TinyDiagnosticsTest.php
index c9db2ed..ec4bb1a 100644
--- a/test/unit/TinyDiagnosticsTest.php
+++ b/test/unit/TinyDiagnosticsTest.php
@@ -8,4 +8,11 @@ public function set_up()
{
parent::set_up();
}
+
+ public function test_adds_ajax_action_to_download_diagnostics() {
+ $tiny_settings = new Tiny_Settings();
+ $tiny_diagnostics = new Tiny_Diagnostics($tiny_settings);
+
+ WordPressStubs::assertHook('wp_ajax_tiny_download_diagnostics', array($tiny_diagnostics, 'download_diagnostics'));
+ }
}
diff --git a/test/unit/TinyLoggerTest.php b/test/unit/TinyLoggerTest.php
index fda9c86..b55a59e 100644
--- a/test/unit/TinyLoggerTest.php
+++ b/test/unit/TinyLoggerTest.php
@@ -1,5 +1,7 @@
Date: Mon, 5 Jan 2026 19:23:45 +0100
Subject: [PATCH 11/23] On constructor log enabled test
---
src/class-tiny-logger.php | 30 ++++++++++++++++++++++++++++++
test/unit/TinyLoggerTest.php | 14 ++++++++++++++
2 files changed, 44 insertions(+)
diff --git a/src/class-tiny-logger.php b/src/class-tiny-logger.php
index 0f833de..6a34f28 100644
--- a/src/class-tiny-logger.php
+++ b/src/class-tiny-logger.php
@@ -25,6 +25,7 @@
*/
class Tiny_Logger {
+
const LOG_LEVEL_ERROR = 'error';
const LOG_LEVEL_DEBUG = 'debug';
@@ -60,10 +61,39 @@ private function __construct() {
$this->log_file_path = $this->get_log_file_path();
}
+ /**
+ * Initializes the logger by registering WordPress hooks.
+ *
+ * This method hooks into 'pre_update_option_tinypng_logging_enabled' to
+ * intercept and process logging settings before they are saved to the database.
+ *
+ * @since 3.7.0
+ *
+ * @return void
+ */
public static function init() {
add_filter( 'pre_update_option_tinypng_logging_enabled', 'Tiny_Logger::on_save_log_enabled', 10, 3 );
}
+ /**
+ * Resets the singleton instance.
+ * Used primarily for unit testing.
+ */
+ public static function reset() {
+ self::$instance = null;
+ }
+
+ /**
+ * Retrieves whether logging is currently enabled.
+ *
+ * @since 3.7.0
+ *
+ * @return bool True if logging is enabled, false otherwise.
+ */
+ public function get_log_enabled() {
+ return $this->log_enabled;
+ }
+
/**
* Triggered when log_enabled is saved
* - set the setting on the instance
diff --git a/test/unit/TinyLoggerTest.php b/test/unit/TinyLoggerTest.php
index b55a59e..4482a6d 100644
--- a/test/unit/TinyLoggerTest.php
+++ b/test/unit/TinyLoggerTest.php
@@ -1,6 +1,7 @@
reset();
+ }
+
public function test_logger_always_has_one_instance()
{
$instance1 = Tiny_Logger::get_instance();
$instance2 = Tiny_Logger::get_instance();
assertEquals($instance1, $instance2, 'logger should be a singleton');
}
+
+ public function test_log_enabled_when_option_is_on() {
+ $this->wp->addOption('tinypng_logging_enabled', 'on');
+ $logger = Tiny_Logger::get_instance();
+ assertTrue($logger->get_log_enabled(), 'log should be enabled when tinypng_logging_enabled is on');
+ }
}
From 2cfabf1a444a8cd9b5037f474d69c97472919004 Mon Sep 17 00:00:00 2001
From: tijmen
Date: Mon, 5 Jan 2026 19:24:54 +0100
Subject: [PATCH 12/23] Manual formatting logger
---
src/class-tiny-logger.php | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/src/class-tiny-logger.php b/src/class-tiny-logger.php
index 6a34f28..33119fa 100644
--- a/src/class-tiny-logger.php
+++ b/src/class-tiny-logger.php
@@ -72,7 +72,9 @@ private function __construct() {
* @return void
*/
public static function init() {
- add_filter( 'pre_update_option_tinypng_logging_enabled', 'Tiny_Logger::on_save_log_enabled', 10, 3 );
+ add_filter(
+ 'pre_update_option_tinypng_logging_enabled',
+ 'Tiny_Logger::on_save_log_enabled', 10, 3 );
}
/**
@@ -103,7 +105,7 @@ public function get_log_enabled() {
* @since 3.7.0
*/
public static function on_save_log_enabled( $log_enabled, $old, $option ) {
- if ( $log_enabled !== 'on' ) {
+ if ( 'on' !== $log_enabled ) {
$instance = self::get_instance();
$instance->clear_logs();
}
@@ -221,7 +223,7 @@ private function rotate_logs() {
$new_file = $this->log_file_path . '.' . ($i + 1);
if ( file_exists( $old_file ) ) {
- if ( $i === self::MAX_LOG_FILES - 1 ) {
+ if ( self::MAX_LOG_FILES - 1 === $i ) {
unlink( $old_file );
} else {
rename( $old_file, $new_file );
From f54b12dee70d216a43260d4fe6d55263144603a7 Mon Sep 17 00:00:00 2001
From: tijmen
Date: Mon, 5 Jan 2026 19:27:27 +0100
Subject: [PATCH 13/23] Manual formatting fixes in diagnostics
---
src/class-tiny-diagnostics.php | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/src/class-tiny-diagnostics.php b/src/class-tiny-diagnostics.php
index 989e93b..29093c7 100644
--- a/src/class-tiny-diagnostics.php
+++ b/src/class-tiny-diagnostics.php
@@ -109,14 +109,18 @@ private static function get_server_info() {
return array(
'php_version' => phpversion(),
- 'server_software' => isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : 'Unknown',
+ 'server_software' => isset( $_SERVER['SERVER_SOFTWARE'] ) ?
+ sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) :
+ 'Unknown',
'mysql_version' => $wpdb->db_version(),
'max_execution_time' => ini_get( 'max_execution_time' ),
'memory_limit' => ini_get( 'memory_limit' ),
'post_max_size' => ini_get( 'post_max_size' ),
'upload_max_filesize' => ini_get( 'upload_max_filesize' ),
'max_input_vars' => ini_get( 'max_input_vars' ),
- 'curl_version' => function_exists( 'curl_version' ) ? curl_version()['version'] : 'Not available',
+ 'curl_version' => function_exists( 'curl_version' ) ?
+ curl_version()['version'] :
+ 'Not available',
'disabled_functions' => ini_get( 'disable_functions' ),
);
}
@@ -179,7 +183,12 @@ public function download_diagnostics() {
*/
public function create_diagnostic_zip() {
if ( ! class_exists( 'ZipArchive' ) ) {
- return new WP_Error( 'zip_not_available', __( 'ZipArchive class is not available on this server.', 'tiny-compress-images' ) );
+ return new WP_Error(
+ 'zip_not_available',
+ __( 'ZipArchive class is not available on this server.',
+ 'tiny-compress-images'
+ )
+ );
}
$upload_dir = wp_upload_dir();
@@ -194,7 +203,10 @@ public function create_diagnostic_zip() {
$zip = new ZipArchive();
if ( true !== $zip->open( $zip_path, ZipArchive::CREATE | ZipArchive::OVERWRITE ) ) {
- return new WP_Error( 'zip_create_failed', __( 'Failed to create zip file.', 'tiny-compress-images' ) );
+ return new WP_Error( 'zip_create_failed',
+ __( 'Failed to create zip file.',
+ 'tiny-compress-images' )
+ );
}
// Add diagnostic info.
From 9adff724e434ac180e2ec6ac1582bab5d5c75742 Mon Sep 17 00:00:00 2001
From: tijmen
Date: Mon, 5 Jan 2026 20:42:39 +0100
Subject: [PATCH 14/23] chore: add tests for log path
---
src/class-tiny-diagnostics.php | 1 -
src/class-tiny-image.php | 28 ++++++++---------
src/class-tiny-logger.php | 49 +++++++++++++++--------------
test/helpers/wordpress.php | 25 +++++++++------
test/unit/TinyLoggerTest.php | 7 ++++-
test/unit/TinySettingsAdminTest.php | 1 +
test/unit/TinySettingsAjaxTest.php | 40 +++++++++--------------
7 files changed, 76 insertions(+), 75 deletions(-)
diff --git a/src/class-tiny-diagnostics.php b/src/class-tiny-diagnostics.php
index 29093c7..b760bf5 100644
--- a/src/class-tiny-diagnostics.php
+++ b/src/class-tiny-diagnostics.php
@@ -193,7 +193,6 @@ public function create_diagnostic_zip() {
$upload_dir = wp_upload_dir();
$temp_dir = trailingslashit( $upload_dir['basedir'] ) . 'tiny-compress-temp';
-
if ( ! file_exists( $temp_dir ) ) {
wp_mkdir_p( $temp_dir );
}
diff --git a/src/class-tiny-image.php b/src/class-tiny-image.php
index a77ab38..22b4740 100644
--- a/src/class-tiny-image.php
+++ b/src/class-tiny-image.php
@@ -211,25 +211,25 @@ public function compress() {
$convert_to = $this->convert_to();
foreach ( $unprocessed_sizes as $size_name => $size ) {
- Tiny_Logger::debug('compress size', array(
- 'image_id' => $this->id,
- 'size' => $size_name,
- 'resize' => $resize,
- 'preserve' => $preserve,
- 'convert' => $convert_to,
- 'modified' => $size->modified(),
- 'filename' => $size->filename,
- 'is_duplicate' => $size->is_duplicate(),
- 'exists' => $size->exists(),
- 'has_been_compressed' => $size->has_been_compressed(),
- 'filesize' => $size->filesize(),
- 'mimetype' => $size->mimetype(),
- ));
if ( ! $size->is_duplicate() ) {
$size->add_tiny_meta_start();
$this->update_tiny_post_meta();
$resize = $this->settings->get_resize_options( $size_name );
$preserve = $this->settings->get_preserve_options( $size_name );
+ Tiny_Logger::debug('compress size', array(
+ 'image_id' => $this->id,
+ 'size' => $size_name,
+ 'resize' => $resize,
+ 'preserve' => $preserve,
+ 'convert' => $convert_to,
+ 'modified' => $size->modified(),
+ 'filename' => $size->filename,
+ 'is_duplicate' => $size->is_duplicate(),
+ 'exists' => $size->exists(),
+ 'has_been_compressed' => $size->has_been_compressed(),
+ 'filesize' => $size->filesize(),
+ 'mimetype' => $size->mimetype(),
+ ));
try {
$response = $compressor->compress_file(
$size->filename,
diff --git a/src/class-tiny-logger.php b/src/class-tiny-logger.php
index 33119fa..8bb2bd5 100644
--- a/src/class-tiny-logger.php
+++ b/src/class-tiny-logger.php
@@ -18,8 +18,10 @@
* Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
+
/**
* Handles logging of plugin events to file.
+ *
*
* @since 3.7.0
*/
@@ -33,7 +35,8 @@ class Tiny_Logger {
const MAX_LOG_FILES = 3;
private static $instance = null;
- private $log_enabled = false;
+
+ private $log_enabled = null;
private $log_file_path = null;
/**
@@ -53,12 +56,10 @@ public static function get_instance() {
/**
* Constructor.
- *
- * @since 3.7.0
+
*/
private function __construct() {
- $this->log_enabled = 'on' === get_option( 'tinypng_logging_enabled', false );
- $this->log_file_path = $this->get_log_file_path();
+ $this->log_file_path = $this->resolve_log_file_path();
}
/**
@@ -67,8 +68,6 @@ private function __construct() {
* This method hooks into 'pre_update_option_tinypng_logging_enabled' to
* intercept and process logging settings before they are saved to the database.
*
- * @since 3.7.0
- *
* @return void
*/
public static function init() {
@@ -88,14 +87,26 @@ public static function reset() {
/**
* Retrieves whether logging is currently enabled.
*
- * @since 3.7.0
- *
* @return bool True if logging is enabled, false otherwise.
*/
public function get_log_enabled() {
+ if ( null === $this->log_enabled) {
+ $this->log_enabled = 'on' === get_option( 'tinypng_logging_enabled', false );
+ }
+
return $this->log_enabled;
}
+ /**
+ * Retrieves the absolute filesystem path to the log file.
+ *
+ * @return string The full filesystem path to the tiny-compress.log file.
+ */
+ public function get_log_file_path()
+ {
+ return $this->log_file_path;
+ }
+
/**
* Triggered when log_enabled is saved
* - set the setting on the instance
@@ -114,28 +125,18 @@ public static function on_save_log_enabled( $log_enabled, $old, $option ) {
}
/**
- * Gets the log file path.
+ * Retrieves the log path using wp_upload_dir. This operation
+ * should only be used internally. Use the getter to get the
+ * memoized function.
*
* @since 3.7.0
*
* @return string The log file path.
*/
- private function get_log_file_path() {
+ private function resolve_log_file_path() {
$upload_dir = wp_upload_dir();
$log_dir = trailingslashit( $upload_dir['basedir'] ) . 'tiny-compress-logs';
-
- return trailingslashit( $log_dir ) . 'tiny-compress.log';
- }
-
- /**
- * Gets the log directory path.
- *
- * @since 3.7.0
- *
- * @return string The log directory path.
- */
- public function get_log_dir() {
- return dirname( $this->log_file_path );
+ return trailingslashit($log_dir) . 'tiny-compress.log';
}
/**
diff --git a/test/helpers/wordpress.php b/test/helpers/wordpress.php
index debe8aa..f186163 100644
--- a/test/helpers/wordpress.php
+++ b/test/helpers/wordpress.php
@@ -92,16 +92,6 @@ public function __construct($vfs)
$this->create_filesystem();
}
- /**
- * Mocked function for https://developer.wordpress.org/reference/functions/trailingslashit/
- *
- * @return void
- */
- public function trailingslashit($value)
- {
- return $value;
- }
-
public function create_filesystem()
{
vfsStream::newDirectory(self::UPLOAD_DIR)
@@ -120,6 +110,7 @@ public function defaults()
public function call($method, $args)
{
+ $mocks = new WordPressMocks();
$this->calls[$method][] = $args;
if ('add_action' === $method) {
if ('init' === $args[0]) {
@@ -189,6 +180,8 @@ public function call($method, $args)
return array('basedir' => $this->vfs->url() . '/' . self::UPLOAD_DIR, 'baseurl' => '/' . self::UPLOAD_DIR);
} elseif ('is_admin' === $method) {
return true;
+ } elseif (method_exists($mocks, $method)) {
+ return $mocks->$method($args[0]);
}
}
@@ -353,6 +346,18 @@ public static function assertHook($hookname, $expected_args = null)
}
}
+class WordPressMocks {
+ /**
+ * Mocked function for https://developer.wordpress.org/reference/functions/trailingslashit/
+ *
+ * @return void
+ */
+ public function trailingslashit($value)
+ {
+ return $value . '/';
+ }
+}
+
class WP_HTTP_Proxy
{
public function is_enabled()
diff --git a/test/unit/TinyLoggerTest.php b/test/unit/TinyLoggerTest.php
index 4482a6d..5932bf0 100644
--- a/test/unit/TinyLoggerTest.php
+++ b/test/unit/TinyLoggerTest.php
@@ -26,9 +26,14 @@ public function test_logger_always_has_one_instance()
assertEquals($instance1, $instance2, 'logger should be a singleton');
}
- public function test_log_enabled_when_option_is_on() {
+ public function test_get_log_enabled_memoizes_log_enabled() {
$this->wp->addOption('tinypng_logging_enabled', 'on');
$logger = Tiny_Logger::get_instance();
assertTrue($logger->get_log_enabled(), 'log should be enabled when tinypng_logging_enabled is on');
}
+
+ public function test_sets_log_path_on_construct() {
+ $logger = Tiny_Logger::get_instance();
+ assertEquals($logger->get_log_file_path(), 'vfs://root/wp-content/uploads/tiny-compress-logs/tiny-compress.log');
+ }
}
diff --git a/test/unit/TinySettingsAdminTest.php b/test/unit/TinySettingsAdminTest.php
index 0fdbf7f..d5577aa 100644
--- a/test/unit/TinySettingsAdminTest.php
+++ b/test/unit/TinySettingsAdminTest.php
@@ -20,6 +20,7 @@ public function test_admin_init_should_register_keys() {
array( 'tinify', 'tinypng_resize_original' ),
array( 'tinify', 'tinypng_preserve_data' ),
array( 'tinify', 'tinypng_convert_format' ),
+ array( 'tinify', 'tinypng_logging_enabled' ),
), $this->wp->getCalls( 'register_setting' ));
}
diff --git a/test/unit/TinySettingsAjaxTest.php b/test/unit/TinySettingsAjaxTest.php
index 4501fd0..40fb44b 100644
--- a/test/unit/TinySettingsAjaxTest.php
+++ b/test/unit/TinySettingsAjaxTest.php
@@ -3,37 +3,27 @@
require_once dirname( __FILE__ ) . '/TinyTestCase.php';
class Tiny_Settings_Ajax_Test extends Tiny_TestCase {
- protected $subject;
protected $notices;
public function set_up() {
parent::set_up();
- $this->subject = new Tiny_Settings();
- $this->notices = new Tiny_Notices();
- $this->subject->ajax_init();
}
+
+ public function test_settings_ajax_init() {
+ $tiny_settings = new Tiny_Settings();
+ $tiny_settings->ajax_init();
+
+ WordPressStubs::assertHook('wp_ajax_tiny_image_sizes_notice', array( $tiny_settings, 'image_sizes_notice' ));
+ WordPressStubs::assertHook('wp_ajax_tiny_account_status', array( $tiny_settings, 'account_status' ));
+ WordPressStubs::assertHook('wp_ajax_tiny_settings_create_api_key', array( $tiny_settings, 'create_api_key' ));
+ WordPressStubs::assertHook('wp_ajax_tiny_settings_update_api_key', array( $tiny_settings, 'update_api_key' ));
+ }
+
+ public function test_notices_ajax_init() {
+ $tiny_notices = new Tiny_Notices();
+ $tiny_notices->ajax_init();
- public function test_ajax_init_should_add_actions() {
- $this->assertEquals(array(
- array( 'init', array( $this->subject, 'init' ) ),
- array( 'rest_api_init', array( $this->subject, 'rest_init' ) ),
- array( 'admin_init', array( $this->subject, 'admin_init' ) ),
- array( 'admin_menu', array( $this->subject, 'admin_menu' ) ),
- array( 'init', array( $this->notices, 'init' ) ),
- array( 'rest_api_init', array( $this->notices, 'rest_init' ) ),
- array( 'admin_init', array( $this->notices, 'admin_init' ) ),
- array( 'admin_menu', array( $this->notices, 'admin_menu' ) ),
- array( 'init', array( $this->notices, 'init' ) ),
- array( 'rest_api_init', array( $this->notices, 'rest_init' ) ),
- array( 'admin_init', array( $this->notices, 'admin_init' ) ),
- array( 'admin_menu', array( $this->notices, 'admin_menu' ) ),
- array( 'wp_ajax_tiny_image_sizes_notice', array( $this->subject, 'image_sizes_notice' ) ),
- array( 'wp_ajax_tiny_account_status', array( $this->subject, 'account_status' ) ),
- array( 'wp_ajax_tiny_settings_create_api_key', array( $this->subject, 'create_api_key' ) ),
- array( 'wp_ajax_tiny_settings_update_api_key', array( $this->subject, 'update_api_key' ) ),
- ),
- $this->wp->getCalls( 'add_action' )
- );
+ WordPressStubs::assertHook('wp_ajax_tiny_dismiss_notice', array( $tiny_notices, 'dismiss' ));
}
}
From 76ce4cbc4a65aaa90f47a608904378b33e5b4499 Mon Sep 17 00:00:00 2001
From: tijmen
Date: Tue, 6 Jan 2026 16:08:34 +0100
Subject: [PATCH 15/23] chore: simplify rotation
---
src/class-tiny-logger.php | 90 ++++++++----------------------------
test/helpers/wordpress.php | 21 +++++++++
test/unit/TinyLoggerTest.php | 81 +++++++++++++++++++++++++++++++-
3 files changed, 119 insertions(+), 73 deletions(-)
diff --git a/src/class-tiny-logger.php b/src/class-tiny-logger.php
index 8bb2bd5..7769205 100644
--- a/src/class-tiny-logger.php
+++ b/src/class-tiny-logger.php
@@ -32,7 +32,6 @@ class Tiny_Logger {
const LOG_LEVEL_DEBUG = 'debug';
const MAX_LOG_SIZE = 5242880; // 5MB
- const MAX_LOG_FILES = 3;
private static $instance = null;
@@ -43,8 +42,6 @@ class Tiny_Logger {
* To log on various places easily, we create a singleton
* to prevent passing around the instance.
*
- * @since 3.7.0
- *
* @return Tiny_Logger The logger instance.
*/
public static function get_instance() {
@@ -60,6 +57,7 @@ public static function get_instance() {
*/
private function __construct() {
$this->log_file_path = $this->resolve_log_file_path();
+ $this->log_enabled = 'on' === get_option( 'tinypng_logging_enabled', false );
}
/**
@@ -90,10 +88,6 @@ public static function reset() {
* @return bool True if logging is enabled, false otherwise.
*/
public function get_log_enabled() {
- if ( null === $this->log_enabled) {
- $this->log_enabled = 'on' === get_option( 'tinypng_logging_enabled', false );
- }
-
return $this->log_enabled;
}
@@ -112,12 +106,12 @@ public function get_log_file_path()
* - set the setting on the instance
* - if turn off, clear the logs
* - if turned on, check if we can create the log file
- *
- * @since 3.7.0
*/
public static function on_save_log_enabled( $log_enabled, $old, $option ) {
+ $instance = self::get_instance();
+ $instance->log_enabled = 'on' === $log_enabled;
+
if ( 'on' !== $log_enabled ) {
- $instance = self::get_instance();
$instance->clear_logs();
}
@@ -129,8 +123,6 @@ public static function on_save_log_enabled( $log_enabled, $old, $option ) {
* should only be used internally. Use the getter to get the
* memoized function.
*
- * @since 3.7.0
- *
* @return string The log file path.
*/
private function resolve_log_file_path() {
@@ -139,22 +131,9 @@ private function resolve_log_file_path() {
return trailingslashit($log_dir) . 'tiny-compress.log';
}
- /**
- * Checks if logging is enabled.
- *
- * @since 3.7.0
- *
- * @return bool True if logging is enabled.
- */
- public function is_enabled() {
- return $this->log_enabled;
- }
-
/**
* Logs an error message.
*
- * @since 3.7.0
- *
* @param string $message The message to log.
* @param array $context Optional. Additional context data. Default empty array.
*/
@@ -166,8 +145,6 @@ public static function error( $message, $context = array() ) {
/**
* Logs a debug message.
*
- * @since 3.7.0
- *
* @param string $message The message to log.
* @param array $context Optional. Additional context data. Default empty array.
*/
@@ -179,11 +156,10 @@ public static function debug( $message, $context = array() ) {
/**
* Logs a message.
*
- * @since 3.7.0
- *
* @param string $level The log level.
* @param string $message The message to log.
* @param array $context Optional. Additional context data. Default empty array.
+ * @return void
*/
private function log( $level, $message, $context = array() ) {
if ( ! $this->log_enabled ) {
@@ -192,10 +168,16 @@ private function log( $level, $message, $context = array() ) {
$this->rotate_logs();
+ // Ensure log directory exists.
+ $log_dir = dirname( $this->log_file_path );
+ if ( ! file_exists( $log_dir ) ) {
+ wp_mkdir_p( $log_dir );
+ }
+
$timestamp = current_time( 'Y-m-d H:i:s' );
$level_str = strtoupper( $level );
$context_str = ! empty( $context ) ? ' ' . wp_json_encode( $context ) : '';
- $log_entry = "[{$timestamp}] [{$level_str}] {$message}{$context_str}\n";
+ $log_entry = "[{$timestamp}] [{$level_str}] {$message}{$context_str}\\n";
$file = fopen( $this->log_file_path, 'a' );
if ( $file ) {
@@ -205,9 +187,10 @@ private function log( $level, $message, $context = array() ) {
}
/**
- * Rotates log files when they exceed the max size.
+ * Deletes log file and creates a new one when the
+ * MAX_LOG_SIZE is met.
*
- * @since 3.7.0
+ * @return void
*/
private function rotate_logs() {
if ( ! file_exists( $this->log_file_path ) ) {
@@ -219,53 +202,25 @@ private function rotate_logs() {
return;
}
- for ( $i = self::MAX_LOG_FILES - 1; $i > 0; $i-- ) {
- $old_file = $this->log_file_path . '.' . $i;
- $new_file = $this->log_file_path . '.' . ($i + 1);
-
- if ( file_exists( $old_file ) ) {
- if ( self::MAX_LOG_FILES - 1 === $i ) {
- unlink( $old_file );
- } else {
- rename( $old_file, $new_file );
- }
- }
- }
-
- rename( $this->log_file_path, $this->log_file_path . '.1' );
+ unlink( $this->log_file_path );
}
/**
- * Clears all log files.
- *
- * @since 3.7.0
+ * Clears log file
*
* @return bool True if logs were cleared successfully.
*/
public function clear_logs() {
- $cleared = true;
-
- // Remove main log file.
if ( file_exists( $this->log_file_path ) ) {
- $cleared = unlink( $this->log_file_path ) && $cleared;
- }
-
- // Remove rotated log files.
- for ( $i = 1; $i <= self::MAX_LOG_FILES; $i++ ) {
- $log_file = $this->log_file_path . '.' . $i;
- if ( file_exists( $log_file ) ) {
- $cleared = unlink( $log_file ) && $cleared;
- }
+ return unlink( $this->log_file_path );
}
- return $cleared;
+ return true;
}
/**
* Gets all log file paths.
*
- * @since 3.7.0
- *
* @return array Array of log file paths.
*/
public function get_log_files() {
@@ -275,13 +230,6 @@ public function get_log_files() {
$files[] = $this->log_file_path;
}
- for ( $i = 1; $i <= self::MAX_LOG_FILES; $i++ ) {
- $log_file = $this->log_file_path . '.' . $i;
- if ( file_exists( $log_file ) ) {
- $files[] = $log_file;
- }
- }
-
return $files;
}
}
diff --git a/test/helpers/wordpress.php b/test/helpers/wordpress.php
index f186163..3803568 100644
--- a/test/helpers/wordpress.php
+++ b/test/helpers/wordpress.php
@@ -88,6 +88,8 @@ public function __construct($vfs)
$this->addMethod('is_customize_preview');
$this->addMethod('is_plugin_active');
$this->addMethod('trailingslashit');
+ $this->addMethod('current_time');
+ $this->addMethod('wp_mkdir_p');
$this->defaults();
$this->create_filesystem();
}
@@ -356,6 +358,25 @@ public function trailingslashit($value)
{
return $value . '/';
}
+
+ /**
+ * Mocked function for https://developer.wordpress.org/reference/functions/current_time/
+ *
+ * @return int|string
+ */
+ public function current_time() {
+ $dt = new DateTime( 'now' );
+ return $dt->format('Y-m-d H:i:s');
+ }
+
+ /**
+ * Mocked function for https://developer.wordpress.org/reference/functions/wp_mkdir_p/
+ *
+ * @return bool
+ */
+ public function wp_mkdir_p( $dir ) {
+ mkdir( $dir, 0755, true );
+ }
}
class WP_HTTP_Proxy
diff --git a/test/unit/TinyLoggerTest.php b/test/unit/TinyLoggerTest.php
index 5932bf0..621b4c3 100644
--- a/test/unit/TinyLoggerTest.php
+++ b/test/unit/TinyLoggerTest.php
@@ -1,7 +1,10 @@
clear_logs();
$logger->reset();
}
@@ -26,14 +30,87 @@ public function test_logger_always_has_one_instance()
assertEquals($instance1, $instance2, 'logger should be a singleton');
}
- public function test_get_log_enabled_memoizes_log_enabled() {
+ public function test_get_log_enabled_memoizes_log_enabled()
+ {
$this->wp->addOption('tinypng_logging_enabled', 'on');
$logger = Tiny_Logger::get_instance();
assertTrue($logger->get_log_enabled(), 'log should be enabled when tinypng_logging_enabled is on');
}
- public function test_sets_log_path_on_construct() {
+ public function test_sets_log_path_on_construct()
+ {
$logger = Tiny_Logger::get_instance();
assertEquals($logger->get_log_file_path(), 'vfs://root/wp-content/uploads/tiny-compress-logs/tiny-compress.log');
}
+
+ public function test_registers_save_update_when_log_enabled()
+ {
+ $logger = Tiny_Logger::get_instance();
+ $logger->init();
+ WordPressStubs::assertHook('pre_update_option_tinypng_logging_enabled', 'Tiny_Logger::on_save_log_enabled');
+ }
+
+ public function test_option_hook_updates_log_enabled()
+ {
+ $this->wp->addOption('tinypng_logging_enabled', false);
+ Tiny_Logger::init();
+ $logger = Tiny_Logger::get_instance();
+
+ assertFalse($logger->get_log_enabled(), 'option is not set so should be false');
+
+ apply_filters('pre_update_option_tinypng_logging_enabled', 'on', null, '');
+
+ assertTrue($logger->get_log_enabled(), 'when option is updated, should be true');
+ }
+
+ public function test_will_not_log_if_disabled()
+ {
+ $this->wp->addOption('tinypng_logging_enabled', false);
+ $logger = Tiny_Logger::get_instance();
+
+ Tiny_Logger::error('This should not be logged');
+ Tiny_Logger::debug('This should also not be logged');
+
+ $log_path = $logger->get_log_file_path();
+ $log_exists = file_exists($log_path);
+ assertFalse($log_exists, 'log file should not exist when logging is disabled');
+ }
+
+ public function test_creates_log_when_log_is_enabled()
+ {
+ $this->wp->addOption('tinypng_logging_enabled', 'on');
+
+ $logger = Tiny_Logger::get_instance();
+ $log_path = $logger->get_log_file_path();
+ $log_exists = file_exists($log_path);
+ assertFalse($log_exists, 'log file should not exist initially');
+
+ Tiny_Logger::error('This should be logged');
+ Tiny_Logger::debug('This should also be logged');
+
+ $log_path = $logger->get_log_file_path();
+ $log_exists = file_exists($log_path);
+ assertTrue($log_exists, 'log file is created when logging is enabled');
+ }
+
+ public function test_removes_full_log_and_creates_new()
+ {
+ $this->wp->addOption('tinypng_logging_enabled', 'on');
+
+ $log_dir_path = 'wp-content/uploads/tiny-compress-logs';
+ vfsStream::newDirectory($log_dir_path)->at($this->vfs);
+ $log_dir = $this->vfs->getChild($log_dir_path);
+
+ vfsStream::newFile('tiny-compress.log')
+ ->withContent(LargeFileContent::withMegabytes(5.1))
+ ->at($log_dir);
+
+ $logger = Tiny_Logger::get_instance();
+
+ assertTrue(filesize($logger->get_log_file_path()) > 5242880, 'log file should be larger than 5MB');
+
+ Tiny_Logger::error('This should be logged');
+
+ assertTrue(filesize($logger->get_log_file_path()) < 1048576, 'log file rotated and less than 1MB');
+ }
}
From 396ccbb9efa03b379ef83874c8a6147a9b546f97 Mon Sep 17 00:00:00 2001
From: tijmen
Date: Tue, 6 Jan 2026 16:08:58 +0100
Subject: [PATCH 16/23] Format
---
src/class-tiny-logger.php | 11 +++++------
1 file changed, 5 insertions(+), 6 deletions(-)
diff --git a/src/class-tiny-logger.php b/src/class-tiny-logger.php
index 7769205..f12dfd5 100644
--- a/src/class-tiny-logger.php
+++ b/src/class-tiny-logger.php
@@ -21,7 +21,7 @@
/**
* Handles logging of plugin events to file.
- *
+ *
*
* @since 3.7.0
*/
@@ -96,8 +96,7 @@ public function get_log_enabled() {
*
* @return string The full filesystem path to the tiny-compress.log file.
*/
- public function get_log_file_path()
- {
+ public function get_log_file_path() {
return $this->log_file_path;
}
@@ -110,7 +109,7 @@ public function get_log_file_path()
public static function on_save_log_enabled( $log_enabled, $old, $option ) {
$instance = self::get_instance();
$instance->log_enabled = 'on' === $log_enabled;
-
+
if ( 'on' !== $log_enabled ) {
$instance->clear_logs();
}
@@ -128,7 +127,7 @@ public static function on_save_log_enabled( $log_enabled, $old, $option ) {
private function resolve_log_file_path() {
$upload_dir = wp_upload_dir();
$log_dir = trailingslashit( $upload_dir['basedir'] ) . 'tiny-compress-logs';
- return trailingslashit($log_dir) . 'tiny-compress.log';
+ return trailingslashit( $log_dir ) . 'tiny-compress.log';
}
/**
@@ -187,7 +186,7 @@ private function log( $level, $message, $context = array() ) {
}
/**
- * Deletes log file and creates a new one when the
+ * Deletes log file and creates a new one when the
* MAX_LOG_SIZE is met.
*
* @return void
From 6cfae116d059cb43f2b88b6b011ee124b2ae5894 Mon Sep 17 00:00:00 2001
From: tijmen
Date: Tue, 6 Jan 2026 16:42:06 +0100
Subject: [PATCH 17/23] change file name, format and size
---
src/class-tiny-diagnostics.php | 2 +-
src/class-tiny-image.php | 2 +-
src/class-tiny-logger.php | 11 +++++++----
test/unit/TinyLoggerTest.php | 4 ++--
4 files changed, 11 insertions(+), 8 deletions(-)
diff --git a/src/class-tiny-diagnostics.php b/src/class-tiny-diagnostics.php
index b760bf5..256989d 100644
--- a/src/class-tiny-diagnostics.php
+++ b/src/class-tiny-diagnostics.php
@@ -210,7 +210,7 @@ public function create_diagnostic_zip() {
// Add diagnostic info.
$info = self::collect_info();
- $zip->addFromString( 'diagnostics.json', wp_json_encode( $info, JSON_PRETTY_PRINT ) );
+ $zip->addFromString( 'tiny-diagnostics.json', wp_json_encode( $info, JSON_PRETTY_PRINT ) );
// Add log files.
$logger = Tiny_Logger::get_instance();
diff --git a/src/class-tiny-image.php b/src/class-tiny-image.php
index 22b4740..adb0056 100644
--- a/src/class-tiny-image.php
+++ b/src/class-tiny-image.php
@@ -253,7 +253,7 @@ public function compress() {
$size->add_tiny_meta_error( $e );
$failed++;
Tiny_Logger::error('compress failed', array(
- 'error' => $e,
+ 'error' => $e->get_message(),
'size' => $size_name,
'image_id' => $this->id,
));
diff --git a/src/class-tiny-logger.php b/src/class-tiny-logger.php
index f12dfd5..0930034 100644
--- a/src/class-tiny-logger.php
+++ b/src/class-tiny-logger.php
@@ -31,7 +31,7 @@ class Tiny_Logger {
const LOG_LEVEL_ERROR = 'error';
const LOG_LEVEL_DEBUG = 'debug';
- const MAX_LOG_SIZE = 5242880; // 5MB
+ const MAX_LOG_SIZE = 2 * 1024 * 1024; // 2MB
private static $instance = null;
@@ -176,11 +176,14 @@ private function log( $level, $message, $context = array() ) {
$timestamp = current_time( 'Y-m-d H:i:s' );
$level_str = strtoupper( $level );
$context_str = ! empty( $context ) ? ' ' . wp_json_encode( $context ) : '';
- $log_entry = "[{$timestamp}] [{$level_str}] {$message}{$context_str}\\n";
-
+ $log_entry = "[{$timestamp}] [{$level_str}] {$message}{$context_str}" . PHP_EOL;
$file = fopen( $this->log_file_path, 'a' );
if ( $file ) {
- fwrite( $file, $log_entry );
+ if ( flock( $file, LOCK_EX ) ) {
+ fwrite( $file, $log_entry );
+ fflush( $file );
+ flock( $file, LOCK_UN );
+ }
fclose( $file );
}
}
diff --git a/test/unit/TinyLoggerTest.php b/test/unit/TinyLoggerTest.php
index 621b4c3..7140c0e 100644
--- a/test/unit/TinyLoggerTest.php
+++ b/test/unit/TinyLoggerTest.php
@@ -102,12 +102,12 @@ public function test_removes_full_log_and_creates_new()
$log_dir = $this->vfs->getChild($log_dir_path);
vfsStream::newFile('tiny-compress.log')
- ->withContent(LargeFileContent::withMegabytes(5.1))
+ ->withContent(LargeFileContent::withMegabytes(2.1))
->at($log_dir);
$logger = Tiny_Logger::get_instance();
- assertTrue(filesize($logger->get_log_file_path()) > 5242880, 'log file should be larger than 5MB');
+ assertTrue(filesize($logger->get_log_file_path()) > 2097152, 'log file should be larger than 2MB');
Tiny_Logger::error('This should be logged');
From d430ff64d081bfac35f047d8603d779d6ce14da0 Mon Sep 17 00:00:00 2001
From: tijmen
Date: Wed, 7 Jan 2026 14:33:15 +0100
Subject: [PATCH 18/23] Clear logs when turned on
---
src/class-tiny-logger.php | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/src/class-tiny-logger.php b/src/class-tiny-logger.php
index 0930034..11f9465 100644
--- a/src/class-tiny-logger.php
+++ b/src/class-tiny-logger.php
@@ -103,14 +103,13 @@ public function get_log_file_path() {
/**
* Triggered when log_enabled is saved
* - set the setting on the instance
- * - if turn off, clear the logs
- * - if turned on, check if we can create the log file
+ * - if turn on, clear the old logs
*/
public static function on_save_log_enabled( $log_enabled, $old, $option ) {
$instance = self::get_instance();
$instance->log_enabled = 'on' === $log_enabled;
- if ( 'on' !== $log_enabled ) {
+ if ( $instance->get_log_enabled() ) {
$instance->clear_logs();
}
From e4c3ef3b9a143aed1323b01b48b52892c4e1769f Mon Sep 17 00:00:00 2001
From: tijmen
Date: Wed, 7 Jan 2026 15:08:23 +0100
Subject: [PATCH 19/23] Add more tests
---
test/unit/TinyDiagnosticsTest.php | 25 ++++++++++++++++++++++++-
1 file changed, 24 insertions(+), 1 deletion(-)
diff --git a/test/unit/TinyDiagnosticsTest.php b/test/unit/TinyDiagnosticsTest.php
index ec4bb1a..088cf2b 100644
--- a/test/unit/TinyDiagnosticsTest.php
+++ b/test/unit/TinyDiagnosticsTest.php
@@ -1,5 +1,11 @@
collect_info();
+
+ // were just verifying the main structure
+ assertArrayHasKey('timestamp', $info);
+ assertArrayHasKey('server_info', $info);
+ assertArrayHasKey('site_info', $info);
+ assertArrayHasKey('active_plugins', $info);
+ assertArrayHasKey('tiny_info', $info);
+ assertArrayHasKey('image_sizes', $info);
+ }
}
From 1d7cd63791f2a9bbfa3ba1f2818c79646644e195 Mon Sep 17 00:00:00 2001
From: tijmen
Date: Wed, 7 Jan 2026 15:10:47 +0100
Subject: [PATCH 20/23] Add mocks for test
---
test/helpers/wordpress.php | 91 +++++++++++++++++++++++++++++++++++---
1 file changed, 84 insertions(+), 7 deletions(-)
diff --git a/test/helpers/wordpress.php b/test/helpers/wordpress.php
index 3803568..6f684d9 100644
--- a/test/helpers/wordpress.php
+++ b/test/helpers/wordpress.php
@@ -59,6 +59,7 @@ class WordPressStubs
public function __construct($vfs)
{
$GLOBALS['wp'] = $this;
+ $GLOBALS['wpdb'] = $this;
$this->vfs = $vfs;
$this->addMethod('add_action');
$this->addMethod('do_action');
@@ -90,6 +91,12 @@ public function __construct($vfs)
$this->addMethod('trailingslashit');
$this->addMethod('current_time');
$this->addMethod('wp_mkdir_p');
+ $this->addMethod('db_version');
+ $this->addMethod('wp_get_theme');
+ $this->addMethod('get_home_url');
+ $this->addMethod('get_locale');
+ $this->addMethod('wp_timezone_string');
+ $this->addMethod('update_option');
$this->defaults();
$this->create_filesystem();
}
@@ -110,6 +117,11 @@ public function defaults()
$GLOBALS['_wp_additional_image_sizes'] = array();
}
+ public function __call($method, $args)
+ {
+ return $this->call($method, $args);
+ }
+
public function call($method, $args)
{
$mocks = new WordPressMocks();
@@ -183,7 +195,7 @@ public function call($method, $args)
} elseif ('is_admin' === $method) {
return true;
} elseif (method_exists($mocks, $method)) {
- return $mocks->$method($args[0]);
+ return call_user_func_array(array($mocks, $method), $args);
}
}
@@ -348,7 +360,8 @@ public static function assertHook($hookname, $expected_args = null)
}
}
-class WordPressMocks {
+class WordPressMocks
+{
/**
* Mocked function for https://developer.wordpress.org/reference/functions/trailingslashit/
*
@@ -358,14 +371,15 @@ public function trailingslashit($value)
{
return $value . '/';
}
-
+
/**
* Mocked function for https://developer.wordpress.org/reference/functions/current_time/
*
* @return int|string
*/
- public function current_time() {
- $dt = new DateTime( 'now' );
+ public function current_time()
+ {
+ $dt = new DateTime('now');
return $dt->format('Y-m-d H:i:s');
}
@@ -374,8 +388,71 @@ public function current_time() {
*
* @return bool
*/
- public function wp_mkdir_p( $dir ) {
- mkdir( $dir, 0755, true );
+ public function wp_mkdir_p($dir)
+ {
+ mkdir($dir, 0755, true);
+ }
+
+ /**
+ * https://developer.wordpress.org/reference/classes/wpdb/db_version/
+ *
+ * @return string|null database version
+ */
+ public function db_version()
+ {
+ return 'mysqlv';
+ }
+
+ /**
+ * https://developer.wordpress.org/reference/classes/wpdb/db_version/
+ *
+ * @return string|null database version
+ */
+ public function wp_get_theme()
+ {
+ return new class {
+ function get($val)
+ {
+ return $val;
+ }
+ };
+ }
+
+ /**
+ * https://developer.wordpress.org/reference/classes/wpdb/db_version/
+ *
+ * @return string|null database version
+ */
+ public function get_home_url()
+ {
+ return 'http://localhost';
+ }
+
+ /**
+ * https://developer.wordpress.org/reference/classes/wpdb/db_version/
+ *
+ * @return string|null database version
+ */
+ public function get_locale()
+ {
+ return 'gb_GB';
+ }
+ /**
+ * https://developer.wordpress.org/reference/functions/wp_timezone_string/
+ *
+ * @return string|null database version
+ */
+ public function wp_timezone_string()
+ {
+ return 'timezone';
+ }
+ /**
+ * https://developer.wordpress.org/reference/functions/wp_timezone_string/
+ *
+ * @return void
+ */
+ public function update_option()
+ {
}
}
From 85f8158ef4716117c0cd6994b6a7a361712bb76d Mon Sep 17 00:00:00 2001
From: tijmen
Date: Wed, 7 Jan 2026 22:13:31 +0100
Subject: [PATCH 21/23] set timeout to 300
---
src/class-tiny-compress-client.php | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/class-tiny-compress-client.php b/src/class-tiny-compress-client.php
index d4a8918..3b4636c 100644
--- a/src/class-tiny-compress-client.php
+++ b/src/class-tiny-compress-client.php
@@ -36,7 +36,7 @@ class Tiny_Compress_Client extends Tiny_Compress {
* @since 3.6.8
* @var int
*/
- const API_TIMEOUT = 10;
+ const API_TIMEOUT = 300;
private $last_error_code = 0;
private $last_message = '';
From f995de476de7b9a64034eb3164f8a684f3595cc2 Mon Sep 17 00:00:00 2001
From: tijmen
Date: Fri, 9 Jan 2026 13:39:01 +0100
Subject: [PATCH 22/23] Seperate API timeout and connect timeout
---
src/class-tiny-compress-client.php | 5 +++--
1 file changed, 3 insertions(+), 2 deletions(-)
diff --git a/src/class-tiny-compress-client.php b/src/class-tiny-compress-client.php
index 3b4636c..b41aa6c 100644
--- a/src/class-tiny-compress-client.php
+++ b/src/class-tiny-compress-client.php
@@ -36,7 +36,8 @@ class Tiny_Compress_Client extends Tiny_Compress {
* @since 3.6.8
* @var int
*/
- const API_TIMEOUT = 300;
+ const API_TIMEOUT = 120;
+ const CONNECT_TIMEOUT = 8;
private $last_error_code = 0;
private $last_message = '';
@@ -186,7 +187,7 @@ private function set_request_options( $client ) {
// Set API request timeout to prevent indefinite hanging
$options[ CURLOPT_TIMEOUT ] = self::API_TIMEOUT;
- $options[ CURLOPT_CONNECTTIMEOUT ] = self::API_TIMEOUT;
+ $options[ CURLOPT_CONNECTTIMEOUT ] = self::CONNECT_TIMEOUT;
if ( TINY_DEBUG ) {
$file = fopen( dirname( __FILE__ ) . '/curl.log', 'w' );
From 42623d1e863aa655ce48d56d0729f2938bc5adde Mon Sep 17 00:00:00 2001
From: tijmen
Date: Fri, 9 Jan 2026 14:23:23 +0100
Subject: [PATCH 23/23] remove server info and add a phpinfo file
---
src/class-tiny-diagnostics.php | 37 +++++++------------------------
test/unit/TinyDiagnosticsTest.php | 6 -----
2 files changed, 8 insertions(+), 35 deletions(-)
diff --git a/src/class-tiny-diagnostics.php b/src/class-tiny-diagnostics.php
index 256989d..b335042 100644
--- a/src/class-tiny-diagnostics.php
+++ b/src/class-tiny-diagnostics.php
@@ -63,7 +63,6 @@ public function __construct( $settings ) {
public function collect_info() {
$info = array(
'timestamp' => current_time( 'Y-m-d H:i:s' ),
- 'server_info' => self::get_server_info(),
'site_info' => self::get_site_info(),
'active_plugins' => self::get_active_plugins(),
'tiny_info' => $this->get_tiny_info(),
@@ -97,34 +96,6 @@ private static function get_site_info() {
);
}
- /**
- * Gets server information.
- *
- * @since 3.7.0
- *
- * @return array Server information.
- */
- private static function get_server_info() {
- global $wpdb;
-
- return array(
- 'php_version' => phpversion(),
- 'server_software' => isset( $_SERVER['SERVER_SOFTWARE'] ) ?
- sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) :
- 'Unknown',
- 'mysql_version' => $wpdb->db_version(),
- 'max_execution_time' => ini_get( 'max_execution_time' ),
- 'memory_limit' => ini_get( 'memory_limit' ),
- 'post_max_size' => ini_get( 'post_max_size' ),
- 'upload_max_filesize' => ini_get( 'upload_max_filesize' ),
- 'max_input_vars' => ini_get( 'max_input_vars' ),
- 'curl_version' => function_exists( 'curl_version' ) ?
- curl_version()['version'] :
- 'Not available',
- 'disabled_functions' => ini_get( 'disable_functions' ),
- );
- }
-
/**
* Gets list of active plugins.
*
@@ -212,6 +183,14 @@ public function create_diagnostic_zip() {
$info = self::collect_info();
$zip->addFromString( 'tiny-diagnostics.json', wp_json_encode( $info, JSON_PRETTY_PRINT ) );
+ // Add phpinfo HTML.
+ ob_start();
+ phpinfo( INFO_GENERAL );
+ phpinfo( INFO_CONFIGURATION );
+ phpinfo( INFO_MODULES );
+ $phpinfo_html = ob_get_clean();
+ $zip->addFromString( 'phpinfo.html', $phpinfo_html );
+
// Add log files.
$logger = Tiny_Logger::get_instance();
$log_files = $logger->get_log_files();
diff --git a/test/unit/TinyDiagnosticsTest.php b/test/unit/TinyDiagnosticsTest.php
index 088cf2b..548934c 100644
--- a/test/unit/TinyDiagnosticsTest.php
+++ b/test/unit/TinyDiagnosticsTest.php
@@ -1,9 +1,4 @@