run
* 4. In wp-admin/includes/class-wp-automatic-updater.php $this->run() checks to make sure we're on the main site if on a network,
* and also if the autoupdates are disabled (by plugin, by being on a version controlled site, etc )
* 5. In wp-admin/includes/class-wp-automatic-updater.php $this->run() then checks to see which plugins have new versions (version/update check)
* 6. In wp-admin/includes/class-wp-automatic-updater.php $this->run() then calls $this->update() for each plugin installed who has an upgrade.
* 7. In wp-admin/includes/class-wp-automatic-updater.php $this->update() double checks filesystem access and then installs the plugin if able
*
* Notes:
* - This autoupdater only works if WordPress core detects no version control. If you want to test this, do it on a new WP site without any .git folders anywhere.
* - This autoupdater only works if the file access is able to be written to
* - This autoupdater only works if a new version has been detected, and will run not the second the update is released,
* but whenever the cron for wp_version_check is next released. This is generally run every 8-12 hours.
* - However, that cron can be disabled, the autoupdater can be turned off via constant or filter, version control or file lock can be detected,
* and other plugins can be installed (incl in functions of theme) that turn off all automatic plugin updates.
* - If you want to test this is working, you have to manually run the wp_version_check cron. Install the WP Crontrol plugin or Core Control plugin, and run the cron manually using it.
* - Again, because you skimmed over it the first time, if you want to test this manually you need to test this on a new WP install without version control for core,
* plugins, etc, without file lock, with license key entered (for pro only)
* and use the WP Crontrol or Core Control plugin to run wp_version_check
* - You may have to manually remove an option called "auto_updater.lock" from the WP options table
* - You may need to run wp_version_check multiple times (note though that they must be spaced at least 60 seconds apart)
* - Because WP's updater asks the OS if the file is writable, make sure you do not have any files/folders for the plugin you are trying to autoupdate open when testing.
* - You may need to delete the plugin info transient to get it to hard refresh the plugin info.
*
* @since 4.0.12
*/
class AutoUpdates {
use \AIOSEO\Plugin\Pro\Traits\Updates;
/**
* Class constructor.
*
* @since 4.0.12
*/
public function __construct() {
add_filter( 'auto_update_plugin', [ $this, 'automaticUpdates' ], 10, 2 );
add_filter( 'plugin_auto_update_setting_html', [ $this, 'filterWordPressAutoUpdateSetting' ], 10, 3 );
if ( wp_doing_cron() ) {
add_filter( 'upgrader_package_options', [ $this, 'validateDownloadUrl' ] );
}
}
/**
* Filters the auto update plugin routine to allow All in One SEO to be automatically updated.
*
* @since 4.0.12
*
* @param bool $update Flag to update the plugin or not.
* @param object $item Update data about a specific plugin.
* @return bool The new update state.
*/
public function automaticUpdates( $update, $item = null ) {
$item = (array) $item;
if ( empty( $item['plugin'] ) ) {
return $update;
}
$pluginInfo = get_site_transient( 'update_plugins' );
$response = ! empty( $pluginInfo->response ) ? $pluginInfo->response : [];
$noUpdate = ! empty( $pluginInfo->no_update ) ? $pluginInfo->no_update : [];
$plugin = isset( $item['plugin'] ) && isset( $response[ $item['plugin'] ] )
? (array) $response[ $item['plugin'] ]
: (
isset( $noUpdate[ $item['plugin'] ] )
? (array) $noUpdate[ $item['plugin'] ]
: null
);
if ( empty( $plugin ) ) {
return $update;
}
$isFree = 'all-in-one-seo-pack' === $item['slug'];
$isPaid = isset( $plugin['aioseo'] ); // see updater class
$isAddon = $this->isPluginOurAddon( $item['plugin'] );
$automaticUpdatesEnabled = aioseo()->options->advanced->autoUpdates;
// When used in the context of Plugins page.
$screen = aioseo()->helpers->getCurrentScreen();
if ( ! empty( $screen->id ) && in_array( $screen->id, [ 'plugins', 'plugins-network' ], true ) ) {
$isPro = aioseo()->pro;
$isMainPro = $isPro && plugin_basename( AIOSEO_FILE ) === $item['plugin'];
if (
$isFree ||
$isMainPro ||
( $isAddon && $isPro )
) {
return in_array( $automaticUpdatesEnabled, [ 'all', 'minor' ], true );
}
if ( $isAddon && ! $isPro ) {
return false;
}
}
// If this is multisite and is not on the main site, return early.
if ( is_multisite() && ! is_main_site() ) {
return $update;
}
// If we don't have everything we need, return early.
if ( ! isset( $item['new_version'] ) || ! isset( $item['slug'] ) ) {
return $update;
}
// If the plugin isn't ours, return early.
if ( ! $isFree && ! $isPaid || ( $isFree && ! defined( 'AIOSEO_VERSION' ) ) ) {
return $update;
}
switch ( $automaticUpdatesEnabled ) {
case 'all':
return true;
case 'none':
return false;
case 'minor':
$version = $isFree ? AIOSEO_VERSION : $plugin['oldVersion'];
// If the major version is different, we don't want to update.
$currentMajor = $this->getMajorVersion( $version );
$newMajor = $this->getMajorVersion( $plugin['new_version'] );
if ( $currentMajor !== $newMajor ) {
return false;
}
$currentMinor = $this->getMinorVersion( $version );
$newMinor = $this->getMinorVersion( $plugin['new_version'] );
return version_compare( $newMinor, $currentMinor, '>' );
default:
return $update;
}
}
/**
* Add Manage Auto-updates link for All in One SEO Pro and its add-ons on Plugins page
*
* @since 4.0.12
*
* @param string $html
* @param string $pluginFile
* @return string
*/
public function filterWordPressAutoUpdateSetting( $html, $pluginFile = '', $pluginData = [] ) {
if (
// Don't show the link for addons to prevent clutter.
empty( $pluginData['slug'] ) &&
( empty( $pluginData['TextDomain'] ) || ! in_array( $pluginData['TextDomain'], [ 'aioseo-pro', 'all-in-one-seo-pack' ], true ) )
) {
return $html;
}
$isPro = aioseo()->pro;
$isAddon = $this->isPluginOurAddon( $pluginFile );
$isMainPro = $isPro && plugin_basename( AIOSEO_FILE ) === $pluginFile;
$hasPermission = current_user_can( aioseo()->admin->getPageRequiredCapability( 'aioseo-settings' ) );
if ( $isAddon && ! $isPro ) {
$html = sprintf(
'%s',
aioseo()->helpers->utmUrl( AIOSEO_MARKETING_URL . 'docs/how-to-upgrade-from-all-in-one-seo-lite-to-pro', 'plugins-autoupdate', 'upgrade-to-autoupdate' ),
sprintf(
// Translators: 1 - "AIOSEO Pro"
__( 'Enable the %1$s plugin to manage auto-updates', 'aioseo-pro' ),
'AIOSEO Pro'
)
);
add_filter( "aioseo_is_autoupdate_setting_html_filtered_$pluginFile", '__return_true' );
} elseif ( $hasPermission &&
( $isMainPro || ( $isAddon && $isPro ) )
) {
$text = __( 'Manage auto-updates', 'aioseo-pro' );
$html .= '
' . sprintf( '%s', admin_url( 'admin.php?page=aioseo-settings#/advanced' ), $text );
add_filter( "aioseo_is_autoupdate_setting_html_filtered_$pluginFile", '__return_true' );
}
return $html;
}
/**
* Checks if the plugin is one of ours.
*
* @since 4.0.12
*
* @param string $pluginFile The plugin file to check against.
* @return bool True if it is, false if not.
*/
private function isPluginOurAddon( $pluginFile ) {
$addons = aioseo()->addons->getAddons();
if ( ! is_array( $addons ) ) {
return false;
}
foreach ( $addons as $addon ) {
if ( $pluginFile === $addon->basename ) {
return true;
}
}
return false;
}
/**
* Splits out a version number and returns the minor version portion.
*
* @since 4.7.5
*
* @param string $version The version to check.
* @return string The minor version portion of the version.
*/
private function getMajorVersion( $version ) {
return $this->getVersionHelper( $version, 3 );
}
/**
* Splits out a version number and returns the minor version portion.
*
* @since 4.7.5
*
* @param string $version The version to check.
* @return string The minor version portion of the version.
*/
private function getMinorVersion( $version ) {
return $this->getVersionHelper( $version, 4 );
}
/**
* Returns the version number with the specified number of decimal positions.
*
* @since 4.7.5
*
* @param string $version The version number.
* @param string $decimalPositions The number of decimal positions to return.
* @return string The version number with the specified number of decimal positions.
*/
private function getVersionHelper( $version, $decimalPositions ) {
$versionPositions = explode( '.', $version );
$versionPositions = array_pad( $versionPositions, $decimalPositions, '0' );
return implode( '.', array_slice( $versionPositions, 0, $decimalPositions ) );
}
}