diff --git a/admin/class-boldgrid-backup-admin-auto-updates-logger.php b/admin/class-boldgrid-backup-admin-auto-updates-logger.php new file mode 100644 index 00000000..edff07c6 --- /dev/null +++ b/admin/class-boldgrid-backup-admin-auto-updates-logger.php @@ -0,0 +1,217 @@ + + */ + +/** + * Class: Boldgrid_Backup_Admin_Auto_Updates_Logger + * + * @since 1.8.0 + */ +class Boldgrid_Backup_Admin_Auto_Updates_Logger { + /** + * Core object. + * + * @var Boldgrid_Backup_Core + * @since 1.8.0 + */ + public $core; + + /** + * Log object. + * + * @var Boldgrid_Backup_Admin_Log + * @since 1.8.0 + */ + public $auto_update_log; + + /** + * Settings. + * + * @var array + */ + public $settings; + + /** + * Constructor. + * + * @since 1.8.0 + */ + public function __construct() { + $this->core = apply_filters( 'boldgrid_backup_get_core', null ); + $this->settings = $this->core->settings->get_setting( 'auto_update' ); + + // Hook into WordPress initialization to detect auto-updates. + add_action( 'init', array( $this, 'detect_auto_update' ) ); + + // Hook into WordPress update process to log update information. + add_action( 'upgrader_process_complete', array( $this, 'upgrade_complete' ), 10, 2 ); + } + + /** + * Get Days. + * + * @return int + */ + public function get_days() { + if ( empty( $this->settings['timely-updates-enabled'] ) || empty( $this->settings['days'] ) ) { + return 0; + } else { + return $this->settings['days']; + } + } + + /** + * Callback function to detect when WordPress auto-update process starts. + */ + public function detect_auto_update() { + if ( defined( 'DOING_CRON' ) && DOING_CRON && false !== strpos( $_SERVER['REQUEST_URI'], '/wp-cron.php' ) ) { + // Timely auto updates enabled. + $timely_auto_updates = empty( $this->settings['timely-updates-enabled'] ) ? 'No' : 'Yes'; + // Today's date. + $today = date( 'Y-m-d' ); + // Days to delay the update. + $days_delay = $this->get_days(); + + $this->auto_update_log = new Boldgrid_Backup_Admin_Log( $this->core ); + $this->auto_update_log->init( 'auto-update.log' ); + $this->auto_update_log->add( '--- Running Auto Updates ---' ); + $this->auto_update_log->add( 'Timely Updates Enabled: ' . $timely_auto_updates ); + + $core_enabled = false; + + foreach ( $this->settings['wpcore'] as $core ) { + if ( ! empty( $core ) ) { + $core_enabled = true; + } + } + + // Check for core updates. + if ( $core_enabled ) { + $core_update = get_site_transient( 'update_core' ); + + if ( isset( $core_update->updates ) && is_array( $core_update->updates ) ) { + foreach ( $core_update->updates as $update ) { + if ( $update->current !== $update->version ) { + $core_msg = sprintf( + 'WordPress Core Update Available from version %s to %s.', + $update->current, + $update->version + ); + + $this->auto_update_log->add( $core_msg ); + } else { + $this->auto_update_log->add( 'WordPress Core is up to date.' ); + } + } + } + } + + // Check for plugin updates. + $plugin_updates = get_site_transient( 'update_plugins' ); + + if ( isset( $plugin_updates->response ) && is_array( $plugin_updates->response ) ) { + foreach ( $plugin_updates->response as $plugin_file => $update ) { + if ( ! empty( $this->settings['plugins'][ $plugin_file ] ) ) { + $plugin_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $plugin_file ); + $plugin_slug = dirname( plugin_basename( WP_PLUGIN_DIR . '/' . $plugin_file ) ); + $plugin_name = $plugin_data['Name']; + $plugin_current_version = $plugin_data['Version']; + $remote_plugin_data = wp_remote_get( 'https://api.wordpress.org/plugins/info/1.0/' . $plugin_slug . '.json' ); + + if ( ! is_wp_error( $remote_plugin_data ) ) { + $plugin_json = json_decode( $remote_plugin_data['body'] ); + $plugin_new_version = $plugin_json->version; + $plugin_release_date = date( 'Y-m-d', strtotime( $plugin_json->last_updated ) ); + $days_since_plugin_release = abs( strtotime( $today ) - strtotime( $plugin_release_date ) ) / 86400; + $allow_update_msg = 'Yes' === $timely_auto_updates && $days_since_plugin_release < $days_delay ? 'This plugin will be updated.' : 'This plugin will not be updated.'; + + $plugin_msg = sprintf( + 'Plugin Update Available: %s from version %s to %s released on %s. Days since release: %s. Timely auto updates set to %s days after release. %s', + $plugin_name, + $plugin_current_version, + $plugin_new_version, + $plugin_release_date, + $days_since_plugin_release, + $days_delay, + $allow_update_msg + ); + + $this->auto_update_log->add( $plugin_msg ); + } + } + } + } else { + $this->auto_update_log->add( 'All plugins are up to date.' ); + } + + // Check for theme updates. + $theme_updates = get_site_transient( 'update_themes' ); + + if ( isset( $theme_updates->response ) && is_array( $theme_updates->response ) ) { + foreach ( $theme_updates->response as $theme_slug => $update ) { + if ( ! empty( $this->settings['themes'][ $theme_slug ] ) ) { + $theme_data = wp_get_theme( $theme_slug ); + $theme_name = $theme_data->get( 'Name' ); + $theme_current_version = $theme_data->get( 'Version' ); + $remote_theme_data = wp_remote_get( 'https://api.wordpress.org/themes/info/1.2/?action=theme_information&slug=' . $theme_slug ); + + if ( ! is_wp_error( $remote_theme_data ) ) { + $theme_json = json_decode( $remote_theme_data['body'] ); + $theme_new_version = $theme_json->version; + $theme_release_date = date( 'Y-m-d', strtotime( $theme_json->last_updated ) ); + $days_since_theme_release = abs( strtotime( $today ) - strtotime( $theme_release_date ) ) / 86400; + $allow_update_msg = 'Yes' === $timely_auto_updates && $days_since_theme_release < $days_delay ? 'This theme will be updated.' : 'This theme will not be updated.'; + $theme_msg = sprintf( + 'Theme Update Available: %s from version %s to %s released on %s. Days since release: %s. Timely auto updates set to %s days after release. %s', + $theme_name, + $theme_current_version, + $theme_new_version, + $theme_release_date, + $days_since_theme_release, + $days_delay, + $allow_update_msg + ); + + $this->auto_update_log->add( $theme_msg ); + } + } + } + } else { + $this->auto_update_log->add( 'All themes are up to date.' ); + } + } + } + + /** + * Log update information. + * + * @param WP_Upgrader $upgrader_object + * @param array $options + */ + public function upgrade_complete( $upgrader_object, $options ) { + $this->auto_update_log = new Boldgrid_Backup_Admin_Log( $this->core ); + $this->auto_update_log->init( 'auto-update.log' ); + + if ( isset( $options['action'] ) && 'update' === $options['action'] ) { + $type = isset( $options['type'] ) ? $options['type'] : 'WP Core'; + $update_item = ! empty( $options['temp_backup'] ) ? implode( ', ', $options['temp_backup'] ) : ''; + + $log_message = sprintf( + 'Automatic %s update for %s complete.', + $type, + $update_item + ); + + $this->auto_update_log->add( $log_message ); + } + } +} diff --git a/admin/class-boldgrid-backup-admin-auto-updates.php b/admin/class-boldgrid-backup-admin-auto-updates.php index 718139b9..443e1264 100644 --- a/admin/class-boldgrid-backup-admin-auto-updates.php +++ b/admin/class-boldgrid-backup-admin-auto-updates.php @@ -52,15 +52,32 @@ class Boldgrid_Backup_Admin_Auto_Updates { */ public $core; + /** + * Auto Update Log. + * + * @since 1.14.0 + * @var string + */ + public $auto_update_log; + + /** + * Core Save Settings. + * + * @since 1.14.0 + * @var bool + */ + public $core_save_settings = false; + /** * Constructor. * * @since 1.14.0 */ public function __construct() { - $this->set_settings(); - add_filter( 'automatic_updater_disabled', '__return_false' ); + $this->core = apply_filters( 'boldgrid_backup_get_core', null ); + + $this->set_settings(); } /** @@ -86,24 +103,63 @@ public function __construct() { * @param string $option Name of option being updated. */ public function wordpress_option_updated( $old_value, $new_value, $option ) { - // Determines if this is being fired for a theme or plugin update - $update_type = 'auto_update_plugins' === $option ? 'plugins' : 'themes'; - $core = apply_filters( 'boldgrid_backup_get_core', null ); - $settings = $core->settings->get_settings(); + // Determines if this is being fired for a theme or plugin update. + $this->auto_update_log = new Boldgrid_Backup_Admin_Log( $this->core ); + $this->auto_update_log->init( 'auto-update.log' ); + $update_type = 'auto_update_plugins' === $option ? 'plugins' : 'themes'; + $this->settings = $this->core->settings->get_settings(); + $wpcs = isset( $this->settings['auto_update']['wpcore'] ) ? $this->settings['auto_update']['wpcore'] : []; + + // Log the Core auto update settings only once. + if ( false === $this->core_save_settings ) { + $this->auto_update_log->add( '--------------------------------------------------' ); + $this->auto_update_log->add( 'WP Core auto update settings' ); + + if ( ! empty( $wpcs['all'] ) ) { + $this->auto_update_log->add( 'WP Core Updates are set to auto update all.' ); + } + $dev = ( ! empty( $wpcs['dev'] ) ) ? 'true' : 'false'; + $this->auto_update_log->add( 'Setting WP Core Dev Updates to ' . $dev . '.' ); + $major = ( ! empty( $wpcs['major'] ) ) ? 'true' : 'false'; + $this->auto_update_log->add( 'Setting WP Core Major Updates to ' . $major . '.' ); + $minor = ( ! empty( $wpcs['minor'] ) ) ? 'true' : 'false'; + $this->auto_update_log->add( 'Setting WP Core Minor Updates to ' . $minor . '.' ); + $translation = ( ! empty( $wpcs['translation'] ) ) ? 'true' : 'false'; + $this->auto_update_log->add( 'Setting WP Core Translation Updates to ' . $translation . '.' ); + $this->auto_update_log->add( '--------------------------------------------------' ); + + $this->core_save_settings = true; + } // The plugins / themes listed in $new_value will only be those that have auto updates enabled. $enabled_offers = $new_value; - foreach ( $settings['auto_update'][ $update_type ] as $offer => $enabled ) { + + $this->auto_update_log->add( 'WP ' . $update_type . ' auto update settings.' ); + + foreach ( $this->settings['auto_update'][ $update_type ] as $offer => $enabled ) { // Do not modify the 'default' setting. This is used to define the default for new themes / plugins. if ( 'default' === $offer ) { continue; } + + if ( 'plugins' === $update_type ) { + $item_data = get_plugin_data( WP_PLUGIN_DIR . '/' . $offer ); + $item_name = $item_data['Name']; + } else { + $item_name = $offer; + } + + // Log the plugin / theme auto update settings. + $this->auto_update_log->add( 'Setting ' . $update_type . ' ' . $item_name . ' to ' . ( in_array( $offer, $enabled_offers, true ) ? 'enabled' : 'disabled' ) . '.' ); + // If the theme / plugin is found in the $enabled_offers array, enable in our settings, otherwise disable. - $settings['auto_update'][ $update_type ][ $offer ] = in_array( $offer, $enabled_offers, true ) ? '1' : '0'; + $this->settings['auto_update'][ $update_type ][ $offer ] = in_array( $offer, $enabled_offers, true ) ? '1' : '0'; } + $this->auto_update_log->add( '--------------------------------------------------' ); + // Save the settings. - $core->settings->save( $settings ); + $this->core->settings->save( $this->settings ); } /** @@ -112,8 +168,7 @@ public function wordpress_option_updated( $old_value, $new_value, $option ) { * @since 1.14.0 */ public function set_settings() { - $core = apply_filters( 'boldgrid_backup_get_core', null ); - $this->settings = $core->settings->get_setting( 'auto_update' ); + $this->settings = $this->core->settings->get_setting( 'auto_update' ); } /** @@ -214,6 +269,7 @@ public function auto_update_plugins( $update, $item ) { $plugins[] = $plugin->getSlug(); } } + if ( in_array( $item->slug, $plugins, true ) ) { // Always update plugins in this array. return true; diff --git a/admin/class-boldgrid-backup-admin-core.php b/admin/class-boldgrid-backup-admin-core.php index df5572fb..3c4de869 100644 --- a/admin/class-boldgrid-backup-admin-core.php +++ b/admin/class-boldgrid-backup-admin-core.php @@ -747,6 +747,7 @@ public function __construct() { if ( Boldgrid_Backup_Admin_Utility::is_active() ) { $this->auto_updates = new Boldgrid_Backup_Admin_Auto_Updates(); + new Boldgrid_Backup_Admin_Auto_Updates_Logger(); } // Ensure there is a backup identifier. diff --git a/includes/class-boldgrid-backup.php b/includes/class-boldgrid-backup.php index 77053317..e2cb5b78 100644 --- a/includes/class-boldgrid-backup.php +++ b/includes/class-boldgrid-backup.php @@ -126,8 +126,8 @@ private function load_dependencies() { * The class responsible for the admin notices for the plugin. */ require_once BOLDGRID_BACKUP_PATH . '/admin/class-boldgrid-backup-admin-notice.php'; - require_once BOLDGRID_BACKUP_PATH . '/admin/class-boldgrid-backup-admin-auto-updates.php'; + require_once BOLDGRID_BACKUP_PATH . '/admin/class-boldgrid-backup-admin-auto-updates-logger.php'; /** * The class responsible for the cron functionality in the admin area.