Fixed a potential fatal error when the current PUC version is removed during an upgrade.

By default, PUC automatically checks for updates immediately after the user upgrades the plugin or theme. This can become a problem if the upgrade overwrites the PUC library with a different version. While checking for updates, PUC may attempt to autoload a class, which will trigger a fatal error if the class file was deleted during the upgrade.

Fixed by checking if the running PUC version still exists after the upgrade. If it doesn't, remove hooks and stop.
This commit is contained in:
Yahnis Elsts 2020-02-15 15:28:12 +02:00
parent 5cdadd0369
commit e3cc1c03c9
2 changed files with 34 additions and 2 deletions

View File

@ -87,6 +87,7 @@ if ( !class_exists('Puc_v4p9_Scheduler', false) ):
* Runs upon the WP action upgrader_process_complete.
*
* We look at the parameters to decide whether to call maybeCheckForUpdates() or not.
* We also check if the update checker has been removed by the update.
*
* @param WP_Upgrader $upgrader WP_Upgrader instance
* @param array $upgradeInfo extra information about the upgrade
@ -95,6 +96,15 @@ if ( !class_exists('Puc_v4p9_Scheduler', false) ):
/** @noinspection PhpUnusedParameterInspection */
$upgrader, $upgradeInfo
) {
//Cancel all further actions if the current version of PUC has been deleted or overwritten
//by a different version during the upgrade. If we try to do anything more in that situation,
//we could trigger a fatal error by trying to autoload a deleted class.
clearstatcache();
if ( !file_exists(__FILE__) ) {
$this->removeHooks();
$this->updateChecker->removeHooks();
return;
}
//Sanity check and limitation to relevant types.
if (
@ -136,7 +146,7 @@ if ( !class_exists('Puc_v4p9_Scheduler', false) ):
$this->maybeCheckForUpdates();
}
/**
* Check for updates if the configured check interval has already elapsed.
* Will use a shorter check interval on certain admin pages like "Dashboard -> Updates" or when doing cron.
@ -233,6 +243,24 @@ if ( !class_exists('Puc_v4p9_Scheduler', false) ):
public function getCronHookName() {
return $this->cronHook;
}
/**
* Remove most hooks added by the scheduler.
*/
public function removeHooks() {
remove_filter('cron_schedules', array($this, '_addCustomSchedule'));
remove_action('admin_init', array($this, 'maybeCheckForUpdates'));
remove_action('load-update-core.php', array($this, 'maybeCheckForUpdates'));
if ( $this->cronHook !== null ) {
remove_action($this->cronHook, array($this, 'maybeCheckForUpdates'));
}
if ( !empty($this->hourlyCheckHooks) ) {
foreach ($this->hourlyCheckHooks as $hook) {
remove_action($hook, array($this, 'maybeCheckForUpdates'));
}
}
}
}
endif;

View File

@ -151,7 +151,7 @@ if ( !class_exists('Puc_v4p9_UpdateChecker', false) ):
/**
* Remove hooks that were added by this update checker instance.
*/
protected function removeHooks() {
public function removeHooks() {
remove_filter('site_transient_' . $this->updateTransient, array($this,'injectUpdate'));
remove_filter('site_transient_' . $this->updateTransient, array($this, 'injectTranslationUpdates'));
remove_action(
@ -164,6 +164,10 @@ if ( !class_exists('Puc_v4p9_UpdateChecker', false) ):
remove_action('plugins_loaded', array($this, 'maybeInitDebugBar'));
remove_action('init', array($this, 'loadTextDomain'));
if ( $this->scheduler ) {
$this->scheduler->removeHooks();
}
}
/**