Add support for processing extension updates in batches

Introduced batch processing for extension updates with package start and complete hooks, preventing duplicate actions via transient flags. Added constants for configuration and helper methods to manage package version state effectively. Ensures smoother upgrade handling for Ultimate Member extensions.
This commit is contained in:
Mykyta Synelnikov
2025-10-31 01:26:42 +02:00
parent efc3227634
commit a25153e347
+115 -23
View File
@@ -10,6 +10,10 @@ if ( ! defined( 'ABSPATH' ) ) {
*/
class Extensions_Updater {
const EXTRA_TIME = 30;
const PAGINATION = 50;
/**
* @var array
*/
@@ -33,41 +37,104 @@ class Extensions_Updater {
);
add_action( 'admin_init', array( $this, 'maybe_run_updater' ) );
add_action( 'um_' . $this->updater_data['slug'] . '_package_start', array( $this, 'package_start' ), 10, 4 );
add_action( 'um_' . $this->updater_data['slug'] . '_package_complete', array( $this, 'package_complete' ) );
}
public function package_start( $version, $file_path, $delay, $per_page ) {
$hook = 'um_' . $this->updater_data['slug'] . '_package_complete';
include_once $file_path;
/**
* IMPORTANT!!!: Last action that we need to do after package is complete.
* `UM()->maybe_action_scheduler()->schedule_single_action(
* time() + 1,
* $hook,
* array(
* 'version' => $version,
* )
* );`
*/
}
public function package_complete( $version ) {
$this->set_last_version_upgrade( $version );
$this->reset_in_process_package_version();
}
/**
* Maybe run upgrade if needed.
*/
public function maybe_run_updater() {
$last_version_upgrade = $this->get_last_version_upgrade();
if ( ! empty( $last_version_upgrade ) && version_compare( $last_version_upgrade, $this->updater_data['version'], '>=' ) ) {
// Don't need update.
// Cold start to avoid scheduled actions duplicates. Don't remove it.
$init = get_transient( 'um_' . $this->updater_data['slug'] . '_updater_init' );
if ( ! empty( $init ) ) {
return;
}
set_transient( 'um_' . $this->updater_data['slug'] . '_updater_init', true, 10 );
$next_package = $this->get_next_package();
if ( empty( $next_package ) ) {
$this->set_last_version_upgrade( $this->updater_data['version'] );
$this->reset_in_process_package_version();
return;
}
$packages = $this->get_packages();
if ( ! empty( $packages ) ) {
$packages_dir = $this->get_packages_dir();
foreach ( $packages as $package_version ) {
if ( version_compare( $package_version, $last_version_upgrade, '<=' ) ) {
continue;
}
list( $package_version, $file_path ) = $next_package;
if ( version_compare( $package_version, $this->updater_data['version'], '>' ) ) {
continue;
}
$file_path = $packages_dir . $package_version . '.php';
if ( ! file_exists( $file_path ) ) {
continue;
}
include_once $file_path;
$this->set_last_version_upgrade( $package_version );
}
$in_process_package = $this->get_in_process_package_version();
if ( ! empty( $in_process_package ) && version_compare( $in_process_package, $package_version, '=' ) ) {
return;
}
$this->set_last_version_upgrade( $this->updater_data['version'] );
// Initialize start package action.
$action_id = UM()->maybe_action_scheduler()->schedule_single_action(
time() + self::EXTRA_TIME,
'um_' . $this->updater_data['slug'] . '_package_start',
array(
'version' => $package_version,
'path' => $file_path,
'delay' => self::EXTRA_TIME,
'per_page' => self::PAGINATION,
)
);
// As soon as scheduler single action is created - then set in progress package version to avoid duplicates of the package start action.
if ( ! empty( $action_id ) ) {
$this->set_in_process_package_version( $package_version );
}
}
private function get_next_package() {
$last_version_upgrade = $this->get_last_version_upgrade();
if ( ! empty( $last_version_upgrade ) && version_compare( $last_version_upgrade, $this->updater_data['version'], '>=' ) ) {
return null;
}
$packages = $this->get_packages();
if ( empty( $packages ) ) {
return null;
}
$packages_dir = $this->get_packages_dir();
foreach ( $packages as $package_version ) {
if ( version_compare( $package_version, $last_version_upgrade, '<=' ) ) {
continue;
}
if ( version_compare( $package_version, $this->updater_data['version'], '>' ) ) {
continue;
}
$file_path = $packages_dir . $package_version . '.php';
if ( ! file_exists( $file_path ) ) {
continue;
}
return array( $package_version, $file_path );
}
return null;
}
/**
@@ -121,4 +188,29 @@ class Extensions_Updater {
private function set_last_version_upgrade( $version ) {
update_option( 'um_' . $this->updater_data['slug'] . '_last_version_upgrade', $version );
}
/**
* Gets the last version upgrade from options.
*
* @return string The last version upgrade.
*/
private function get_in_process_package_version() {
return get_option( 'um_' . $this->updater_data['slug'] . '_in_process_package_upgrade', '' );
}
/**
* Set the last version upgrade for the updater.
*
* @param string $version The version to set as the last upgrade version.
*/
private function set_in_process_package_version( $version ) {
update_option( 'um_' . $this->updater_data['slug'] . '_in_process_package_upgrade', $version );
}
/**
* Set the last version upgrade for the updater.
*/
private function reset_in_process_package_version() {
update_option( 'um_' . $this->updater_data['slug'] . '_in_process_package_upgrade', '' );
}
}