Automator_System_Report
Class System_Report
Source Source
File: src/core/lib/utilities/class-automator-system-report.php
class Automator_System_Report { /** * @var */ public static $instance; /** * @return Automator_System_Report */ public static function get_instance() { if ( null === self::$instance ) { self::$instance = new self(); } return self::$instance; } /** * @return array */ public function get() { return array( 'environment' => $this->get_environment_info(), 'database' => $this->get_database_info(), 'active_plugins' => $this->get_active_plugins(), 'inactive_plugins' => $this->get_inactive_plugins(), 'dropins_mu_plugins' => $this->get_dropins_mu_plugins(), 'theme' => $this->get_theme_info(), ); } /** * Add prefix to table. * * @param string $table Table name. * * @return string */ protected function add_db_table_prefix( $table ) { global $wpdb; return $wpdb->prefix . $table; } /** * Notation to numbers. * * This function transforms the php.ini notation for numbers (like '2M') to an integer. * * @param string $size Size value. * * @return int */ public function automator_string_to_num( $size ) { $l = substr( $size, - 1 ); $ret = (int) substr( $size, 0, - 1 ); switch ( strtoupper( $l ) ) { case 'P': $ret *= 1024; case 'T': $ret *= 1024; case 'G': $ret *= 1024; case 'M': $ret *= 1024; case 'K': $ret *= 1024; } return $ret; } /** * @param string[] $fields * * @return array */ public function get_environment_info( $fields = array( 'environment' ) ) { $enable_remote_post = $this->check_if_field_item_exists( 'environment', array( 'remote_post_successful', 'remote_post_response', ), $fields ); $enable_remote_get = $this->check_if_field_item_exists( 'environment', array( 'remote_get_successful', 'remote_get_response', ), $fields ); // Figure out cURL version, if installed. $curl_version = ''; if ( function_exists( 'curl_version' ) ) { $curl_version = curl_version(); $curl_version = $curl_version['version'] . ', ' . $curl_version['ssl_version']; } elseif ( extension_loaded( 'curl' ) ) { $curl_version = __( 'cURL installed but unable to retrieve version.', 'uncanny-automator' ); } // WP memory limit. $wp_memory_limit = $this->automator_string_to_num( WP_MEMORY_LIMIT ); if ( function_exists( 'memory_get_usage' ) ) { $wp_memory_limit = max( $wp_memory_limit, $this->automator_string_to_num( @ini_get( 'memory_limit' ) ) ); // phpcs:ignore WordPress.PHP.NoSilencedErrors.Discouraged } // Test POST requests. $post_response_successful = null; $post_response_code = null; if ( $enable_remote_post ) { $post_response_code = get_transient( 'automator_test_remote_post' ); if ( false === $post_response_code || is_wp_error( $post_response_code ) ) { $response = wp_safe_remote_post( 'https://www.automatorplugin.com/', array( 'timeout' => 10, 'user-agent' => 'Automator/' . AUTOMATOR_PLUGIN_VERSION, 'httpversion' => '1.1', 'body' => array( 'cmd' => '_notify-validate', ), ) ); if ( ! is_wp_error( $response ) ) { $post_response_code = $response['response']['code']; } set_transient( 'automator_test_remote_post', $post_response_code, HOUR_IN_SECONDS ); } $post_response_successful = ! is_wp_error( $post_response_code ) && $post_response_code >= 200 && $post_response_code < 300; } // Test GET requests. $get_response_successful = null; $get_response_code = null; if ( $enable_remote_get ) { $get_response_code = get_transient( 'automator_test_remote_get' ); if ( false === $get_response_code || is_wp_error( $get_response_code ) ) { $response = wp_safe_remote_get( 'https://www.automatorplugin.com/' ); if ( ! is_wp_error( $response ) ) { $get_response_code = $response['response']['code']; } set_transient( 'automator_test_remote_get', $get_response_code, HOUR_IN_SECONDS ); } $get_response_successful = ! is_wp_error( $get_response_code ) && $get_response_code >= 200 && $get_response_code < 300; } $database_version = $this->get_server_database_version(); $environment = array( 'home_url' => get_option( 'home' ), 'site_url' => get_option( 'siteurl' ), 'version' => AUTOMATOR_PLUGIN_VERSION, 'log_directory' => UA_DEBUG_LOGS_DIR, 'log_directory_writable' => is_writable( dirname( UA_DEBUG_LOGS_DIR . 'test.log' ) ), 'wp_version' => get_bloginfo( 'version' ), 'wp_multisite' => is_multisite(), 'wp_memory_limit' => $wp_memory_limit, 'wp_debug_mode' => ( defined( 'WP_DEBUG' ) && WP_DEBUG ), 'wp_cron' => ! ( defined( 'DISABLE_WP_CRON' ) && DISABLE_WP_CRON ), 'language' => get_locale(), 'external_object_cache' => wp_using_ext_object_cache(), 'server_info' => isset( $_SERVER['SERVER_SOFTWARE'] ) ? sanitize_text_field( wp_unslash( $_SERVER['SERVER_SOFTWARE'] ) ) : '', 'php_version' => phpversion(), 'php_post_max_size' => $this->automator_string_to_num( ini_get( 'post_max_size' ) ), 'php_max_execution_time' => (int) ini_get( 'max_execution_time' ), 'php_max_input_vars' => (int) ini_get( 'max_input_vars' ), 'curl_version' => $curl_version, 'max_upload_size' => wp_max_upload_size(), 'mysql_version' => $database_version['number'], 'mysql_version_string' => $database_version['string'], 'default_timezone' => date_default_timezone_get(), 'mbstring_enabled' => extension_loaded( 'mbstring' ), 'remote_post_successful' => $post_response_successful, 'remote_post_response' => is_wp_error( $post_response_code ) ? $post_response_code->get_error_message() : $post_response_code, 'remote_get_successful' => $get_response_successful, 'remote_get_response' => is_wp_error( $get_response_code ) ? $get_response_code->get_error_message() : $get_response_code, ); // Return all environment info. Described by JSON Schema. return $environment; } /** * @return array|string[] */ public function get_server_database_version() { global $wpdb; if ( empty( $wpdb->is_mysql ) ) { return array( 'string' => '', 'number' => '', ); } // phpcs:disable WordPress.DB.RestrictedFunctions, PHPCompatibility.Extensions.RemovedExtensions.mysql_DeprecatedRemoved if ( $wpdb->use_mysqli ) { $server_info = mysqli_get_server_info( $wpdb->dbh ); } else { $server_info = mysql_get_server_info( $wpdb->dbh ); } // phpcs:enable WordPress.DB.RestrictedFunctions, PHPCompatibility.Extensions.RemovedExtensions.mysql_DeprecatedRemoved return array( 'string' => $server_info, 'number' => preg_replace( '/([^\d.]+).*/', '', $server_info ), ); } /** * @param $section * @param $items * @param $fields * * @return bool */ private function check_if_field_item_exists( $section, $items, $fields ) { if ( ! in_array( $section, $fields, true ) ) { return false; } $exclude = array(); foreach ( $fields as $field ) { $values = explode( '.', $field ); if ( $section !== $values[0] || empty( $values[1] ) ) { continue; } $exclude[] = $values[1]; } return 0 <= count( array_intersect( $items, $exclude ) ); } /** * */ public function output_tables_info() { $missing_tables = Automator_DB::verify_base_tables(); if ( 0 === count( $missing_tables ) ) { return; } ?> <br> <strong style="color:#a00;"> <span class="dashicons dashicons-warning"></span> <?php echo esc_html( sprintf( // translators: Comma seperated list of missing tables. __( 'Missing base tables: %s. Some Automator functionality may not work as expected.', 'uncanny-automator' ), implode( ', ', $missing_tables ) ) ); ?> </strong> <?php } /** * @return array */ public function get_database_info() { global $wpdb; $tables = array(); $database_size = array(); // It is not possible to get the database name from some classes that replace wpdb (e.g., HyperDB) // and that is why this if condition is needed. if ( defined( 'DB_NAME' ) ) { $database_table_information = $wpdb->get_results( $wpdb->prepare( "SELECT table_name AS 'name', engine AS 'engine', round( ( data_length / 1024 / 1024 ), 2 ) 'data', round( ( index_length / 1024 / 1024 ), 2 ) 'index' FROM information_schema.TABLES WHERE table_schema = %s ORDER BY name ASC;", DB_NAME ) ); // Automator Core tables to check existence of. $core_tables = (object) apply_filters( 'automator_database_tables', (object) array( 'recipe' => 'uap_recipe_log', 'trigger' => 'uap_trigger_log', 'trigger_meta' => 'uap_trigger_log_meta', 'action' => 'uap_action_log', 'action_meta' => 'uap_action_log_meta', 'closure' => 'uap_closure_log', 'closure_meta' => 'uap_closure_log_meta', 'recipe_logs' => 'uap_recipe_logs_view', 'trigger_logs' => 'uap_trigger_logs_view', 'action_logs' => 'uap_action_logs_view', ) ); /** * Adding the prefix to the tables array, for backwards compatibility. * * If we changed the tables above to include the prefix, then any filters against that table could break. */ $core_tables = array_map( array( $this, 'add_db_table_prefix' ), (array) $core_tables ); /** * Organize Automator and non-Automator tables separately for display purposes later. * * To ensure we include all Automator tables, even if they do not exist, pre-populate the Automator array with all the tables. */ $tables = array( 'automator' => array_fill_keys( $core_tables, false ), 'other' => array(), ); $database_size = array( 'data' => 0, 'index' => 0, ); $site_tables_prefix = $wpdb->get_blog_prefix( get_current_blog_id() ); $global_tables = $wpdb->tables( 'global', true ); foreach ( $database_table_information as $table ) { // Only include tables matching the prefix of the current site, this is to prevent displaying all tables on a MS install not relating to the current. if ( is_multisite() && 0 !== strpos( $table->name, $site_tables_prefix ) && ! in_array( $table->name, $global_tables, true ) ) { continue; } $table_type = in_array( $table->name, $core_tables, true ) ? 'automator' : 'other'; $tables[ $table_type ][ $table->name ] = array( 'data' => $table->data, 'index' => $table->index, 'engine' => $table->engine, ); $database_size['data'] += $table->data; $database_size['index'] += $table->index; } } // Return all database info. Described by JSON Schema. return array( 'automator_database_version' => get_option( 'uap_database_version' ), 'automator_database_available_version' => AUTOMATOR_DATABASE_VERSION, 'automator_database_views_version' => get_option( 'uap_database_views_version' ), 'automator_database_available_view_version' => AUTOMATOR_DATABASE_VIEWS_VERSION, 'database_prefix' => $wpdb->prefix, 'database_tables' => $tables, 'database_size' => $database_size, ); } /** * @return array */ public function get_active_plugins() { require_once ABSPATH . 'wp-admin/includes/plugin.php'; if ( ! function_exists( 'get_plugin_data' ) ) { return array(); } $active_plugins = (array) get_option( 'active_plugins', array() ); if ( is_multisite() ) { $network_activated_plugins = array_keys( get_site_option( 'active_sitewide_plugins', array() ) ); $active_plugins = array_merge( $active_plugins, $network_activated_plugins ); } $active_plugins_data = array(); foreach ( $active_plugins as $plugin ) { $data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin ); $active_plugins_data[] = $this->format_plugin_data( $plugin, $data ); } return $active_plugins_data; } /** * Get a list of inplugins active on the site. * * @return array */ public function get_inactive_plugins() { require_once ABSPATH . 'wp-admin/includes/plugin.php'; if ( ! function_exists( 'get_plugins' ) ) { return array(); } $plugins = get_plugins(); $active_plugins = (array) get_option( 'active_plugins', array() ); if ( is_multisite() ) { $network_activated_plugins = array_keys( get_site_option( 'active_sitewide_plugins', array() ) ); $active_plugins = array_merge( $active_plugins, $network_activated_plugins ); } $plugins_data = array(); foreach ( $plugins as $plugin => $data ) { if ( in_array( $plugin, $active_plugins, true ) ) { continue; } $plugins_data[] = $this->format_plugin_data( $plugin, $data ); } return $plugins_data; } /** * Format plugin data, including data on updates, into a standard format. * * @param string $plugin Plugin directory/file. * @param array $data Plugin data from WP. * * @return array Formatted data. * @since 3.6.0 */ protected function format_plugin_data( $plugin, $data ) { require_once ABSPATH . 'wp-admin/includes/update.php'; if ( ! function_exists( 'get_plugin_updates' ) ) { return array(); } // Use WP API to lookup latest updates for plugins. Automator_Helper injects updates for premium plugins. if ( empty( $this->available_updates ) ) { $this->available_updates = get_plugin_updates(); } $version_latest = $data['Version']; // Find latest version. if ( isset( $this->available_updates[ $plugin ]->update->new_version ) ) { $version_latest = $this->available_updates[ $plugin ]->update->new_version; } return array( 'plugin' => $plugin, 'name' => $data['Name'], 'version' => $data['Version'], 'version_latest' => $version_latest, 'url' => $data['PluginURI'], 'author_name' => $data['AuthorName'], 'author_url' => esc_url_raw( $data['AuthorURI'] ), 'network_activated' => $data['Network'], ); } /** * Get a list of Dropins and MU plugins. * * @return array * @since 3.6.0 */ public function get_dropins_mu_plugins() { $dropins = get_dropins(); $plugins = array( 'dropins' => array(), 'mu_plugins' => array(), ); foreach ( $dropins as $key => $dropin ) { $plugins['dropins'][] = array( 'plugin' => $key, 'name' => $dropin['Name'], ); } $mu_plugins = get_mu_plugins(); foreach ( $mu_plugins as $plugin => $mu_plugin ) { $plugins['mu_plugins'][] = array( 'plugin' => $plugin, 'name' => $mu_plugin['Name'], 'version' => $mu_plugin['Version'], 'url' => $mu_plugin['PluginURI'], 'author_name' => $mu_plugin['AuthorName'], 'author_url' => esc_url_raw( $mu_plugin['AuthorURI'] ), ); } return $plugins; } /** * Get info on the current active theme, info on parent theme (if presnet) * and a list of template overrides. * * @return array */ public function get_theme_info() { $active_theme = wp_get_theme(); // Get parent theme info if this theme is a child theme, otherwise // pass empty info in the response. if ( is_child_theme() ) { $parent_theme = wp_get_theme( $active_theme->template ); $parent_theme_info = array( 'parent_name' => $parent_theme->name, 'parent_version' => $parent_theme->version, 'parent_author_url' => $parent_theme->{'Author URI'}, ); } else { $parent_theme_info = array( 'parent_name' => '', 'parent_version' => '', 'parent_author_url' => '', ); } $active_theme_info = array( 'name' => $active_theme->name, 'version' => $active_theme->version, 'author_url' => esc_url_raw( $active_theme->{'Author URI'} ), 'is_child_theme' => is_child_theme(), ); return array_merge( $active_theme_info, $parent_theme_info ); } /** * @param $plugins */ public function output_plugins_info( $plugins ) { foreach ( $plugins as $plugin ) { if ( ! empty( $plugin['name'] ) ) { // Link the plugin name to the plugin url if available. $plugin_name = esc_html( $plugin['name'] ); if ( ! empty( $plugin['url'] ) ) { $plugin_name = '<a href="' . esc_url( $plugin['url'] ) . '" aria-label="' . esc_attr__( 'Visit plugin homepage', 'uncanny-automator' ) . '" target="_blank">' . $plugin_name . '</a>'; } $version_string = $plugin['version']; $network_string = ''; ?> <tr> <td><?php echo wp_kses_post( $plugin_name ); ?></td> <td class="help"> </td> <td> <?php /* translators: %s: plugin author */ printf( esc_html__( 'by %s', 'uncanny-automator' ), esc_html( $plugin['author_name'] ) ); echo ' – ' . esc_html( $version_string ) . $network_string; // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped ?> </td> </tr> <?php } } } }
Expand full source code Collapse full source code View on Github
Methods Methods
- add_db_table_prefix — Add prefix to table.
- automator_string_to_num — Notation to numbers.
- check_if_field_item_exists
- format_plugin_data — Format plugin data, including data on updates, into a standard format.
- get
- get_active_plugins
- get_automator_stats
- get_database_info
- get_dropins_mu_plugins — Get a list of Dropins and MU plugins.
- get_environment_info
- get_inactive_plugins — Get a list of inplugins active on the site.
- get_instance
- get_server_database_version
- get_theme_info — Get info on the current active theme, info on parent theme (if presnet) and a list of template overrides.
- output_plugins_info
- output_tables_info