597 lines
24 KiB
PHP
597 lines
24 KiB
PHP
<?php
|
||
/**
|
||
* Network Admin page.
|
||
*
|
||
* Registers the plugin settings page under Network Admin > Settings and
|
||
* orchestrates the full migration wizard. Handles all POST actions for:
|
||
* - Table rename / restore (preparation)
|
||
* - Wizard step navigation (steps 1–6)
|
||
* - Wizard reset
|
||
* - CSV log export
|
||
*
|
||
* Network Admin only. Uses exclusively:
|
||
* network_admin_menu, network_admin_init.
|
||
*
|
||
* @package Robotstxt_Mlp2_Mlp5
|
||
*/
|
||
|
||
if ( ! defined( 'ABSPATH' ) ) {
|
||
exit;
|
||
}
|
||
|
||
/**
|
||
* Class Robotstxt_Mlp2_Mlp5_Admin_Page
|
||
*/
|
||
class Robotstxt_Mlp2_Mlp5_Admin_Page {
|
||
|
||
/**
|
||
* Menu slug for the plugin settings page.
|
||
*
|
||
* @var string
|
||
*/
|
||
const MENU_SLUG = 'robotstxt-mlp2-mlp5';
|
||
|
||
/**
|
||
* Required capability to access the plugin page.
|
||
*
|
||
* The manage_network capability is the standard for Network Admin settings.
|
||
*
|
||
* @var string
|
||
*/
|
||
const CAPABILITY = 'manage_network';
|
||
|
||
/**
|
||
* Register the Network Admin page and all POST/GET handlers.
|
||
*/
|
||
public static function init(): void {
|
||
add_action( 'network_admin_menu', array( static::class, 'register_menu' ) );
|
||
add_action( 'admin_post_mlp_migrator_rename_tables', array( static::class, 'handle_rename_action' ) );
|
||
add_action( 'admin_post_mlp_migrator_restore_tables', array( static::class, 'handle_restore_action' ) );
|
||
add_action( 'admin_post_mlp_migrator_step', array( static::class, 'handle_step_actions' ) );
|
||
add_action( 'admin_post_mlp_migrator_reset_wizard', array( static::class, 'handle_reset_action' ) );
|
||
add_action( 'admin_post_mlp_migrator_export_log', array( 'Robotstxt_Mlp2_Mlp5_Step_Verification', 'maybe_export_csv' ) );
|
||
}
|
||
|
||
/**
|
||
* Add the settings page under Network Admin > Settings.
|
||
*/
|
||
public static function register_menu(): void {
|
||
add_submenu_page(
|
||
'settings.php',
|
||
__( 'MLP2 to MLP5 Migrator', 'robotstxt-mlp2-mlp5' ),
|
||
__( 'MLP Migrator', 'robotstxt-mlp2-mlp5' ),
|
||
self::CAPABILITY,
|
||
self::MENU_SLUG,
|
||
array( static::class, 'render' )
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Return the URL to this plugin's Network Admin page.
|
||
*
|
||
* @param array $extra Optional extra query args.
|
||
* @return string Absolute URL.
|
||
*/
|
||
public static function page_url( array $extra = array() ): string {
|
||
$args = array_merge( array( 'page' => self::MENU_SLUG ), $extra );
|
||
return network_admin_url( 'settings.php?' . http_build_query( $args ) );
|
||
}
|
||
|
||
// -------------------------------------------------------------------------
|
||
// POST handlers (preparation)
|
||
// -------------------------------------------------------------------------
|
||
|
||
/**
|
||
* Handle the "Rename MLP2 tables" POST action.
|
||
*/
|
||
public static function handle_rename_action(): void {
|
||
check_admin_referer( 'mlp_migrator_rename', 'mlp_migrator_nonce' );
|
||
if ( ! current_user_can( self::CAPABILITY ) ) {
|
||
wp_die( esc_html__( 'You do not have permission to perform this action.', 'robotstxt-mlp2-mlp5' ) );
|
||
}
|
||
$result = Robotstxt_Mlp2_Mlp5_Table_Preparer::rename_to_backup();
|
||
$sitemeta_renamed = Robotstxt_Mlp2_Mlp5_Table_Preparer::rename_mlp2_sitemeta();
|
||
$args = array( 'renamed' => count( $result['renamed'] ) );
|
||
if ( ! empty( $result['errors'] ) ) {
|
||
$args['rename_errors'] = count( $result['errors'] );
|
||
}
|
||
if ( $sitemeta_renamed > 0 ) {
|
||
$args['sitemeta_renamed'] = $sitemeta_renamed;
|
||
}
|
||
wp_safe_redirect( self::page_url( $args ) );
|
||
exit;
|
||
}
|
||
|
||
/**
|
||
* Handle the "Restore original table names" POST action.
|
||
*/
|
||
public static function handle_restore_action(): void {
|
||
check_admin_referer( 'mlp_migrator_restore', 'mlp_migrator_nonce' );
|
||
if ( ! current_user_can( self::CAPABILITY ) ) {
|
||
wp_die( esc_html__( 'You do not have permission to perform this action.', 'robotstxt-mlp2-mlp5' ) );
|
||
}
|
||
$result = Robotstxt_Mlp2_Mlp5_Table_Preparer::restore_from_backup();
|
||
$sitemeta_restored = Robotstxt_Mlp2_Mlp5_Table_Preparer::restore_mlp2_sitemeta();
|
||
$args = array( 'restored' => count( $result['restored'] ) );
|
||
if ( ! empty( $result['errors'] ) ) {
|
||
$args['restore_errors'] = count( $result['errors'] );
|
||
}
|
||
if ( $sitemeta_restored > 0 ) {
|
||
$args['sitemeta_restored'] = $sitemeta_restored;
|
||
}
|
||
wp_safe_redirect( self::page_url( $args ) );
|
||
exit;
|
||
}
|
||
|
||
// -------------------------------------------------------------------------
|
||
// POST handlers (wizard steps)
|
||
// -------------------------------------------------------------------------
|
||
|
||
/**
|
||
* Route all wizard step POST actions.
|
||
*/
|
||
public static function handle_step_actions(): void {
|
||
// phpcs:ignore WordPress.Security.NonceVerification.Missing
|
||
if ( ! isset( $_POST['mlp_migrator_step_action'] ) ) {
|
||
return;
|
||
}
|
||
if ( ! current_user_can( self::CAPABILITY ) ) {
|
||
wp_die( esc_html__( 'You do not have permission to perform this action.', 'robotstxt-mlp2-mlp5' ) );
|
||
}
|
||
|
||
// phpcs:ignore WordPress.Security.NonceVerification.Missing, WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||
$action = sanitize_key( wp_unslash( $_POST['mlp_migrator_step_action'] ) );
|
||
|
||
switch ( $action ) {
|
||
case '1':
|
||
self::handle_step_1_next();
|
||
break;
|
||
case '2_run':
|
||
self::handle_step_2_run();
|
||
break;
|
||
case '2':
|
||
self::handle_step_next( 2, 3, 'mlp_migrator_step_2' );
|
||
break;
|
||
case '3_run':
|
||
self::handle_step_3_run();
|
||
break;
|
||
case '3':
|
||
self::handle_step_next( 3, 4, 'mlp_migrator_step_3' );
|
||
break;
|
||
case '4':
|
||
self::handle_step_next( 4, 5, 'mlp_migrator_step_4' );
|
||
break;
|
||
case '5':
|
||
self::handle_step_next( 5, 6, 'mlp_migrator_step_5' );
|
||
break;
|
||
case '6_cleanup':
|
||
self::handle_step_6_cleanup();
|
||
break;
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Handle "Next" from Step 1 (Preflight).
|
||
*/
|
||
private static function handle_step_1_next(): void {
|
||
check_admin_referer( 'mlp_migrator_step_1', 'mlp_migrator_nonce' );
|
||
$checks = Robotstxt_Mlp2_Mlp5_Step_Preflight::run();
|
||
if ( $checks['can_proceed'] ) {
|
||
Robotstxt_Mlp2_Mlp5_Wizard_State::mark_step_complete( 1 );
|
||
Robotstxt_Mlp2_Mlp5_Wizard_State::set_step( 2 );
|
||
}
|
||
wp_safe_redirect( self::page_url() );
|
||
exit;
|
||
}
|
||
|
||
/**
|
||
* Handle "Run Analysis" from Step 2.
|
||
*/
|
||
private static function handle_step_2_run(): void {
|
||
check_admin_referer( 'mlp_migrator_analysis', 'mlp_migrator_nonce' );
|
||
$result = Robotstxt_Mlp2_Mlp5_Step_Analysis::run();
|
||
Robotstxt_Mlp2_Mlp5_Wizard_State::set_step_data( 2, $result );
|
||
wp_safe_redirect( self::page_url() );
|
||
exit;
|
||
}
|
||
|
||
/**
|
||
* Handle "Start" from Step 3 (Site Relations).
|
||
*/
|
||
private static function handle_step_3_run(): void {
|
||
check_admin_referer( 'mlp_migrator_site_relations', 'mlp_migrator_nonce' );
|
||
$result = Robotstxt_Mlp2_Mlp5_Step_Site_Relations::run();
|
||
Robotstxt_Mlp2_Mlp5_Wizard_State::set_step_data( 3, $result );
|
||
wp_safe_redirect( self::page_url() );
|
||
exit;
|
||
}
|
||
|
||
/**
|
||
* Handle "Next" for a standard step (advance to next, mark complete).
|
||
*
|
||
* @param int $current_step Current step number.
|
||
* @param int $next_step Next step number.
|
||
* @param string $nonce_action Nonce action string.
|
||
*/
|
||
private static function handle_step_next( int $current_step, int $next_step, string $nonce_action ): void {
|
||
check_admin_referer( $nonce_action, 'mlp_migrator_nonce' );
|
||
Robotstxt_Mlp2_Mlp5_Wizard_State::mark_step_complete( $current_step );
|
||
Robotstxt_Mlp2_Mlp5_Wizard_State::set_step( $next_step );
|
||
wp_safe_redirect( self::page_url() );
|
||
exit;
|
||
}
|
||
|
||
/**
|
||
* Handle the cleanup POST from Step 6.
|
||
*/
|
||
private static function handle_step_6_cleanup(): void {
|
||
check_admin_referer( 'mlp_migrator_cleanup', 'mlp_migrator_nonce' );
|
||
|
||
// phpcs:ignore WordPress.Security.ValidatedSanitizedInput.InputNotSanitized
|
||
$confirm = isset( $_POST['cleanup_confirm'] ) ? wp_unslash( $_POST['cleanup_confirm'] ) : '';
|
||
if ( 'DELETE' !== $confirm ) {
|
||
wp_safe_redirect( self::page_url( array( 'cleanup_error' => '1' ) ) );
|
||
exit;
|
||
}
|
||
|
||
$deactivate = ! empty( $_POST['cleanup_deactivate'] );
|
||
$drop_tables = ! empty( $_POST['cleanup_drop_tables'] ) && $deactivate;
|
||
$sitemeta = ! empty( $_POST['cleanup_sitemeta'] );
|
||
|
||
if ( $deactivate ) {
|
||
Robotstxt_Mlp2_Mlp5_Step_Cleanup::deactivate_mlp2();
|
||
}
|
||
if ( $drop_tables ) {
|
||
Robotstxt_Mlp2_Mlp5_Step_Cleanup::drop_backup_tables();
|
||
}
|
||
if ( $sitemeta ) {
|
||
Robotstxt_Mlp2_Mlp5_Step_Cleanup::remove_mlp2_sitemeta();
|
||
}
|
||
|
||
Robotstxt_Mlp2_Mlp5_Wizard_State::mark_step_complete( 6 );
|
||
wp_safe_redirect( self::page_url( array( 'cleanup_done' => '1' ) ) );
|
||
exit;
|
||
}
|
||
|
||
/**
|
||
* Handle the wizard reset POST action.
|
||
*/
|
||
public static function handle_reset_action(): void {
|
||
check_admin_referer( 'mlp_migrator_reset', 'mlp_migrator_nonce' );
|
||
if ( ! current_user_can( self::CAPABILITY ) ) {
|
||
wp_die( esc_html__( 'You do not have permission to perform this action.', 'robotstxt-mlp2-mlp5' ) );
|
||
}
|
||
Robotstxt_Mlp2_Mlp5_Wizard_State::reset();
|
||
Robotstxt_Mlp2_Mlp5_Logger::clear();
|
||
wp_safe_redirect( self::page_url( array( 'reset' => '1' ) ) );
|
||
exit;
|
||
}
|
||
|
||
// -------------------------------------------------------------------------
|
||
// Rendering
|
||
// -------------------------------------------------------------------------
|
||
|
||
/**
|
||
* Render the full page.
|
||
*/
|
||
public static function render(): void {
|
||
if ( ! current_user_can( self::CAPABILITY ) ) {
|
||
wp_die( esc_html__( 'You do not have permission to access this page.', 'robotstxt-mlp2-mlp5' ) );
|
||
}
|
||
|
||
$has_original = Robotstxt_Mlp2_Mlp5_Table_Preparer::has_original_tables();
|
||
$has_backup = Robotstxt_Mlp2_Mlp5_Table_Preparer::has_backup_tables();
|
||
$mlp5 = new Robotstxt_Mlp2_Mlp5_Detector_Mlp5();
|
||
$mlp5_active = $mlp5->is_active();
|
||
|
||
// Once MLP5 is active its own tables match the mlp_* pattern.
|
||
// They are not leftover MLP2 tables, so suppress the "must be renamed" signal.
|
||
if ( $mlp5_active ) {
|
||
$has_original = false;
|
||
}
|
||
|
||
// Migration is complete when wizard step 6 is marked done.
|
||
$wizard_done = Robotstxt_Mlp2_Mlp5_Wizard_State::is_step_complete( Robotstxt_Mlp2_Mlp5_Wizard_State::TOTAL_STEPS );
|
||
$ready = ( $has_backup && $mlp5_active ) || ( $wizard_done && $mlp5_active );
|
||
?>
|
||
<div class="wrap">
|
||
<h1><?php esc_html_e( 'MLP2 to MLP5 Migrator', 'robotstxt-mlp2-mlp5' ); ?></h1>
|
||
|
||
<?php self::render_feedback_notices(); ?>
|
||
|
||
<?php if ( $ready ) : ?>
|
||
<?php self::render_wizard( $has_original, $has_backup, $mlp5_active, $mlp5 ); ?>
|
||
<?php else : ?>
|
||
<?php self::render_state_banner( $has_original, $has_backup, $mlp5_active ); ?>
|
||
<?php self::render_status_card( $has_original, $has_backup, $mlp5_active, $mlp5 ); ?>
|
||
<?php self::render_action_forms( $has_original, $has_backup, $mlp5_active ); ?>
|
||
<?php endif; ?>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
/**
|
||
* Render the full wizard when the system is ready (State C).
|
||
*
|
||
* @param bool $has_original Whether original MLP2 tables exist.
|
||
* @param bool $has_backup Whether backup MLP2 tables exist.
|
||
* @param bool $mlp5_active Whether MLP5 is network-active.
|
||
* @param Robotstxt_Mlp2_Mlp5_Detector_Mlp5 $mlp5 MLP5 detector instance.
|
||
*/
|
||
private static function render_wizard(
|
||
bool $has_original,
|
||
bool $has_backup,
|
||
bool $mlp5_active,
|
||
Robotstxt_Mlp2_Mlp5_Detector_Mlp5 $mlp5
|
||
): void {
|
||
$current_step = Robotstxt_Mlp2_Mlp5_Wizard_State::get_current_step();
|
||
$step_labels = array(
|
||
1 => __( 'Preflight', 'robotstxt-mlp2-mlp5' ),
|
||
2 => __( 'Analysis', 'robotstxt-mlp2-mlp5' ),
|
||
3 => __( 'Site Relations', 'robotstxt-mlp2-mlp5' ),
|
||
4 => __( 'Content Relations', 'robotstxt-mlp2-mlp5' ),
|
||
5 => __( 'Verification', 'robotstxt-mlp2-mlp5' ),
|
||
6 => __( 'Cleanup', 'robotstxt-mlp2-mlp5' ),
|
||
);
|
||
?>
|
||
<div style="background:#fff;border:1px solid #c3c4c7;padding:1.5em;max-width:780px;">
|
||
|
||
<?php /* Step indicator */ ?>
|
||
<ol style="display:flex;list-style:none;margin:0 0 1.5em;padding:0;gap:0;">
|
||
<?php for ( $i = 1; $i <= Robotstxt_Mlp2_Mlp5_Wizard_State::TOTAL_STEPS; $i++ ) : ?>
|
||
<?php
|
||
$is_done = Robotstxt_Mlp2_Mlp5_Wizard_State::is_step_complete( $i );
|
||
$is_current = ( $i === $current_step );
|
||
if ( $is_current ) {
|
||
$bg = '#2271b1';
|
||
$color = '#fff';
|
||
} elseif ( $is_done ) {
|
||
$bg = '#00a32a';
|
||
$color = '#fff';
|
||
} else {
|
||
$bg = '#f0f0f1';
|
||
$color = '#50575e';
|
||
}
|
||
?>
|
||
<li style="flex:1;text-align:center;padding:.5em .25em;background:<?php echo esc_attr( $bg ); ?>;color:<?php echo esc_attr( $color ); ?>;font-size:.85em;font-weight:<?php echo $is_current ? '700' : '400'; ?>;border-right:2px solid #fff;">
|
||
<?php echo esc_html( $i . '. ' . $step_labels[ $i ] ); ?>
|
||
<?php echo $is_done ? ' ✓' : ''; ?>
|
||
</li>
|
||
<?php endfor; ?>
|
||
</ol>
|
||
|
||
<?php /* Step content */ ?>
|
||
<div style="min-height:200px;">
|
||
<?php
|
||
switch ( $current_step ) {
|
||
case 1:
|
||
Robotstxt_Mlp2_Mlp5_Step_Preflight::render();
|
||
break;
|
||
case 2:
|
||
Robotstxt_Mlp2_Mlp5_Step_Analysis::render();
|
||
break;
|
||
case 3:
|
||
Robotstxt_Mlp2_Mlp5_Step_Site_Relations::render();
|
||
break;
|
||
case 4:
|
||
Robotstxt_Mlp2_Mlp5_Step_Content_Relations::render();
|
||
break;
|
||
case 5:
|
||
Robotstxt_Mlp2_Mlp5_Step_Verification::render();
|
||
break;
|
||
case 6:
|
||
Robotstxt_Mlp2_Mlp5_Step_Cleanup::render();
|
||
break;
|
||
}
|
||
?>
|
||
</div>
|
||
|
||
<?php /* Reset disclosure */ ?>
|
||
<details style="margin-top:2em;border-top:1px solid #e2e2e2;padding-top:1em;">
|
||
<summary style="cursor:pointer;color:#646970;"><?php esc_html_e( 'Reset migration (start over)', 'robotstxt-mlp2-mlp5' ); ?></summary>
|
||
<div style="margin-top:.75em;padding:.75em;border:1px solid #dcdcde;background:#fff8f8;">
|
||
<p><?php esc_html_e( 'This will reset the wizard to Step 1 and clear the migration log. It does not modify MLP5 data.', 'robotstxt-mlp2-mlp5' ); ?></p>
|
||
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
|
||
<?php wp_nonce_field( 'mlp_migrator_reset', 'mlp_migrator_nonce' ); ?>
|
||
<input type="hidden" name="action" value="mlp_migrator_reset_wizard" />
|
||
<button type="submit" class="button button-secondary"><?php esc_html_e( 'Reset wizard', 'robotstxt-mlp2-mlp5' ); ?></button>
|
||
</form>
|
||
</div>
|
||
</details>
|
||
</div>
|
||
|
||
<?php /* Status sidebar (compact, always visible) */ ?>
|
||
<div style="margin-top:1em;max-width:780px;">
|
||
<details>
|
||
<summary style="cursor:pointer;color:#646970;"><?php esc_html_e( 'System status', 'robotstxt-mlp2-mlp5' ); ?></summary>
|
||
<div style="margin-top:.5em;">
|
||
<?php self::render_status_card( $has_original, $has_backup, $mlp5_active, $mlp5 ); ?>
|
||
</div>
|
||
</details>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
// -------------------------------------------------------------------------
|
||
// Shared UI helpers (used in both preparation and wizard views)
|
||
// -------------------------------------------------------------------------
|
||
|
||
/**
|
||
* Show feedback notices after redirects.
|
||
*/
|
||
private static function render_feedback_notices(): void {
|
||
// phpcs:disable WordPress.Security.NonceVerification.Recommended
|
||
if ( isset( $_GET['renamed'] ) ) {
|
||
$count = (int) $_GET['renamed'];
|
||
/* translators: %d: number of renamed tables */
|
||
printf( '<div class="notice notice-success is-dismissible"><p>%s</p></div>', esc_html( sprintf( _n( '%d table renamed successfully.', '%d tables renamed successfully.', $count, 'robotstxt-mlp2-mlp5' ), $count ) ) ); // phpcs:ignore WordPress.WP.I18n.MismatchedPlaceholders
|
||
}
|
||
if ( isset( $_GET['rename_errors'] ) ) {
|
||
$count = (int) $_GET['rename_errors'];
|
||
/* translators: %d: number of tables that could not be renamed */
|
||
printf( '<div class="notice notice-error"><p>%s</p></div>', esc_html( sprintf( _n( '%d table could not be renamed. Check database permissions.', '%d tables could not be renamed. Check database permissions.', $count, 'robotstxt-mlp2-mlp5' ), $count ) ) ); // phpcs:ignore WordPress.WP.I18n.MismatchedPlaceholders
|
||
}
|
||
if ( isset( $_GET['sitemeta_renamed'] ) ) {
|
||
printf( '<div class="notice notice-success is-dismissible"><p>%s</p></div>', esc_html__( 'MLP2 sitemeta backed up. MultilingualPress 5 can now activate cleanly.', 'robotstxt-mlp2-mlp5' ) );
|
||
}
|
||
if ( isset( $_GET['sitemeta_restored'] ) ) {
|
||
printf( '<div class="notice notice-success is-dismissible"><p>%s</p></div>', esc_html__( 'MLP2 sitemeta restored to original keys.', 'robotstxt-mlp2-mlp5' ) );
|
||
}
|
||
if ( isset( $_GET['restored'] ) ) {
|
||
$count = (int) $_GET['restored'];
|
||
/* translators: %d: number of restored tables */
|
||
printf( '<div class="notice notice-success is-dismissible"><p>%s</p></div>', esc_html( sprintf( _n( '%d table restored to original name.', '%d tables restored to original names.', $count, 'robotstxt-mlp2-mlp5' ), $count ) ) ); // phpcs:ignore WordPress.WP.I18n.MismatchedPlaceholders
|
||
}
|
||
if ( isset( $_GET['restore_errors'] ) ) {
|
||
$count = (int) $_GET['restore_errors'];
|
||
/* translators: %d: number of tables that could not be restored */
|
||
printf( '<div class="notice notice-error"><p>%s</p></div>', esc_html( sprintf( _n( '%d table could not be restored. Check database permissions.', '%d tables could not be restored. Check database permissions.', $count, 'robotstxt-mlp2-mlp5' ), $count ) ) ); // phpcs:ignore WordPress.WP.I18n.MismatchedPlaceholders
|
||
}
|
||
if ( isset( $_GET['reset'] ) ) {
|
||
printf( '<div class="notice notice-success is-dismissible"><p>%s</p></div>', esc_html__( 'Wizard reset. You can start the migration from Step 1.', 'robotstxt-mlp2-mlp5' ) );
|
||
}
|
||
if ( isset( $_GET['cleanup_done'] ) ) {
|
||
printf( '<div class="notice notice-success is-dismissible"><p>%s</p></div>', esc_html__( 'Cleanup completed.', 'robotstxt-mlp2-mlp5' ) );
|
||
}
|
||
if ( isset( $_GET['cleanup_error'] ) ) {
|
||
printf( '<div class="notice notice-error"><p>%s</p></div>', esc_html__( 'Cleanup confirmation invalid. Type DELETE exactly.', 'robotstxt-mlp2-mlp5' ) );
|
||
}
|
||
// phpcs:enable WordPress.Security.NonceVerification.Recommended
|
||
}
|
||
|
||
/**
|
||
* Show a banner communicating the overall system state (preparation view only).
|
||
*
|
||
* @param bool $has_original Whether original MLP2 tables exist.
|
||
* @param bool $has_backup Whether backup MLP2 tables exist.
|
||
* @param bool $mlp5_active Whether MLP5 is network-active.
|
||
*/
|
||
private static function render_state_banner( bool $has_original, bool $has_backup, bool $mlp5_active ): void {
|
||
if ( $has_original && ! $has_backup ) {
|
||
$color = '#d63638';
|
||
$msg = __( 'Action required: MLP2 tables must be renamed before MultilingualPress 5 can be activated.', 'robotstxt-mlp2-mlp5' );
|
||
} elseif ( $has_backup && ! $mlp5_active ) {
|
||
$color = '#dba617';
|
||
$msg = __( 'MLP2 tables renamed. Now go to Network Admin > Plugins and activate MultilingualPress 5.', 'robotstxt-mlp2-mlp5' );
|
||
} elseif ( $has_original && $has_backup ) {
|
||
$color = '#dba617';
|
||
$msg = __( 'Warning: both original and backup MLP2 tables were found. Investigate before proceeding.', 'robotstxt-mlp2-mlp5' );
|
||
} else {
|
||
$color = '#d63638';
|
||
$msg = __( 'No MLP2 tables found. Migration cannot proceed. Restore your database from a backup.', 'robotstxt-mlp2-mlp5' );
|
||
}
|
||
printf(
|
||
'<div style="border-left:4px solid %s;padding:.75em 1em;margin:1em 0;background:#fff;max-width:640px;"><strong>%s</strong></div>',
|
||
esc_attr( $color ),
|
||
wp_kses_post( $msg )
|
||
);
|
||
}
|
||
|
||
/**
|
||
* Show the system status card.
|
||
*
|
||
* @param bool $has_original Whether original MLP2 tables exist.
|
||
* @param bool $has_backup Whether backup MLP2 tables exist.
|
||
* @param bool $mlp5_active Whether MLP5 is network-active.
|
||
* @param Robotstxt_Mlp2_Mlp5_Detector_Mlp5 $mlp5 MLP5 detector instance.
|
||
*/
|
||
private static function render_status_card(
|
||
bool $has_original,
|
||
bool $has_backup,
|
||
bool $mlp5_active,
|
||
Robotstxt_Mlp2_Mlp5_Detector_Mlp5 $mlp5
|
||
): void {
|
||
$orig_count = count( Robotstxt_Mlp2_Mlp5_Table_Preparer::get_original_tables() );
|
||
$backup_count = count( Robotstxt_Mlp2_Mlp5_Table_Preparer::get_backup_tables() );
|
||
?>
|
||
<div class="card" style="max-width:640px;margin-top:1em;">
|
||
<h2 style="margin-top:0;"><?php esc_html_e( 'System Status', 'robotstxt-mlp2-mlp5' ); ?></h2>
|
||
<table class="widefat striped" style="border:0;">
|
||
<tbody>
|
||
<tr>
|
||
<td><?php esc_html_e( 'MLP2 tables (original names)', 'robotstxt-mlp2-mlp5' ); ?></td>
|
||
<td>
|
||
<?php if ( $has_original ) : ?>
|
||
<span style="color:#d63638;">● <?php echo esc_html( sprintf( /* translators: %d: number of tables */ _n( '%d table — must be renamed', '%d tables — must be renamed', $orig_count, 'robotstxt-mlp2-mlp5' ), $orig_count ) ); // phpcs:ignore WordPress.WP.I18n.MismatchedPlaceholders ?></span>
|
||
<?php else : ?>
|
||
<span style="color:#46b450;">✓ <?php esc_html_e( 'None', 'robotstxt-mlp2-mlp5' ); ?></span>
|
||
<?php endif; ?>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td><?php esc_html_e( 'MLP2 tables (backup copies)', 'robotstxt-mlp2-mlp5' ); ?></td>
|
||
<td>
|
||
<?php if ( $has_backup ) : ?>
|
||
<span style="color:#46b450;">✓ <?php echo esc_html( sprintf( /* translators: %d: number of backup tables */ _n( '%d backup table ready', '%d backup tables ready', $backup_count, 'robotstxt-mlp2-mlp5' ), $backup_count ) ); // phpcs:ignore WordPress.WP.I18n.MismatchedPlaceholders ?></span>
|
||
<?php else : ?>
|
||
<span style="color:#888;">— <?php esc_html_e( 'Not yet renamed', 'robotstxt-mlp2-mlp5' ); ?></span>
|
||
<?php endif; ?>
|
||
</td>
|
||
</tr>
|
||
<tr>
|
||
<td><?php esc_html_e( 'MultilingualPress 5 (network-active)', 'robotstxt-mlp2-mlp5' ); ?></td>
|
||
<td>
|
||
<?php if ( $mlp5_active ) : ?>
|
||
<span style="color:#46b450;">✓ <?php echo esc_html( sprintf( /* translators: %s: version */ __( 'Active (v%s)', 'robotstxt-mlp2-mlp5' ), $mlp5->get_version() ) ); ?></span>
|
||
<?php else : ?>
|
||
<span style="color:#888;">— <?php esc_html_e( 'Not active', 'robotstxt-mlp2-mlp5' ); ?></span>
|
||
<?php endif; ?>
|
||
</td>
|
||
</tr>
|
||
</tbody>
|
||
</table>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
/**
|
||
* Render action forms for the preparation view.
|
||
*
|
||
* @param bool $has_original Whether original MLP2 tables exist.
|
||
* @param bool $has_backup Whether backup MLP2 tables exist.
|
||
* @param bool $mlp5_active Whether MLP5 is network-active.
|
||
*/
|
||
private static function render_action_forms( bool $has_original, bool $has_backup, bool $mlp5_active ): void {
|
||
if ( $has_original ) {
|
||
?>
|
||
<div style="max-width:640px;margin-top:1.5em;">
|
||
<h2><?php esc_html_e( 'Step 1 — Rename MLP2 Tables', 'robotstxt-mlp2-mlp5' ); ?></h2>
|
||
<p><?php esc_html_e( 'MultilingualPress 5 cannot activate while the original MLP2 table names are present. Click below to rename them to temporary backup copies ({prefix}mlp2bak_*). This is safe and fully reversible.', 'robotstxt-mlp2-mlp5' ); ?></p>
|
||
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
|
||
<?php wp_nonce_field( 'mlp_migrator_rename', 'mlp_migrator_nonce' ); ?>
|
||
<input type="hidden" name="action" value="mlp_migrator_rename_tables" />
|
||
<p><button type="submit" class="button button-primary"><?php esc_html_e( 'Rename MLP2 tables (prepare for MLP5 activation)', 'robotstxt-mlp2-mlp5' ); ?></button></p>
|
||
</form>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
if ( $has_backup && ! $mlp5_active ) {
|
||
?>
|
||
<div style="max-width:640px;margin-top:1.5em;">
|
||
<h2><?php esc_html_e( 'Step 2 — Activate MultilingualPress 5', 'robotstxt-mlp2-mlp5' ); ?></h2>
|
||
<p><?php esc_html_e( 'MLP2 tables have been renamed. MultilingualPress 5 can now be activated without the old-version compatibility error.', 'robotstxt-mlp2-mlp5' ); ?></p>
|
||
<p><a href="<?php echo esc_url( network_admin_url( 'plugins.php' ) ); ?>" class="button button-primary"><?php esc_html_e( 'Go to Network Admin › Plugins', 'robotstxt-mlp2-mlp5' ); ?></a></p>
|
||
</div>
|
||
<?php
|
||
}
|
||
|
||
if ( $has_backup ) {
|
||
?>
|
||
<div style="max-width:640px;margin-top:2em;">
|
||
<details>
|
||
<summary style="cursor:pointer;color:#646970;"><?php esc_html_e( 'Emergency: restore original MLP2 table names', 'robotstxt-mlp2-mlp5' ); ?></summary>
|
||
<div style="margin-top:.75em;padding:.75em;border:1px solid #dcdcde;background:#fff8f8;">
|
||
<p><?php esc_html_e( 'This renames backup tables back to their original MLP2 names. Only use this before MLP5 has been activated.', 'robotstxt-mlp2-mlp5' ); ?></p>
|
||
<form method="post" action="<?php echo esc_url( admin_url( 'admin-post.php' ) ); ?>">
|
||
<?php wp_nonce_field( 'mlp_migrator_restore', 'mlp_migrator_nonce' ); ?>
|
||
<input type="hidden" name="action" value="mlp_migrator_restore_tables" />
|
||
<button type="submit" class="button button-secondary"><?php esc_html_e( 'Restore original table names', 'robotstxt-mlp2-mlp5' ); ?></button>
|
||
</form>
|
||
</div>
|
||
</details>
|
||
</div>
|
||
<?php
|
||
}
|
||
}
|
||
}
|