diff --git a/includes/admin/class-extensions-updater.php b/includes/admin/class-extensions-updater.php index 11d3aa40..4080279a 100644 --- a/includes/admin/class-extensions-updater.php +++ b/includes/admin/class-extensions-updater.php @@ -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', '' ); + } }