ui.php
418 lines
| 1 | <?php |
| 2 | namespace Crocoblock\Blocks_Style\Migrator; |
| 3 | |
| 4 | if ( ! defined( 'ABSPATH' ) ) { |
| 5 | exit; // Exit if accessed directly. |
| 6 | } |
| 7 | |
| 8 | class UI { |
| 9 | |
| 10 | protected $page_slug = 'jet_sm_migration'; |
| 11 | protected $migrator_dir; |
| 12 | |
| 13 | public function __construct() { |
| 14 | |
| 15 | // Do nothing if Style Manager plugin is not active |
| 16 | if ( ! class_exists( '\JET_SM\Gutenberg\Block_Manager' ) |
| 17 | || ! is_admin() |
| 18 | ) { |
| 19 | return; |
| 20 | } |
| 21 | |
| 22 | $this->migrator_dir = plugin_dir_path( __FILE__ ); |
| 23 | |
| 24 | // Add admin notice about migration |
| 25 | add_action( 'admin_notices', [ $this, 'migration_notice' ] ); |
| 26 | // Add admin menu for migration |
| 27 | add_action( 'admin_menu', [ $this, 'add_migration_page' ] ); |
| 28 | add_action( 'admin_init', [ $this, 'process_migration' ] ); |
| 29 | add_action( 'admin_init', [ $this, 'process_cleanup' ] ); |
| 30 | add_action( 'admin_init', [ $this, 'process_rollback' ] ); |
| 31 | } |
| 32 | |
| 33 | /** |
| 34 | * Process rollback to legacy JetStyleManager |
| 35 | */ |
| 36 | public function process_rollback() { |
| 37 | |
| 38 | if ( ! isset( $_GET['rollback'] ) || ! current_user_can( 'manage_options' ) ) { |
| 39 | return; |
| 40 | } |
| 41 | |
| 42 | if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], $this->page_slug ) ) { |
| 43 | wp_send_json_error( esc_html__( 'The link is expired. Please reload the page and try again.', 'jet-engine' ) ); |
| 44 | } |
| 45 | |
| 46 | delete_option( 'jet_sm_migration_completed' ); |
| 47 | } |
| 48 | |
| 49 | /** |
| 50 | * Process cleanup of legacy data after migration |
| 51 | */ |
| 52 | public function process_cleanup() { |
| 53 | |
| 54 | if ( ! isset( $_GET['clean_up_migration'] ) || ! current_user_can( 'manage_options' ) ) { |
| 55 | return; |
| 56 | } |
| 57 | |
| 58 | if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], $this->page_slug ) ) { |
| 59 | wp_send_json_error( esc_html__( 'The link is expired. Please reload the page and try again.', 'jet-engine' ) ); |
| 60 | } |
| 61 | |
| 62 | $migrated = get_option( 'jet_sm_migration_completed', false ); |
| 63 | |
| 64 | if ( ! $migrated || 2 == (int) $migrated ) { |
| 65 | wp_send_json_error( esc_html__( 'Migration process is not completed or already cleaned up.', 'jet-engine' ) ); |
| 66 | } |
| 67 | |
| 68 | $clear_meta_keys = [ |
| 69 | '_jet_sm_ready_style', |
| 70 | '_jet_sm_style', |
| 71 | '_jet_sm_controls_values', |
| 72 | '_jet_sm_fonts_collection', |
| 73 | '_jet_sm_fonts_links', |
| 74 | ]; |
| 75 | |
| 76 | global $wpdb; |
| 77 | |
| 78 | foreach ( $clear_meta_keys as $meta_key ) { |
| 79 | $wpdb->query( $wpdb->prepare( |
| 80 | "DELETE FROM {$wpdb->postmeta} WHERE meta_key = %s", |
| 81 | $meta_key |
| 82 | ) ); |
| 83 | } |
| 84 | |
| 85 | update_option( 'jet_sm_migration_completed', 2 ); |
| 86 | |
| 87 | wp_send_json_success( [ |
| 88 | 'message' => esc_html__( 'Legacy data cleaned up successfully. You can now deactivate the JetStyleManager plugin to optimize your website performance.', 'jet-engine' ), |
| 89 | ] ); |
| 90 | } |
| 91 | |
| 92 | /** |
| 93 | * Process migration of the old JetStyleManager data to the new Style Manager module |
| 94 | */ |
| 95 | public function process_migration() { |
| 96 | |
| 97 | if ( ! isset( $_GET['run_migration'] ) || ! current_user_can( 'manage_options' ) ) { |
| 98 | return; |
| 99 | } |
| 100 | |
| 101 | if ( ! wp_verify_nonce( $_REQUEST['_wpnonce'], $this->page_slug ) ) { |
| 102 | wp_send_json_error( esc_html__( 'The link is expired. Please reload the page and try again.', 'jet-engine' ) ); |
| 103 | } |
| 104 | |
| 105 | global $wpdb; |
| 106 | $step = isset( $_REQUEST['step'] ) ? intval( $_REQUEST['step'] ) : 1; |
| 107 | $limit = 20; |
| 108 | $offset = ( $step - 1 ) * $limit; |
| 109 | $items = $wpdb->get_results( "SELECT post_id, meta_value FROM {$wpdb->postmeta} WHERE meta_key = '_jet_sm_controls_values' LIMIT $limit OFFSET $offset" ); |
| 110 | |
| 111 | if ( empty( $items ) ) { |
| 112 | wp_send_json_error( esc_html__( 'No more posts to migrate.', 'jet-engine' ) ); |
| 113 | } |
| 114 | |
| 115 | $total = $this->total_items_to_migrate(); |
| 116 | $migrated = $offset; |
| 117 | |
| 118 | if ( ! class_exists( '\Crocoblock\Blocks_Style\Migrator\Post_Handler' ) ) { |
| 119 | require_once $this->migrator_dir . 'post-handler.php'; |
| 120 | require_once $this->migrator_dir . 'data-normalizer.php'; |
| 121 | } |
| 122 | |
| 123 | foreach ( $items as $item ) { |
| 124 | $post_handler = new Post_Handler( $item->post_id, $item->meta_value ); |
| 125 | $res = $post_handler->migrate_data(); |
| 126 | |
| 127 | if ( $res ) { |
| 128 | $migrated++; |
| 129 | } |
| 130 | } |
| 131 | |
| 132 | if ( $total <= $offset + $limit ) { |
| 133 | |
| 134 | update_option( 'jet_sm_migration_completed', 1 ); |
| 135 | |
| 136 | wp_send_json_success( [ |
| 137 | 'message' => sprintf( |
| 138 | esc_html__( 'Migrated %d posts successfully. Migration completed.', 'jet-engine' ), |
| 139 | $migrated, |
| 140 | ), |
| 141 | 'next_step' => 0, |
| 142 | ] ); |
| 143 | } |
| 144 | |
| 145 | wp_send_json_success( [ |
| 146 | 'message' => sprintf( |
| 147 | esc_html__( 'Migrated %d posts successfully.', 'jet-engine' ), |
| 148 | $migrated, |
| 149 | ), |
| 150 | 'next_step' => $step + 1, |
| 151 | ] ); |
| 152 | } |
| 153 | |
| 154 | /** |
| 155 | * Add migration page to admin menu |
| 156 | */ |
| 157 | public function add_migration_page() { |
| 158 | add_submenu_page( |
| 159 | '', |
| 160 | esc_html__( 'JetStyleManager Migration', 'jet-engine' ), |
| 161 | esc_html__( 'Migration', 'jet-engine' ), |
| 162 | 'manage_options', |
| 163 | $this->page_slug, |
| 164 | [ $this, 'render_migration_page' ] |
| 165 | ); |
| 166 | } |
| 167 | |
| 168 | /** |
| 169 | * Render migration page |
| 170 | */ |
| 171 | public function render_migration_page() { |
| 172 | |
| 173 | if ( ! current_user_can( 'manage_options' ) ) { |
| 174 | wp_die( esc_html__( 'You do not have sufficient permissions to access this page.', 'jet-engine' ) ); |
| 175 | } |
| 176 | |
| 177 | $migration_completed = get_option( 'jet_sm_migration_completed', false ); |
| 178 | $fonts_manager_url = esc_url( admin_url( 'site-editor.php?p=/styles§ion=/typography' ) ); |
| 179 | |
| 180 | $fonts_manager_message = '<p><b>' . esc_html__( 'Please note:', 'jet-engine' ) . '</b> '; |
| 181 | $fonts_manager_message .= sprintf( |
| 182 | esc_html__( ' The new Styles Manager uses fonts installed on your website. You can %1$smanage these fonts here%1$s.', 'jet-engine' ), |
| 183 | '<a href="' . $fonts_manager_url . '" target="_blank">', |
| 184 | '</a>' |
| 185 | ); |
| 186 | $fonts_manager_message .= '</p>'; |
| 187 | |
| 188 | if ( $migration_completed && 2 == (int) $migration_completed ) { |
| 189 | echo '<div class="wrap">'; |
| 190 | echo '<h1>' . esc_html__( 'JetStyleManager Migration', 'jet-engine' ) . '</h1>'; |
| 191 | echo '<p>' . esc_html__( 'Migration process is already completed. You can now deactivate the JetStyleManager plugin to optimize your website performance.', 'jet-engine' ) . '</p>'; |
| 192 | |
| 193 | echo $fonts_manager_message; |
| 194 | |
| 195 | echo '</div>'; |
| 196 | exit; |
| 197 | } |
| 198 | |
| 199 | echo '<div class="wrap">'; |
| 200 | echo '<h1>' . esc_html__( 'JetStyleManager Migration', 'jet-engine' ) . '</h1>'; |
| 201 | echo '<p>' . esc_html__( 'This page allows you to migrate your styling settings to the new Style Manager module.', 'jet-engine' ) . '</p>'; |
| 202 | |
| 203 | $completed_style = 'style="display: none;"'; |
| 204 | $run_style = ''; |
| 205 | |
| 206 | if ( $migration_completed && 1 == (int) $migration_completed ) { |
| 207 | $completed_style = ''; |
| 208 | $run_style = 'style="display: none;"'; |
| 209 | } |
| 210 | |
| 211 | echo '<div id="cleanup_section" ' . $completed_style . '>'; |
| 212 | |
| 213 | echo '<p>' . esc_html__( 'Migration process is completed. Please check your content. If everything is ok, you can click the button below to remove the legacy data and then deactivate JetStyleManager plugin.', 'jet-engine' ) . '</p>'; |
| 214 | |
| 215 | echo $fonts_manager_message; |
| 216 | |
| 217 | echo '<p><a href="' . $this->page_url( false, true ) . '" class="button button-primary" id="cleanup_button">' . esc_html__( 'Cleanup Legacy Data', 'jet-engine' ) . '</a></p>'; |
| 218 | |
| 219 | echo '<p>' . esc_html__( 'If something went wrong click the button below to rollback to the legacy JetStyleManager.', 'jet-engine' ) . '</p>'; |
| 220 | |
| 221 | echo '<p><a href="' . $this->page_url( false, false, true ) . '" class="button button-secondary" id="cleanup_button">' . esc_html__( 'Rollback to legacy JetStyleManager', 'jet-engine' ) . '</a></p>'; |
| 222 | |
| 223 | echo '</div>'; |
| 224 | |
| 225 | echo '<div id="run_section" ' . $run_style . '>'; |
| 226 | |
| 227 | echo '<p>' . esc_html__( 'Click the button below to start the migration process. After migration, you can deactivate the JetStyleManager plugin to optimize your website performance.', 'jet-engine' ) . '</p>'; |
| 228 | |
| 229 | $total_items = $this->total_items_to_migrate(); |
| 230 | |
| 231 | if ( $total_items > 0 ) { |
| 232 | echo '<p>' . sprintf( |
| 233 | esc_html__( 'Total posts to migrate: %d', 'jet-engine' ), |
| 234 | $total_items |
| 235 | ) . '</p>'; |
| 236 | |
| 237 | echo '<p><a href="' . $this->page_url( true ) . '" class="button button-primary" id="run_migration">' . esc_html__( 'Start Migration', 'jet-engine' ) . '</a></p>'; |
| 238 | |
| 239 | echo '<div id="migration_progress"></div>'; |
| 240 | } else { |
| 241 | echo '<p><b>' . esc_html__( 'No posts to migrate. You can just disable an old JetStyleManager plugin and use the new functionality.', 'jet-engine' ) . '</b></p>'; |
| 242 | } |
| 243 | |
| 244 | echo '</div>'; |
| 245 | |
| 246 | $this->inline_scripts(); |
| 247 | |
| 248 | echo '</div>'; |
| 249 | } |
| 250 | |
| 251 | /** |
| 252 | * Get the total number of items to migrate |
| 253 | * |
| 254 | * @return int |
| 255 | */ |
| 256 | public function total_items_to_migrate() { |
| 257 | |
| 258 | global $wpdb; |
| 259 | $count = $wpdb->get_var( "SELECT count(meta_id) FROM {$wpdb->postmeta} WHERE meta_key = '_jet_sm_controls_values';" ); |
| 260 | return $count; |
| 261 | } |
| 262 | |
| 263 | /** |
| 264 | * Inline scripts for the migration page |
| 265 | */ |
| 266 | protected function inline_scripts() { |
| 267 | ?> |
| 268 | <script type="text/javascript"> |
| 269 | |
| 270 | document.addEventListener( 'DOMContentLoaded', function () { |
| 271 | |
| 272 | const migrationData = <?php echo wp_json_encode( [ |
| 273 | 'confirmMessage' => __( 'Are you sure you want to start the migration? This process cannot be undone.', 'jet-engine' ), |
| 274 | ] ); ?>; |
| 275 | |
| 276 | const runMigrationButton = document.getElementById( 'run_migration' ); |
| 277 | const cleanupButton = document.getElementById( 'cleanup_button' ); |
| 278 | const cleanupSection = document.getElementById( 'cleanup_section' ); |
| 279 | const runSection = document.getElementById( 'run_section' ); |
| 280 | const midgrationProgress = document.getElementById( 'migration_progress' ); |
| 281 | |
| 282 | const migrationStep = function( step ) { |
| 283 | |
| 284 | step = step || 1; |
| 285 | |
| 286 | jQuery.ajax({ |
| 287 | url: runMigrationButton.href, |
| 288 | type: 'POST', |
| 289 | data: { |
| 290 | step: step, |
| 291 | }, |
| 292 | success: function (response) { |
| 293 | if ( response.success ) { |
| 294 | |
| 295 | const nextStep = parseInt( response.data.next_step ); |
| 296 | |
| 297 | const progressItem = document.createElement( 'div' ); |
| 298 | progressItem.innerText = response.data.message; |
| 299 | |
| 300 | midgrationProgress.appendChild( |
| 301 | progressItem |
| 302 | ); |
| 303 | |
| 304 | if ( nextStep && nextStep > 0 ) { |
| 305 | migrationStep( nextStep ); |
| 306 | } else { |
| 307 | cleanupSection.style.display = 'block'; |
| 308 | runSection.style.display = 'none'; |
| 309 | } |
| 310 | } else { |
| 311 | alert( response.data ); |
| 312 | } |
| 313 | }, |
| 314 | error: function ( jqXHR, textStatus, errorThrown ) { |
| 315 | alert( errorThrown ); |
| 316 | midgrationProgress.innerHTML = ''; |
| 317 | runMigrationButton.style.display = 'inline-block'; |
| 318 | } |
| 319 | }); |
| 320 | } |
| 321 | |
| 322 | if ( runMigrationButton) { |
| 323 | runMigrationButton.addEventListener( 'click', function ( event ) { |
| 324 | |
| 325 | event.preventDefault(); |
| 326 | |
| 327 | if ( confirm( migrationData.confirmMessage ) ) { |
| 328 | runMigrationButton.style.display = 'none'; |
| 329 | |
| 330 | const progressItem = document.createElement( 'div' ); |
| 331 | progressItem.innerText = 'Migrating posts settings...'; |
| 332 | |
| 333 | midgrationProgress.appendChild( |
| 334 | progressItem |
| 335 | ); |
| 336 | |
| 337 | migrationStep(); |
| 338 | } |
| 339 | }); |
| 340 | } |
| 341 | |
| 342 | if ( cleanupButton ) { |
| 343 | cleanupButton.addEventListener( 'click', function ( event ) { |
| 344 | |
| 345 | event.preventDefault(); |
| 346 | |
| 347 | if ( confirm( '<?php echo esc_js( __( 'Are you sure you want to clean up the legacy data?', 'jet-engine' ) ); ?>' ) ) { |
| 348 | cleanupButton.style.display = 'none'; |
| 349 | |
| 350 | jQuery.ajax({ |
| 351 | url: cleanupButton.href, |
| 352 | type: 'POST', |
| 353 | success: function (response) { |
| 354 | if ( response.success ) { |
| 355 | window.location.reload(); |
| 356 | } else { |
| 357 | alert( response.data ); |
| 358 | cleanupButton.style.display = 'inline-block'; |
| 359 | } |
| 360 | }, |
| 361 | error: function ( jqXHR, textStatus, errorThrown ) { |
| 362 | alert( errorThrown ); |
| 363 | cleanupButton.style.display = 'inline-block'; |
| 364 | } |
| 365 | }); |
| 366 | } |
| 367 | }); |
| 368 | } |
| 369 | }); |
| 370 | </script> |
| 371 | <?php |
| 372 | } |
| 373 | |
| 374 | /** |
| 375 | * Get the URL for the migration page |
| 376 | * |
| 377 | * @param bool $run_migration |
| 378 | * @return string |
| 379 | */ |
| 380 | public function page_url( $run_migration = false, $cleanup = false, $rollback = false ) { |
| 381 | |
| 382 | $url_args = [ 'page' => $this->page_slug ]; |
| 383 | |
| 384 | if ( $run_migration ) { |
| 385 | $url_args['run_migration'] = 1; |
| 386 | } |
| 387 | |
| 388 | if ( $cleanup ) { |
| 389 | $url_args['clean_up_migration'] = 1; |
| 390 | } |
| 391 | |
| 392 | if ( $rollback ) { |
| 393 | $url_args['rollback'] = 1; |
| 394 | } |
| 395 | |
| 396 | $url = add_query_arg( $url_args, admin_url( 'admin.php' ) ); |
| 397 | |
| 398 | return esc_url( wp_nonce_url( $url, $this->page_slug ) ); |
| 399 | } |
| 400 | |
| 401 | /** |
| 402 | * Notice about migration if there is a new style manager version |
| 403 | */ |
| 404 | public function migration_notice() { |
| 405 | |
| 406 | if ( |
| 407 | ! current_user_can( 'manage_options' ) |
| 408 | || isset( $_GET['page'] ) && $_GET['page'] === $this->page_slug |
| 409 | ) { |
| 410 | return; |
| 411 | } |
| 412 | |
| 413 | echo '<div class="notice notice-error is-dismissible">'; |
| 414 | echo '<p>' . esc_html__( 'JetStyleManager as a separate plugin has been replaced with a built-in Style Manager module for the plugins that support it. You can migrate your styling settings to the new style manager module and deactivate JetStyleManager plugin to optimize your website performance.', 'jet-engine' ) . '</p>'; |
| 415 | echo '<p><a href="' . $this->page_url() . '" class="button button-primary">' . esc_html__( 'Go to Migration Page', 'jet-engine' ) . '</a></p>'; |
| 416 | echo '</div>'; |
| 417 | } |
| 418 | } |