db-upgrades-manager.php (6032B)
1 <?php 2 3 namespace Elementor\Core\Base; 4 5 use Elementor\Core\Admin\Admin_Notices; 6 use Elementor\Plugin; 7 8 if ( ! defined( 'ABSPATH' ) ) { 9 exit; // Exit if accessed directly 10 } 11 12 abstract class DB_Upgrades_Manager extends Background_Task_Manager { 13 protected $current_version = null; 14 protected $query_limit = 100; 15 16 abstract public function get_new_version(); 17 abstract public function get_version_option_name(); 18 abstract public function get_upgrades_class(); 19 abstract public function get_updater_label(); 20 21 public function get_task_runner_class() { 22 return 'Elementor\Core\Upgrade\Updater'; 23 } 24 25 public function get_query_limit() { 26 return $this->query_limit; 27 } 28 29 public function set_query_limit( $limit ) { 30 $this->query_limit = $limit; 31 } 32 33 public function get_current_version() { 34 if ( null === $this->current_version ) { 35 $this->current_version = get_option( $this->get_version_option_name() ); 36 } 37 38 return $this->current_version; 39 } 40 41 public function should_upgrade() { 42 $current_version = $this->get_current_version(); 43 44 // It's a new install. 45 if ( ! $current_version ) { 46 $this->update_db_version(); 47 return false; 48 } 49 50 return version_compare( $this->get_new_version(), $current_version, '>' ); 51 } 52 53 public function on_runner_start() { 54 parent::on_runner_start(); 55 56 if ( ! defined( 'IS_ELEMENTOR_UPGRADE' ) ) { 57 define( 'IS_ELEMENTOR_UPGRADE', true ); 58 } 59 } 60 61 public function on_runner_complete( $did_tasks = false ) { 62 $logger = Plugin::$instance->logger->get_logger(); 63 64 $logger->info( 'Elementor data updater process has been completed.', [ 65 'meta' => [ 66 'plugin' => $this->get_plugin_label(), 67 'from' => $this->current_version, 68 'to' => $this->get_new_version(), 69 ], 70 ] ); 71 72 Plugin::$instance->files_manager->clear_cache(); 73 74 $this->update_db_version(); 75 76 if ( $did_tasks ) { 77 $this->add_flag( 'completed' ); 78 } 79 } 80 81 public function admin_notice_start_upgrade() { 82 /** 83 * @var Admin_Notices $admin_notices 84 */ 85 $admin_notices = Plugin::$instance->admin->get_component( 'admin-notices' ); 86 87 $options = [ 88 'title' => $this->get_updater_label(), 89 'description' => esc_html__( 'Your site database needs to be updated to the latest version.', 'elementor' ), 90 'type' => 'error', 91 'icon' => false, 92 'button' => [ 93 'text' => esc_html__( 'Update Now', 'elementor' ), 94 'url' => $this->get_start_action_url(), 95 'class' => 'e-button e-button--cta', 96 ], 97 ]; 98 99 $admin_notices->print_admin_notice( $options ); 100 } 101 102 public function admin_notice_upgrade_is_running() { 103 /** 104 * @var Admin_Notices $admin_notices 105 */ 106 $admin_notices = Plugin::$instance->admin->get_component( 'admin-notices' ); 107 108 $options = [ 109 'title' => $this->get_updater_label(), 110 'description' => esc_html__( 'Database update process is running in the background. Taking a while?', 'elementor' ), 111 'type' => 'warning', 112 'icon' => false, 113 'button' => [ 114 'text' => esc_html__( 'Click here to run it now', 'elementor' ), 115 'url' => $this->get_continue_action_url(), 116 'class' => 'e-button e-button--primary', 117 ], 118 ]; 119 120 $admin_notices->print_admin_notice( $options ); 121 } 122 123 public function admin_notice_upgrade_is_completed() { 124 $this->delete_flag( 'completed' ); 125 126 $message = esc_html__( 'The database update process is now complete. Thank you for updating to the latest version!', 'elementor' ); 127 128 /** 129 * @var Admin_Notices $admin_notices 130 */ 131 $admin_notices = Plugin::$instance->admin->get_component( 'admin-notices' ); 132 133 $options = [ 134 'description' => '<b>' . $this->get_updater_label() . '</b> - ' . $message, 135 'type' => 'success', 136 'icon' => false, 137 ]; 138 139 $admin_notices->print_admin_notice( $options ); 140 } 141 142 /** 143 * @access protected 144 */ 145 protected function start_run() { 146 $updater = $this->get_task_runner(); 147 148 if ( $updater->is_running() ) { 149 return; 150 } 151 152 $upgrade_callbacks = $this->get_upgrade_callbacks(); 153 154 if ( empty( $upgrade_callbacks ) ) { 155 $this->on_runner_complete(); 156 return; 157 } 158 159 foreach ( $upgrade_callbacks as $callback ) { 160 $updater->push_to_queue( [ 161 'callback' => $callback, 162 ] ); 163 } 164 165 $updater->save()->dispatch(); 166 167 Plugin::$instance->logger->get_logger()->info( 'Elementor data updater process has been queued.', [ 168 'meta' => [ 169 'plugin' => $this->get_plugin_label(), 170 'from' => $this->current_version, 171 'to' => $this->get_new_version(), 172 ], 173 ] ); 174 } 175 176 protected function update_db_version() { 177 update_option( $this->get_version_option_name(), $this->get_new_version() ); 178 } 179 180 public function get_upgrade_callbacks() { 181 $prefix = '_v_'; 182 $upgrades_class = $this->get_upgrades_class(); 183 $upgrades_reflection = new \ReflectionClass( $upgrades_class ); 184 185 $callbacks = []; 186 187 foreach ( $upgrades_reflection->getMethods() as $method ) { 188 $method_name = $method->getName(); 189 190 if ( '_on_each_version' === $method_name ) { 191 $callbacks[] = [ $upgrades_class, $method_name ]; 192 continue; 193 } 194 195 if ( false === strpos( $method_name, $prefix ) ) { 196 continue; 197 } 198 199 if ( ! preg_match_all( "/$prefix(\d+_\d+_\d+)/", $method_name, $matches ) ) { 200 continue; 201 } 202 203 $method_version = str_replace( '_', '.', $matches[1][0] ); 204 205 if ( ! version_compare( $method_version, $this->current_version, '>' ) ) { 206 continue; 207 } 208 209 $callbacks[] = [ $upgrades_class, $method_name ]; 210 } 211 212 return $callbacks; 213 } 214 215 public function __construct() { 216 // If upgrade is completed - show the notice only for admins. 217 // Note: in this case `should_upgrade` returns false, because it's already upgraded. 218 if ( is_admin() && current_user_can( 'update_plugins' ) && $this->get_flag( 'completed' ) ) { 219 add_action( 'admin_notices', [ $this, 'admin_notice_upgrade_is_completed' ] ); 220 } 221 222 if ( ! $this->should_upgrade() ) { 223 return; 224 } 225 226 $updater = $this->get_task_runner(); 227 228 $this->start_run(); 229 230 if ( $updater->is_running() && current_user_can( 'update_plugins' ) ) { 231 add_action( 'admin_notices', [ $this, 'admin_notice_upgrade_is_running' ] ); 232 } 233 234 parent::__construct(); 235 } 236 }