compatibility
1 day ago
config
1 day ago
css
5 months ago
data
3 years ago
images
3 years ago
js
1 day ago
vendor
4 months ago
views
1 day ago
class-tiny-apache-rewrite.php
1 day ago
class-tiny-bulk-optimization.php
1 day ago
class-tiny-cli.php
1 day ago
class-tiny-compress-client.php
1 day ago
class-tiny-compress-fopen.php
1 day ago
class-tiny-compress.php
1 day ago
class-tiny-conversion.php
2 months ago
class-tiny-diagnostics.php
5 months ago
class-tiny-exception.php
5 months ago
class-tiny-helpers.php
1 day ago
class-tiny-image-size.php
1 day ago
class-tiny-image.php
1 day ago
class-tiny-logger.php
1 day ago
class-tiny-migrate.php
1 day ago
class-tiny-notices.php
1 day ago
class-tiny-php.php
1 day ago
class-tiny-picture.php
1 day ago
class-tiny-plugin.php
1 day ago
class-tiny-settings.php
1 day ago
class-tiny-source-base.php
2 months ago
class-tiny-source-image.php
5 months ago
class-tiny-source-picture.php
5 months ago
class-tiny-wp-base.php
1 day ago
class-tiny-diagnostics.php
271 lines
| 1 | <?php |
| 2 | /* |
| 3 | * Tiny Compress Images - WordPress plugin. |
| 4 | * Copyright (C) 2015-2026 Tinify B.V. |
| 5 | * |
| 6 | * This program is free software; you can redistribute it and/or modify it |
| 7 | * under the terms of the GNU General Public License as published by the Free |
| 8 | * Software Foundation; either version 2 of the License, or (at your option) |
| 9 | * any later version. |
| 10 | * |
| 11 | * This program is distributed in the hope that it will be useful, but WITHOUT |
| 12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| 13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for |
| 14 | * more details. |
| 15 | * |
| 16 | * You should have received a copy of the GNU General Public License along |
| 17 | * with this program; if not, write to the Free Software Foundation, Inc., 51 |
| 18 | * Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
| 19 | */ |
| 20 | |
| 21 | /** |
| 22 | * Collects diagnostic information and generates downloadable zip files. |
| 23 | * |
| 24 | * @since 3.7.0 |
| 25 | */ |
| 26 | class Tiny_Diagnostics { |
| 27 | |
| 28 | /** |
| 29 | * Tiny settings |
| 30 | * |
| 31 | * @var Tiny_Settings |
| 32 | */ |
| 33 | private $settings; |
| 34 | |
| 35 | /** |
| 36 | * @param Tiny_Settings $settings |
| 37 | */ |
| 38 | public function __construct( $settings ) { |
| 39 | $this->settings = $settings; |
| 40 | |
| 41 | add_action( |
| 42 | 'wp_ajax_tiny_download_diagnostics', |
| 43 | array( $this, 'download_diagnostics' ) |
| 44 | ); |
| 45 | } |
| 46 | |
| 47 | /** |
| 48 | * Collects all diagnostic information. |
| 49 | * |
| 50 | * File contains: |
| 51 | * - timestamp of export |
| 52 | * - server information |
| 53 | * - site information |
| 54 | * - plugin list |
| 55 | * - tinify settings |
| 56 | * - image settings |
| 57 | * - logs |
| 58 | * |
| 59 | * @since 3.7.0 |
| 60 | * |
| 61 | * @return array Array of diagnostic information. |
| 62 | */ |
| 63 | public function collect_info() { |
| 64 | $info = array( |
| 65 | 'timestamp' => current_time( 'Y-m-d H:i:s' ), |
| 66 | 'site_info' => self::get_site_info(), |
| 67 | 'server_info' => self::get_server_info(), |
| 68 | 'active_plugins' => self::get_active_plugins(), |
| 69 | 'tiny_info' => $this->get_tiny_info(), |
| 70 | 'image_sizes' => $this->settings->get_active_tinify_sizes(), |
| 71 | ); |
| 72 | |
| 73 | return $info; |
| 74 | } |
| 75 | |
| 76 | /** |
| 77 | * Gets server information. |
| 78 | * We have considered phpinfo but this would be a security concern |
| 79 | * as it contains a lot of information we probably do not need. |
| 80 | * Whenever support needs more server information, we can manually |
| 81 | * add it here. |
| 82 | * |
| 83 | * @since 3.7.0 |
| 84 | * |
| 85 | * @return array Server information. |
| 86 | */ |
| 87 | private static function get_server_info() { |
| 88 | global $wpdb; |
| 89 | |
| 90 | return array( |
| 91 | 'php_version' => phpversion(), |
| 92 | 'server_software' => isset( $_SERVER['SERVER_SOFTWARE'] ) ? |
| 93 | sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : |
| 94 | 'Unknown', |
| 95 | 'mysql_version' => $wpdb->db_version(), |
| 96 | 'max_execution_time' => ini_get( 'max_execution_time' ), |
| 97 | 'memory_limit' => ini_get( 'memory_limit' ), |
| 98 | 'post_max_size' => ini_get( 'post_max_size' ), |
| 99 | 'upload_max_filesize' => ini_get( 'upload_max_filesize' ), |
| 100 | 'max_input_vars' => ini_get( 'max_input_vars' ), |
| 101 | 'curl_version' => function_exists( 'curl_version' ) ? |
| 102 | curl_version()['version'] : |
| 103 | 'Not available', |
| 104 | 'disabled_functions' => ini_get( 'disable_functions' ), |
| 105 | ); |
| 106 | } |
| 107 | |
| 108 | /** |
| 109 | * Gets site information. |
| 110 | * |
| 111 | * @since 3.7.0 |
| 112 | * |
| 113 | * @return array Site information. |
| 114 | */ |
| 115 | private static function get_site_info() { |
| 116 | global $wp_version; |
| 117 | $theme = wp_get_theme(); |
| 118 | |
| 119 | return array( |
| 120 | 'wp_version' => $wp_version, |
| 121 | 'site_url' => get_site_url(), |
| 122 | 'home_url' => get_home_url(), |
| 123 | 'is_multisite' => is_multisite(), |
| 124 | 'site_language' => get_locale(), |
| 125 | 'timezone' => wp_timezone_string(), |
| 126 | 'theme_name' => $theme->get( 'Name' ), |
| 127 | 'theme_version' => $theme->get( 'Version' ), |
| 128 | 'theme_uri' => $theme->get( 'ThemeURI' ), |
| 129 | ); |
| 130 | } |
| 131 | |
| 132 | /** |
| 133 | * Gets list of active plugins. |
| 134 | * |
| 135 | * @since 3.7.0 |
| 136 | * |
| 137 | * @return array List of active plugins. |
| 138 | */ |
| 139 | private static function get_active_plugins() { |
| 140 | $active_plugins = get_option( 'active_plugins', array() ); |
| 141 | $plugins = array(); |
| 142 | |
| 143 | foreach ( $active_plugins as $plugin ) { |
| 144 | $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ); |
| 145 | $plugins[] = array( |
| 146 | 'name' => $plugin_data['Name'], |
| 147 | 'version' => $plugin_data['Version'], |
| 148 | 'author' => $plugin_data['Author'], |
| 149 | 'file' => $plugin, |
| 150 | ); |
| 151 | } |
| 152 | |
| 153 | return $plugins; |
| 154 | } |
| 155 | |
| 156 | /** |
| 157 | * Gets TinyPNG plugin info & settings. |
| 158 | * |
| 159 | * @since 3.7.0 |
| 160 | * |
| 161 | * @return array Plugin settings |
| 162 | */ |
| 163 | private function get_tiny_info() { |
| 164 | return array( |
| 165 | 'version' => Tiny_Plugin::version(), |
| 166 | 'status' => $this->settings->get_status(), |
| 167 | 'php_client_supported' => Tiny_PHP::client_supported(), |
| 168 | |
| 169 | 'compression_count' => $this->settings->get_compression_count(), |
| 170 | 'compression_timing' => $this->settings->get_compression_timing(), |
| 171 | 'conversion' => $this->settings->get_conversion_options(), |
| 172 | 'paying_state' => $this->settings->get_paying_state(), |
| 173 | ); |
| 174 | } |
| 175 | |
| 176 | public function download_diagnostics() { |
| 177 | check_ajax_referer( 'tiny-compress', 'security' ); |
| 178 | |
| 179 | if ( ! current_user_can( 'manage_options' ) ) { |
| 180 | wp_send_json_error( |
| 181 | esc_html__( 'Not allowed to download diagnostics.', 'tiny-compress-images' ), |
| 182 | 403 |
| 183 | ); |
| 184 | } |
| 185 | |
| 186 | $zippath = $this->create_diagnostic_zip(); |
| 187 | return $this->download_zip( $zippath ); |
| 188 | } |
| 189 | |
| 190 | /** |
| 191 | * Creates a diagnostic zip file. |
| 192 | * |
| 193 | * @since 3.7.0 |
| 194 | * |
| 195 | * @return string|WP_Error Path to the created zip file or WP_Error on failure. |
| 196 | */ |
| 197 | public function create_diagnostic_zip() { |
| 198 | if ( ! class_exists( 'ZipArchive' ) ) { |
| 199 | return new WP_Error( |
| 200 | 'zip_not_available', |
| 201 | __( |
| 202 | 'ZipArchive class is not available on this server.', |
| 203 | 'tiny-compress-images' |
| 204 | ) |
| 205 | ); |
| 206 | } |
| 207 | |
| 208 | $wp_filesystem = Tiny_Helpers::get_wp_filesystem(); |
| 209 | $temp_dir = trailingslashit( get_temp_dir() ) . 'tiny-compress-temp'; |
| 210 | if ( ! $wp_filesystem->exists( $temp_dir ) ) { |
| 211 | wp_mkdir_p( $temp_dir ); |
| 212 | } |
| 213 | |
| 214 | $temp_path = tempnam( $temp_dir, 'tiny-compress-diagnostics-' . gmdate( 'Y-m-d-His' ) ); |
| 215 | |
| 216 | $zip = new ZipArchive(); |
| 217 | if ( true !== $zip->open( $temp_path, ZipArchive::CREATE | ZipArchive::OVERWRITE ) ) { |
| 218 | return new WP_Error( |
| 219 | 'zip_create_failed', |
| 220 | __( |
| 221 | 'Failed to create zip file.', |
| 222 | 'tiny-compress-images' |
| 223 | ) |
| 224 | ); |
| 225 | } |
| 226 | |
| 227 | $info = self::collect_info(); |
| 228 | $zip->addFromString( 'tiny-diagnostics.json', wp_json_encode( $info, JSON_PRETTY_PRINT ) ); |
| 229 | |
| 230 | $logger = Tiny_Logger::get_instance(); |
| 231 | $log_files = $logger->get_log_files(); |
| 232 | |
| 233 | foreach ( $log_files as $log_file ) { |
| 234 | if ( $wp_filesystem->exists( $log_file ) ) { |
| 235 | $zip->addFile( $log_file, 'logs/' . basename( $log_file ) ); |
| 236 | } |
| 237 | } |
| 238 | |
| 239 | $zip->close(); |
| 240 | return $temp_path; |
| 241 | } |
| 242 | |
| 243 | /** |
| 244 | * Downloads and removes the zip |
| 245 | * |
| 246 | * @since 3.7.0 |
| 247 | * |
| 248 | * @param string $zip_path Path to the zip file. |
| 249 | */ |
| 250 | public static function download_zip( $zip_path ) { |
| 251 | $wp_filesystem = Tiny_Helpers::get_wp_filesystem(); |
| 252 | if ( ! $wp_filesystem->exists( $zip_path ) ) { |
| 253 | wp_die( esc_html__( 'Diagnostic file not found.', 'tiny-compress-images' ) ); |
| 254 | } |
| 255 | |
| 256 | header( 'Content-Type: application/zip' ); |
| 257 | header( 'Content-Disposition: attachment; filename="tiny-compress-diagnostics.zip"' ); |
| 258 | header( 'Content-Length: ' . $wp_filesystem->size( $zip_path ) ); |
| 259 | header( 'Pragma: no-cache' ); |
| 260 | header( 'Expires: 0' ); |
| 261 | |
| 262 | // phpcs:ignore WordPress.WP.AlternativeFunctions.file_system_operations_readfile |
| 263 | readfile( $zip_path ); |
| 264 | |
| 265 | // Clean up. |
| 266 | $wp_filesystem->delete( $zip_path ); |
| 267 | |
| 268 | exit; |
| 269 | } |
| 270 | } |
| 271 |