first commit

This commit is contained in:
2023-09-12 21:41:04 +02:00
commit 3361a7f053
13284 changed files with 2116755 additions and 0 deletions

View File

@@ -0,0 +1,185 @@
<?php
/**
* @author OnTheGo Systems
*/
class WPML_TM_ICL20_Migrate_Local {
const JOBS_TYPES_DOCUMENTS = 'icl_translation_status';
const JOBS_TYPES_STRINGS = 'icl_string_translations';
private $progress;
private $sitepress;
private $status;
/** @var WPML_TP_Services */
private $tp_services;
/**
* WPML_TM_ICL20 constructor.
*
* @param WPML_TP_Services $tp_services
* @param WPML_TM_ICL20_Migration_Status $status
* @param WPML_TM_ICL20_Migration_Progress $progress
* @param SitePress $sitepress
*
* @internal param SitePress $sitepress
*/
public function __construct(
WPML_TP_Services $tp_services,
WPML_TM_ICL20_Migration_Status $status,
WPML_TM_ICL20_Migration_Progress $progress,
SitePress $sitepress
) {
$this->tp_services = $tp_services;
$this->status = $status;
$this->progress = $progress;
$this->sitepress = $sitepress;
}
public function migrate_jobs( $table ) {
$result = false;
$current_service = $this->tp_services->get_current_service();
if ( $this->status->get_ICL_20_TS_ID() === $current_service->id ) {
$step = null;
if ( self::JOBS_TYPES_DOCUMENTS === $table ) {
$step = WPML_TM_ICL20_Migration_Progress::STEP_MIGRATE_JOBS_DOCUMENTS;
}
if ( self::JOBS_TYPES_STRINGS === $table ) {
$step = WPML_TM_ICL20_Migration_Progress::STEP_MIGRATE_JOBS_STRINGS;
}
if ( null !== $step ) {
$update = $this->update_table( $table );
$result = false !== $update;
$this->progress->set_completed_step( $step, $result );
} else {
$this->progress->log_failed_attempt( __METHOD__ . ' - ' . 'Wrong "' . $table . '"' );
}
}
return $result;
}
/**
* @param $table
*
* @return false|int
*/
private function update_table( $table ) {
$wpdb = $this->sitepress->get_wpdb();
$update = $wpdb->update(
$wpdb->prefix . $table,
array(
'translator_id' => 0,
'translation_service' => $this->status->get_ICL_20_TS_ID(),
),
array(
'translation_service' => $this->status->get_ICL_LEGACY_TS_ID(),
),
array( '%d', '%d' ),
array( '%d' )
);
if ( false === $update ) {
$this->progress->log_failed_attempt( __METHOD__ . ' - ' . $wpdb->last_error );
}
return $update;
}
public function migrate_project() {
$old_index = $this->progress->get_project_to_migrate();
// icl_translation_projects
$migrated = false;
if ( $old_index ) {
$current_service = $this->tp_services->get_current_service();
if ( $current_service && null !== $current_service->id ) {
$new_index = md5( $current_service->id . serialize( $current_service->custom_fields_data ) );
$migrated = $this->update_project_index( $old_index, $new_index );
}
}
$this->progress->set_completed_step( WPML_TM_ICL20_Migration_Progress::STEP_MIGRATE_LOCAL_PROJECT, $migrated );
return $migrated;
}
private function update_project_index( $old_service_index, $new_service_index ) {
$updated = false;
$projects = $this->sitepress->get_setting( 'icl_translation_projects', null );
$old_index_exists = array_key_exists( $old_service_index, $projects );
$new_index_does_not_exists = ! array_key_exists( $new_service_index, $projects );
if ( $projects && $old_index_exists && $new_index_does_not_exists ) {
$project = $projects[ $old_service_index ];
$projects[ $new_service_index ] = $project;
unset( $projects[ $old_service_index ] );
$this->sitepress->set_setting( 'icl_translation_projects', $projects, true );
$updated = true;
}
if ( false === $updated ) {
$error = '';
if ( ! $old_index_exists ) {
$error = 'The old project does not exists';
}
if ( ! $new_index_does_not_exists ) {
$error = 'The new project index already exists';
}
$this->progress->log_failed_attempt( __METHOD__ . ' - ' . $error );
}
return $updated;
}
public function migrate_service( $new_token ) {
$current_service = $this->tp_services->get_current_service();
$migrated = false;
if ( $current_service ) {
$old_index = md5( $current_service->id . serialize( $current_service->custom_fields_data ) );
$this->progress->set_project_to_migrate( $old_index );
$icl20_service_id = $this->status->get_ICL_20_TS_ID();
$this->tp_services->select_service(
$icl20_service_id,
array(
'api_token' => $new_token,
)
);
$active_service = $this->tp_services->get_current_service();
$migrated = $active_service->id === $icl20_service_id;
}
$this->progress->set_completed_step( WPML_TM_ICL20_Migration_Progress::STEP_MIGRATE_LOCAL_SERVICE, $migrated );
return $migrated;
}
public function rollback_service() {
$current_service = $this->tp_services->get_current_service();
$rolled_back = false;
if ( $current_service ) {
$this->tp_services->select_service( $this->status->get_ICL_LEGACY_TS_ID() );
$active_service = $this->tp_services->get_current_service();
$rolled_back = $active_service->id === $this->status->get_ICL_LEGACY_TS_ID();
}
$this->progress->set_completed_step( WPML_TM_ICL20_Migration_Progress::STEP_MIGRATE_LOCAL_SERVICE, false );
return $rolled_back;
}
}

View File

@@ -0,0 +1,125 @@
<?php
class WPML_TM_ICL20_Migrate_Remote {
private $container;
private $progress;
/**
* WPML_TM_ICL20 constructor.
*
* @param WPML_TM_ICL20_Migration_Progress $progress
* @param WPML_TM_ICL20_Migration_Container $container
*/
public function __construct(
WPML_TM_ICL20_Migration_Progress $progress,
WPML_TM_ICL20_Migration_Container $container
) {
$this->progress = $progress;
$this->container = $container;
}
/**
* @param string $ts_accesskey
* @param int $ts_id
*
* @return bool
*
* Note: `ts_id` (aka `website_id`) = `website_id`
*
* @link https://onthegosystems.myjetbrains.com/youtrack/issue/icldev-2322
*/
public function acknowledge_icl( $ts_id, $ts_accesskey ) {
$result = false;
try {
$result = $this->container->get_acknowledge()->acknowledge_icl( $ts_id, $ts_accesskey );
} catch ( WPML_TM_ICL20MigrationException $ex ) {
$this->progress->log_failed_attempt( __METHOD__ . ' - ' . $ex->getCode() . ': ' . $ex->getMessage() );
}
if ( $result ) {
$this->progress->set_completed_step( WPML_TM_ICL20_Migration_Progress::STEP_ICL_ACK, true );
return $result;
}
$this->progress->set_completed_step( WPML_TM_ICL20_Migration_Progress::STEP_ICL_ACK, false );
return false;
}
/**
* @param string $ts_accesskey
* @param int $ts_id
*
* @return string|null
*
* Note: `ts_id` (aka `website_id`) = `website_id`
*
* @link https://onthegosystems.myjetbrains.com/youtrack/issue/icldev-2285
*/
public function get_token( $ts_id, $ts_accesskey ) {
$token = null;
try {
$token = $this->container->get_token()->get_token( $ts_id, $ts_accesskey );
} catch ( WPML_TM_ICL20MigrationException $ex ) {
$this->progress->log_failed_attempt( __METHOD__ . ' - ' . $ex->getCode() . ': ' . $ex->getMessage() );
}
if ( null !== $token ) {
$this->progress->set_completed_step( WPML_TM_ICL20_Migration_Progress::STEP_TOKEN, $token );
return $token;
}
$this->progress->set_completed_step( 'token', false );
return null;
}
/**
* @param int $project_id
* @param string $access_key
* @param string $new_token
*
* @return bool|null
* @link https://onthegosystems.myjetbrains.com/youtrack/issue/tsapi-887
*
*/
public function migrate_project( $project_id, $access_key, $new_token ) {
$migrate = null;
try {
$migrate = $this->container->get_project()->migrate( $project_id, $access_key, $new_token );
} catch ( WPML_TM_ICL20MigrationException $ex ) {
$this->progress->log_failed_attempt( __METHOD__ . ' - ' . $ex->getCode() . ': ' . $ex->getMessage() );
}
if ( $migrate ) {
$this->progress->set_completed_step( WPML_TM_ICL20_Migration_Progress::STEP_MIGRATE_REMOTE_PROJECT, true );
return $migrate;
}
$this->progress->set_completed_step( WPML_TM_ICL20_Migration_Progress::STEP_MIGRATE_REMOTE_PROJECT, false );
return false;
}
/**
* @param int $project_id
* @param string $access_key
*
* @return bool
* @link https://onthegosystems.myjetbrains.com/youtrack/issue/tsapi-887
*
*/
public function migrate_project_rollback( $project_id, $access_key ) {
$result = false;
try {
$result = $this->container->get_project()->rollback_migration( $project_id, $access_key );
} catch ( WPML_TM_ICL20MigrationException $ex ) {
$this->progress->log_failed_attempt( __METHOD__ . ' - ' . $ex->getCode() . ': ' . $ex->getMessage() );
}
return $result;
}
}

View File

@@ -0,0 +1,159 @@
<?php
/**
* @author OnTheGo Systems
*/
class WPML_TM_ICL20_Migrate {
private $local_migration;
private $progress;
private $remote_migration;
private $status;
/** @var WPML_TP_Services */
private $tp_services;
public function __construct(
WPML_TM_ICL20_Migration_Progress $progress,
WPML_TM_ICL20_Migration_Status $status,
WPML_TM_ICL20_Migrate_Remote $remote_migration,
WPML_TM_ICL20_Migrate_Local $local_migration,
WPML_TP_Services $tp_services
) {
$this->progress = $progress;
$this->status = $status;
$this->remote_migration = $remote_migration;
$this->local_migration = $local_migration;
$this->tp_services = $tp_services;
}
public function migrate_project_rollback() {
if ( ! $this->status->has_active_legacy_icl() ) {
return false;
}
$project = $this->tp_services->get_current_project();
$token = $this->get_token( $project );
if ( $token ) {
return $this->remote_migration->migrate_project_rollback( $project->id, $project->access_key );
}
return false;
}
public function run() {
$this->progress->set_migration_started();
$project = $this->tp_services->get_current_project();
$token = $project ? $this->get_token( $project ) : null;
if ( (bool) $token
&& $this->migrate_project( $project, $token )
&& $this->acknowledge_icl( $project )
&& $this->migrate_local_service( $token )
&& $this->migrate_local_project()
&& $this->migrate_local_jobs(
WPML_TM_ICL20_Migrate_Local::JOBS_TYPES_DOCUMENTS,
WPML_TM_ICL20_Migration_Progress::STEP_MIGRATE_JOBS_DOCUMENTS
)
&& $this->migrate_local_jobs(
WPML_TM_ICL20_Migrate_Local::JOBS_TYPES_STRINGS,
WPML_TM_ICL20_Migration_Progress::STEP_MIGRATE_JOBS_STRINGS
) ) {
$this->progress->set_migration_done();
return true;
}
return false;
}
/**
* @param $project
*
* @return string
*/
private function get_token( $project ) {
$token = $this->progress->get_completed_step( WPML_TM_ICL20_Migration_Progress::STEP_TOKEN );
if ( WPML_TM_ICL20_Migration_Progress::STEP_FAILED === $token ) {
$token = $this->remote_migration->get_token( $project->ts_id, $project->ts_access_key );
}
return $token;
}
/**
* @param $project
* @param $token
*
* @return bool
*/
private function migrate_project( $project, $token ) {
$project_migrated = $this->progress->get_completed_step( WPML_TM_ICL20_Migration_Progress::STEP_MIGRATE_REMOTE_PROJECT );
if ( WPML_TM_ICL20_Migration_Progress::STEP_FAILED === $project_migrated ) {
$project_migrated = $this->remote_migration->migrate_project( $project->id, $project->access_key, $token );
}
return (bool) $project_migrated;
}
/**
* @param $project
*
* @return bool
*/
private function acknowledge_icl( $project ) {
$icl_acknowledged = $this->progress->get_completed_step( WPML_TM_ICL20_Migration_Progress::STEP_ICL_ACK );
if ( WPML_TM_ICL20_Migration_Progress::STEP_FAILED === $icl_acknowledged ) {
$icl_acknowledged = $this->remote_migration->acknowledge_icl( $project->ts_id, $project->ts_access_key );
}
return (bool) $icl_acknowledged;
}
/**
* @param $token
*
* @return bool
*/
private function migrate_local_service( $token ) {
$service_migrated = $this->progress->get_completed_step( WPML_TM_ICL20_Migration_Progress::STEP_MIGRATE_LOCAL_SERVICE );
if ( WPML_TM_ICL20_Migration_Progress::STEP_DONE === $service_migrated ) {
$current_service = $this->tp_services->get_current_service();
$service_migrated = $current_service && $this->status->get_ICL_20_TS_ID() === $current_service->id;
}
if ( WPML_TM_ICL20_Migration_Progress::STEP_FAILED === $service_migrated ) {
$service_migrated = $this->local_migration->migrate_service( $token );
}
return (bool) $service_migrated;
}
/**
* @return bool
*/
private function migrate_local_project() {
$project_migrated = $this->progress->get_completed_step( WPML_TM_ICL20_Migration_Progress::STEP_MIGRATE_LOCAL_PROJECT );
if ( WPML_TM_ICL20_Migration_Progress::STEP_FAILED === $project_migrated ) {
$project_migrated = $this->local_migration->migrate_project();
}
return (bool) $project_migrated;
}
/**
* @param string $table
* @param string $step
*
* @return bool
*/
private function migrate_local_jobs( $table, $step ) {
$job_migrated = $this->progress->get_completed_step( $step );
if ( WPML_TM_ICL20_Migration_Progress::STEP_FAILED === $job_migrated ) {
$job_migrated = $this->local_migration->migrate_jobs( $table );
}
return (bool) $job_migrated;
}
}

View File

@@ -0,0 +1,28 @@
<?php
/**
* @author OnTheGo Systems
*/
class WPML_TM_ICL20_Migration_AJAX extends WPML_TM_AJAX {
/** @var WPML_TM_ICL20_Migration_Progress */
private $progress;
/**
* WPML_TM_ICL20_Migration_AJAX constructor.
*
* @param WPML_TM_ICL20_Migration_Progress $progress
*/
public function __construct( WPML_TM_ICL20_Migration_Progress $progress ) {
$this->progress = $progress;
}
/**
* AJAX callback used to set the user confirmation for starting the migration
*/
public function user_confirmation() {
if ( $this->is_valid_request() ) {
$this->progress->set_user_confirmed();
wp_send_json_success();
}
}
}

View File

@@ -0,0 +1,7 @@
<?php
/**
* @author OnTheGo Systems
*/
class WPML_TM_ICL20MigrationException extends WPMLTranslationProxyApiException {
}

View File

@@ -0,0 +1,170 @@
<?php
/**
* @author OnTheGo Systems
*/
class WPML_TM_ICL20_Migration_Factory {
/**
* @var WPML_TM_ICL20_Migration_Notices
*/
private $notices;
/**
* @var WPML_TM_ICL20_Migration_Progress
*/
private $progress;
/**
* @var WPML_TM_ICL20_Migration_Status
*/
private $status;
/**
* @var WPML_TP_Services
*/
private $tp_services;
/**
* @var WP_Http
*/
private $wp_http;
/**
* @return WPML_TM_ICL20_Migration_AJAX
*/
public function create_ajax() {
return new WPML_TM_ICL20_Migration_AJAX( $this->create_progress() );
}
/**
* @return WPML_TM_ICL20_Migration_Locks
*/
public function create_locks() {
return new WPML_TM_ICL20_Migration_Locks( $this->create_progress() );
}
/**
* @return WPML_TM_ICL20_Migration_Progress
*/
public function create_progress() {
if ( null === $this->progress ) {
$this->progress = new WPML_TM_ICL20_Migration_Progress();
}
return $this->progress;
}
/**
* @return WPML_TM_ICL20_Migrate
*/
public function create_migration() {
return new WPML_TM_ICL20_Migrate(
$this->create_progress(),
$this->create_status(),
$this->get_remote_migration(),
$this->get_local_migration(),
$this->get_tp_services()
);
}
/**
* @return WPML_TM_ICL20_Migration_Status
*/
public function create_status() {
if ( null === $this->status ) {
$current_service = $this->get_tp_services()->get_current_service();
$this->status = new WPML_TM_ICL20_Migration_Status( $current_service );
}
return $this->status;
}
/**
* @return WPML_TM_ICL20_Migrate_Remote
*/
private function get_remote_migration() {
$http = $this->get_wp_http();
$token = new WPML_TM_ICL20_Token( $http, ICL_API_ENDPOINT );
$project = new WPML_TM_ICL20_Project( $http, OTG_TRANSLATION_PROXY_URL );
$ack = new WPML_TM_ICL20_Acknowledge( $http, ICL_API_ENDPOINT );
$container = new WPML_TM_ICL20_Migration_Container( $token, $project, $ack );
return new WPML_TM_ICL20_Migrate_Remote( $this->create_progress(), $container );
}
/**
* @return WPML_TM_ICL20_Migrate_Local
*/
private function get_local_migration() {
return new WPML_TM_ICL20_Migrate_Local(
$this->get_tp_services(),
$this->create_status(),
$this->create_progress(),
$this->get_sitepress()
);
}
/**
* @return WPML_TP_Services
*/
private function get_tp_services() {
if ( null === $this->tp_services ) {
$this->tp_services = new WPML_TP_Services();
}
return $this->tp_services;
}
/**
* @return WP_Http
*/
private function get_wp_http() {
if ( null === $this->wp_http ) {
$this->wp_http = new WP_Http();
}
return $this->wp_http;
}
/**
* @return SitePress
*/
private function get_sitepress() {
global $sitepress;
return $sitepress;
}
/**
* @return WPML_TM_ICL20_Migration_Notices
*/
public function create_notices() {
if ( null === $this->notices ) {
$this->notices = new WPML_TM_ICL20_Migration_Notices( $this->create_progress(), wpml_get_admin_notices() );
}
return $this->notices;
}
/**
* @return WPML_TM_ICL20_Migration_Support
*/
public function create_ui_support() {
$template_paths = array(
WPML_TM_PATH . '/templates/support/icl20/migration/',
);
$template_loader = new WPML_Twig_Template_Loader( $template_paths );
$template_service = $template_loader->get_template();
return new WPML_TM_ICL20_Migration_Support( $template_service, $this->create_progress(), $this->can_rollback() );
}
/**
* @return bool
*/
public function can_rollback() {
return defined( 'WP_DEBUG' )
&& defined( 'WPML_TP_ICL_20_ENABLE_ROLLBACK' )
&& WP_DEBUG
&& WPML_TP_ICL_20_ENABLE_ROLLBACK;
}
}

View File

@@ -0,0 +1,112 @@
<?php
/**
* @author OnTheGo Systems
*/
class WPML_TM_ICL20_Migration_Loader {
/** @var WPML_TM_ICL20_Migration_Factory */
private $factory;
/** @var WPML_TM_ICL20_Migration_Progress */
private $progress;
/** @var WPML_TM_ICL20_Migration_Status */
private $status;
/** @var WPML_WP_API */
private $wp_api;
/**
* WPML_TM_ICL20_Migration_Loader constructor.
*
* @param WPML_WP_API $wp_api
* @param WPML_TM_ICL20_Migration_Factory $factory
*/
public function __construct( WPML_WP_API $wp_api, WPML_TM_ICL20_Migration_Factory $factory ) {
$this->wp_api = $wp_api;
$this->factory = $factory;
}
/**
* This is the main method which deals with the whole logic for handling the migration
*/
public function run() {
$this->status = $this->factory->create_status();
$this->progress = $this->factory->create_progress();
$requires_migration = $this->requires_migration();
$notices = $this->factory->create_notices();
$notices->clear_migration_required();
if ( $this->status->has_active_service() ) {
$notices->run( $requires_migration );
}
if ( $requires_migration ) {
if ( ! $this->progress->get_user_confirmed() ) {
add_action(
'wp_ajax_' . WPML_TM_ICL20_Migration_Support::PREFIX . 'user_confirm',
array( $this->factory->create_ajax(), 'user_confirmation' )
);
return;
}
if ( $this->is_back_end() ) {
$this->maybe_fix_preferred_service();
$migration = $this->factory->create_migration();
if ( $this->factory->can_rollback() ) {
add_action(
'wpml_tm_icl20_migration_rollback',
array( $migration, 'migrate_project_rollback' )
);
}
$support = $this->factory->create_ui_support();
$support->add_hooks();
$support->parse_request();
if ( ! $this->progress->are_next_automatic_attempts_locked() ) {
$notices->run( ! $migration->run() );
}
if ( ! $this->progress->is_migration_done() ) {
$locks = $this->factory->create_locks();
$locks->add_hooks();
}
}
}
}
/** @return bool */
private function is_back_end() {
return $this->wp_api->is_admin()
&& ! $this->wp_api->is_ajax()
&& ! $this->wp_api->is_cron_job()
&& ! $this->wp_api->is_heartbeat();
}
/** @return bool */
private function requires_migration() {
if ( $this->status->has_active_legacy_icl() ) {
return true;
}
if ( $this->status->has_active_icl_20() ) {
if ( $this->progress->is_migration_incomplete() ) {
return true;
}
$this->progress->set_migration_done();
}
return false;
}
/**
* If the website is set to use a preferred translation service which is the legacy ICL, it will replace it with
* ICL2.0
*/
private function maybe_fix_preferred_service() {
if ( $this->status->is_preferred_service_legacy_ICL() ) {
$this->status->set_preferred_service_to_ICL20();
}
}
}

View File

@@ -0,0 +1,263 @@
<?php
/**
* @author OnTheGo Systems
*/
class WPML_TM_ICL20_Migration_Progress {
const MAX_AUTOMATIC_ATTEMPTS = 5;
const OPTION_KEY_USER_CONFIRMED = '_wpml_icl20_migration_user_confirmed';
const OPTION_KEY_MIGRATION_ATTEMPTS = '_wpml_icl20_migration_attempts';
const OPTION_KEY_MIGRATION_LAST_ATTEMPT = '_wpml_icl20_migration_last_attempt';
const OPTION_KEY_MIGRATION_LAST_ERROR = '_wpml_icl20_migration_last_error';
const OPTION_KEY_MIGRATION_LOCAL_PROJECT_INDEX = '_wpml_icl20_migration_local_project_index';
const OPTION_KEY_MIGRATION_LOCKED = '_wpml_icl20_migration_locked';
const OPTION_KEY_MIGRATION_REQUIRED = '_wpml_icl20_migration_required';
const OPTION_KEY_MIGRATION_STEPS = '_wpml_icl20_migration_step_%s';
const STEP_ICL_ACK = 'icl_ack';
const STEP_MIGRATE_JOBS_DOCUMENTS = 'migrate_jobs_doc';
const STEP_MIGRATE_JOBS_STRINGS = 'migrate_jobs_strings';
const STEP_MIGRATE_LOCAL_PROJECT = 'migrate_local_project';
const STEP_MIGRATE_LOCAL_SERVICE = 'migrate_local_service';
const STEP_MIGRATE_REMOTE_PROJECT = 'migrate_remote_project';
const STEP_TOKEN = 'token';
const STEP_FAILED = 'failed';
const STEP_DONE = 'done';
const VALUE_YES = 'yes';
const VALUE_NO = 'no';
/**
* @var array
*/
private $steps;
/**
* WPML_TM_ICL20_Migration_Progress constructor.
*/
public function __construct() {
$this->steps = array(
self::STEP_TOKEN,
self::STEP_MIGRATE_REMOTE_PROJECT,
self::STEP_ICL_ACK,
self::STEP_MIGRATE_LOCAL_SERVICE,
self::STEP_MIGRATE_LOCAL_PROJECT,
self::STEP_MIGRATE_JOBS_DOCUMENTS,
self::STEP_MIGRATE_JOBS_STRINGS,
);
}
/**
* @param string $step
*
* @return string|null
*/
public function get_completed_step( $step ) {
return get_option( sprintf( self::OPTION_KEY_MIGRATION_STEPS, $step ), self::STEP_FAILED );
}
/**
* @return int|null
*/
public function get_last_attempt_timestamp() {
return get_option( self::OPTION_KEY_MIGRATION_LAST_ATTEMPT, null );
}
/**
* @return string|null
*/
public function get_last_migration_error() {
return get_option( self::OPTION_KEY_MIGRATION_LAST_ERROR, null );
}
/**
* @return string|null
*/
public function get_project_to_migrate() {
return get_option( self::OPTION_KEY_MIGRATION_LOCAL_PROJECT_INDEX, null );
}
/**
* @return array
*/
public function get_steps() {
return $this->steps;
}
/**
* @param string $message
*/
public function log_failed_attempt( $message ) {
$this->update_last_error( $message );
}
/**
* @param string $message
*/
private function update_last_error( $message ) {
update_option( self::OPTION_KEY_MIGRATION_LAST_ERROR, $message, false );
}
/**
* @return bool
*/
public function is_migration_incomplete() {
return $this->get_current_attempts_count() > 0;
}
/**
* @param string $step
* @param string|bool $value
*/
public function set_completed_step( $step, $value ) {
$step_value = $value;
if ( is_bool( $value ) ) {
$step_value = $value ? self::STEP_DONE : self::STEP_FAILED;
}
update_option( sprintf( self::OPTION_KEY_MIGRATION_STEPS, $step ), $step_value, false );
}
/**
* @return bool
*/
public function has_migration_ever_started() {
$this->requires_migration();
$notoptions = wp_cache_get( 'notoptions', 'options' );
if ( isset( $notoptions[ self::OPTION_KEY_MIGRATION_REQUIRED ] ) ) {
return false;
}
return true;
}
/**
* It will mark the migration as done
*/
public function set_migration_done() {
update_option( self::OPTION_KEY_MIGRATION_REQUIRED, self::VALUE_NO, false );
$this->clear_temporary_options();
}
/**
* It will remove all the temporary options used to store the status of the migration
*/
public function clear_temporary_options() {
$options = array(
self::OPTION_KEY_MIGRATION_LOCKED,
self::OPTION_KEY_MIGRATION_LAST_ERROR,
self::OPTION_KEY_MIGRATION_ATTEMPTS,
self::OPTION_KEY_MIGRATION_LAST_ATTEMPT,
self::OPTION_KEY_MIGRATION_LOCAL_PROJECT_INDEX,
);
foreach ( $options as $option ) {
delete_option( $option );
}
foreach ( $this->steps as $step ) {
delete_option( sprintf( self::OPTION_KEY_MIGRATION_STEPS, $step ) );
}
}
/**
* @return bool
*/
public function is_migration_done() {
$result = true;
if ( $this->requires_migration() ) {
foreach ( $this->steps as $step ) {
if ( self::STEP_DONE !== get_option(
sprintf( self::OPTION_KEY_MIGRATION_STEPS, $step ),
self::STEP_FAILED
) ) {
$result = false;
break;
}
}
}
return $result;
}
/**
* @return bool
*/
public function requires_migration() {
return self::VALUE_YES === get_option( self::OPTION_KEY_MIGRATION_REQUIRED, self::VALUE_NO );
}
/**
* Sets the migration as started so to know, in the next attempts, if the migration was partial or never started.
*/
public function set_migration_started() {
update_option( self::OPTION_KEY_MIGRATION_REQUIRED, self::VALUE_YES, false );
$this->increase_attempts_count();
}
/**
* It will increases on every migration attempt
*/
private function increase_attempts_count() {
update_option(
self::OPTION_KEY_MIGRATION_ATTEMPTS,
$this->get_current_attempts_count() + 1,
false
);
update_option(
self::OPTION_KEY_MIGRATION_LAST_ATTEMPT,
time(),
false
);
if ( $this->has_too_many_automatic_attempts() ) {
$this->block_next_automatic_attempts();
}
}
/**
* @return int
*/
public function get_current_attempts_count() {
return (int) get_option( self::OPTION_KEY_MIGRATION_ATTEMPTS, 0 );
}
/**
* @return bool
*/
public function has_too_many_automatic_attempts() {
return $this->get_current_attempts_count() >= self::MAX_AUTOMATIC_ATTEMPTS
|| $this->are_next_automatic_attempts_locked();
}
/**
* Used when too many attempts are made
*/
private function block_next_automatic_attempts() {
update_option( self::OPTION_KEY_MIGRATION_LOCKED, self::VALUE_YES, false );
}
/**
* @return bool
*/
public function are_next_automatic_attempts_locked() {
return self::VALUE_YES === get_option( self::OPTION_KEY_MIGRATION_LOCKED, self::VALUE_NO );
}
/**
* @param string $old_index
*/
public function set_project_to_migrate( $old_index ) {
update_option( self::OPTION_KEY_MIGRATION_LOCAL_PROJECT_INDEX, $old_index, false );
}
/**
* @return bool
*/
public function get_user_confirmed() {
return self::VALUE_YES === get_option( self::OPTION_KEY_USER_CONFIRMED, self::VALUE_NO );
}
/**
* User as an opt-in action from the user before starting the migration
*/
public function set_user_confirmed() {
update_option( self::OPTION_KEY_USER_CONFIRMED, self::VALUE_YES, false );
}
}

View File

@@ -0,0 +1,122 @@
<?php
/**
* @author OnTheGo Systems
*/
class WPML_TM_ICL20_Migration_Status {
const ICL_20_TS_ID = 67;
const ICL_LEGACY_TS_ID = 4;
const ICL_LEGACY_TS_SUID = '6ab1000a33e2cc9ecbcf6abc57254be8';
const ICL_20_TS_SUID = 'dd17d48516ca4bce0b83043583fabd2e';
private $installer_settings = array();
private $service;
public function __construct( $service ) {
$this->service = $service;
}
public function has_active_legacy_icl() {
return $this->has_active_service() && $this->get_ICL_LEGACY_TS_ID() === $this->service->id;
}
public function has_active_icl_20() {
return $this->has_active_service() && $this->get_ICL_20_TS_ID() === $this->service->id;
}
public function has_active_service() {
return (bool) $this->service;
}
public function get_ICL_LEGACY_TS_ID() {
if ( defined( 'WPML_TP_ICL_LEGACY_TS_ID' ) ) {
return WPML_TP_ICL_LEGACY_TS_ID;
}
return self::ICL_LEGACY_TS_ID;
}
public function get_ICL_20_TS_ID() {
if ( defined( 'WPML_TP_ICL_20_TS_ID' ) ) {
return WPML_TP_ICL_20_TS_ID;
}
return self::ICL_20_TS_ID;
}
public function get_ICL_LEGACY_TS_SUID() {
if ( defined( 'WPML_TP_ICL_LEGACY_TS_SUID' ) ) {
return WPML_TP_ICL_LEGACY_TS_SUID;
}
return self::ICL_LEGACY_TS_SUID;
}
public function get_ICL_20_TS_SUID() {
if ( defined( 'WPML_TP_ICL_20_TS_SUID' ) ) {
return WPML_TP_ICL_20_TS_SUID;
}
return self::ICL_20_TS_SUID;
}
public function is_preferred_service_legacy_ICL() {
return $this->has_preferred_service() && self::ICL_LEGACY_TS_SUID === $this->get_preferred_service();
}
public function set_preferred_service_to_ICL20() {
if ( $this->get_preferred_service() ) {
$this->installer_settings['repositories']['wpml']['ts_info']['preferred'] = $this->get_ICL_20_TS_SUID();
$this->update_installer_settings();
}
}
private function has_preferred_service() {
return ! in_array( $this->get_preferred_service(), array( 'clear', false ), true );
}
private function get_preferred_service() {
$installer_settings = $this->get_installer_settings();
if ( isset( $installer_settings['repositories']['wpml']['ts_info']['preferred'] )
&& 'clear' !== $installer_settings['repositories']['wpml']['ts_info']['preferred'] ) {
return $installer_settings['repositories']['wpml']['ts_info']['preferred'];
}
return false;
}
/**
* @return array
*/
private function get_installer_settings() {
if ( ! $this->installer_settings ) {
$raw_settings = get_option( 'wp_installer_settings', null );
if ( $raw_settings ) {
if ( is_array( $raw_settings ) || empty( $raw_settings ) ) { // backward compatibility 1.1
$this->installer_settings = $raw_settings;
} else {
$has_gz_support = function_exists( 'gzuncompress' ) && function_exists( 'gzcompress' );
$raw_settings = base64_decode( $raw_settings );
if ( $has_gz_support ) {
$raw_settings = gzuncompress( $raw_settings );
}
/** @noinspection UnserializeExploitsInspection */
$this->installer_settings = unserialize( $raw_settings );
}
}
}
return $this->installer_settings;
}
private function update_installer_settings() {
$has_gz_support = function_exists( 'gzuncompress' ) && function_exists( 'gzcompress' );
$raw_settings = serialize( $this->installer_settings );
if ( $has_gz_support ) {
$raw_settings = gzcompress( $raw_settings );
}
$raw_settings = base64_encode( $raw_settings );
update_option( 'wp_installer_settings', $raw_settings );
}
}

View File

@@ -0,0 +1,55 @@
<?php
/**
* @author OnTheGo Systems
*/
class WPML_TM_ICL20_Acknowledge {
private $end_point;
private $http;
/**
* WPML_TM_ICL20 constructor.
*
* @param WP_Http $http
* @param string $end_point
*/
public function __construct( WP_Http $http, $end_point ) {
$this->http = $http;
$this->end_point = $end_point;
}
/**
* @param string $ts_accesskey
* @param int $ts_id
*
* @return bool
* @throws \WPML_TM_ICL20MigrationException
*
* Note: `ts_id` (aka `website_id`) = `website_id`
*
* @link https://onthegosystems.myjetbrains.com/youtrack/issue/icldev-2322
*/
public function acknowledge_icl( $ts_id, $ts_accesskey ) {
$url = $this->end_point . '/wpml/websites/' . $ts_id . '/migrated';
$url = add_query_arg( array(
'accesskey' => $ts_accesskey,
),
$url );
$response = $this->http->post( $url,
array(
'method' => 'POST',
'headers' => array(
'Accept' => 'application/json',
'Content-Type' => 'application/json',
),
) );
$code = (int) $response['response']['code'];
if ( $code !== 200 ) {
throw new WPML_TM_ICL20MigrationException( $response['response']['message'], $code );
}
return true;
}
}

View File

@@ -0,0 +1,41 @@
<?php
/**
* @author OnTheGo Systems
*/
class WPML_TM_ICL20_Migration_Container {
private $acknowledge;
private $project;
private $token;
public function __construct(
WPML_TM_ICL20_Token $token,
WPML_TM_ICL20_Project $project,
WPML_TM_ICL20_Acknowledge $ack
) {
$this->token = $token;
$this->project = $project;
$this->acknowledge = $ack;
}
/**
* @return WPML_TM_ICL20_Acknowledge
*/
public function get_acknowledge() {
return $this->acknowledge;
}
/**
* @return WPML_TM_ICL20_Project
*/
public function get_project() {
return $this->project;
}
/**
* @return WPML_TM_ICL20_Token
*/
public function get_token() {
return $this->token;
}
}

View File

@@ -0,0 +1,102 @@
<?php
/**
* @author OnTheGo Systems
*/
class WPML_TM_ICL20_Project {
private $end_point;
private $http;
/**
* WPML_TM_ICL20 constructor.
*
* @param WP_Http $http
* @param string $end_point
*/
public function __construct( WP_Http $http, $end_point ) {
$this->http = $http;
$this->end_point = $end_point;
}
/**
* @param int $project_id
* @param string $access_key
* @param string $new_token
*
* @return bool|null
* @throws \WPML_TM_ICL20MigrationException
* @link https://onthegosystems.myjetbrains.com/youtrack/issue/tsapi-887
*
*/
public function migrate( $project_id, $access_key, $new_token ) {
$url = $this->end_point . '/projects/' . $project_id . '/migrate_service.json';
$args = array(
'method' => 'POST',
'headers' => array(
'Accept' => 'application/json',
'Content-Type' => 'application/json',
),
'body' => wp_json_encode( array(
'accesskey' => $access_key,
'custom_fields' => array(
'api_token' => $new_token,
)
) )
);
$response = $this->http->post( $url, $args );
$code = (int) $response['response']['code'];
if ( $code !== 200 ) {
$message = $response['response']['message'];
if ( array_key_exists( 'body', $response ) ) {
$body = json_decode( $response['body'], JSON_OBJECT_AS_ARRAY );
if ( isset( $body['status']['message'] ) ) {
$message .= PHP_EOL . $body['status']['message'];
}
}
throw new WPML_TM_ICL20MigrationException( $message, $code );
}
return true;
}
/**
* @param int $project_id
* @param string $access_key
*
* @return bool
* @throws WPML_TM_ICL20MigrationException
*/
public function rollback_migration( $project_id, $access_key ) {
$url = $this->end_point . '/projects/' . $project_id . '/rollback_migration.json';
$args = array(
'method' => 'POST',
'headers' => array(
'Accept' => 'application/json',
'Content-Type' => 'application/json',
),
'body' => wp_json_encode( array( 'accesskey' => $access_key ) )
);
$response = $this->http->post( $url, $args );
$code = (int) $response['response']['code'];
if ( $code !== 200 ) {
$message = $response['response']['message'];
if ( array_key_exists( 'body', $response ) ) {
$body = json_decode( $response['body'], JSON_OBJECT_AS_ARRAY );
if ( isset( $body['status']['message'] ) ) {
$message .= PHP_EOL . $body['status']['message'];
}
}
throw new WPML_TM_ICL20MigrationException( $message, $code );
}
return true;
}
}

View File

@@ -0,0 +1,70 @@
<?php
/**
* @author OnTheGo Systems
*/
class WPML_TM_ICL20_Token {
private $end_point;
private $http;
/**
* WPML_TM_ICL20 constructor.
*
* @param WP_Http $http
* @param string $end_point
*/
public function __construct( WP_Http $http, $end_point ) {
$this->http = $http;
$this->end_point = $end_point;
}
/**
* @param string $ts_accesskey
* @param int $ts_id
*
* @return string|null
* @throws \WPML_TM_ICL20MigrationException
*
* Note: `ts_id` (aka `website_id`) = `website_id`
*
* @link https://onthegosystems.myjetbrains.com/youtrack/issue/icldev-2285
*/
public function get_token( $ts_id, $ts_accesskey ) {
if ( ! $ts_id ) {
throw new WPML_TM_ICL20MigrationException( 'Missing ICL Website ID ($ts_id)' );
}
if ( ! $ts_accesskey ) {
throw new WPML_TM_ICL20MigrationException( 'Missing ICL Access KEY ($ts_accesskey)' );
}
$url = $this->end_point . '/wpml/websites/' . $ts_id . '/token';
$url = add_query_arg( array(
'accesskey' => $ts_accesskey,
),
$url );
$response = $this->http->get( $url,
array(
'method' => 'GET',
'headers' => array(
'Accept: application/json'
),
) );
$code = (int) $response['response']['code'];
if ( 200 !== $code ) {
throw new WPML_TM_ICL20MigrationException( $response['response']['message'], $code );
}
if ( array_key_exists( 'body', $response ) ) {
$response_data = json_decode( $response['body'], JSON_OBJECT_AS_ARRAY );
if ( array_key_exists( 'api_token', $response_data )
&& '' !== trim( $response_data['api_token'] ) ) {
return $response_data['api_token'];
}
}
return null;
}
}

View File

@@ -0,0 +1,46 @@
/*globals jQuery, ajaxurl */
jQuery(function () {
'use strict';
var notice = jQuery('[data-id="icl-20-migration"][data-group="icl-20-migration"]');
var confirm;
var startButton;
var updateButton = function () {
if (confirm.prop('checked')) {
startButton.removeClass('disabled');
startButton.on('click', userConfirms);
} else {
startButton.addClass('disabled');
startButton.off('click');
}
};
var userConfirms = function (e) {
e.preventDefault();
e.stopPropagation();
if (confirm.prop('checked')) {
jQuery.ajax(ajaxurl, {
method: 'POST',
data: {
action: confirm.data('action'),
nonce: confirm.data('nonce')
},
complete: function () {
location.reload();
}
});
}
};
if (notice.length) {
confirm = notice.find('#wpml-icl20-migrate-confirm');
startButton = notice.find('.notice-action.button-secondary.notice-action-button-secondary');
if (confirm.length && startButton.length) {
updateButton();
confirm.on('click', updateButton);
}
}
});

View File

@@ -0,0 +1,18 @@
<?php
/**
* @author OnTheGo Systems
*/
class WPML_TM_ICL20_Migration_Locks {
private $progress;
public function __construct( WPML_TM_ICL20_Migration_Progress $progress ) {
$this->progress = $progress;
}
public function add_hooks() {
if ( ! $this->progress->is_migration_done() ) {
add_filter( 'wpml_tm_lock_ui', '__return_true' );
}
}
}

View File

@@ -0,0 +1,285 @@
<?php
/**
* @author OnTheGo Systems
*/
class WPML_TM_ICL20_Migration_Notices {
const NOTICE_GROUP = 'icl-20-migration';
const NOTICE_MIGRATION_REQUIRED_ID = 'icl-20-migration';
const NOTICE_MIGRATION_COMPLETED_ID = 'icl-20-migration-completed';
/**
* @var WPML_Notices
*/
private $notices;
/**
* @var WPML_TM_ICL20_Migration_Progress
*/
private $progress;
/**
* WPML_TM_ICL20_Migration_Notices constructor.
*
* @param WPML_TM_ICL20_Migration_Progress $progress
* @param WPML_Notices $notices
*/
public function __construct( WPML_TM_ICL20_Migration_Progress $progress, WPML_Notices $notices ) {
$this->progress = $progress;
$this->notices = $notices;
}
/**
* @param bool $requires_migration
*/
public function run( $requires_migration = false ) {
$this->clear_migration_required();
$ever_started = $this->progress->has_migration_ever_started();
if ( $ever_started && ! $this->progress->requires_migration() ) {
$this->build_migration_completed();
} else {
if ( ! $ever_started
&& $requires_migration
&& ! $this->progress->is_migration_incomplete() ) {
$this->build_migration_required();
add_action( 'wpml-notices-scripts-enqueued', array( $this, 'admin_enqueue_scripts' ) );
return;
}
if ( $ever_started && ! $this->progress->is_migration_done() ) {
$this->build_migration_failed();
return;
}
}
}
/**
* Clear all notices created before and during the migration
*/
public function clear_migration_required() {
$this->notices->remove_notice( self::NOTICE_GROUP, self::NOTICE_MIGRATION_REQUIRED_ID );
}
/**
* Builds the notice shown if the migration fails
*/
private function build_migration_failed() {
$message = array();
$actions = array();
$title = '<h3>' . esc_html__(
'ICanLocalize migration could not complete',
'wpml-translation-management'
) . '</h3>';
$message[] = esc_html__(
'WPML needs to update your connection to ICanLocalize, but could not complete the change.',
'wpml-translation-management'
);
$locked = $this->progress->are_next_automatic_attempts_locked();
if ( $locked ) {
$message[] = esc_html__(
'Please contact WPML support and give them the following debug information:',
'wpml-translation-management'
);
$error = '<pre>';
foreach ( $this->progress->get_steps() as $step ) {
$completed_step = $this->progress->get_completed_step( $step );
if ( ! $completed_step || WPML_TM_ICL20_Migration_Progress::STEP_FAILED === $completed_step ) {
$error .= esc_html(
sprintf(
__(
'Failed step: %s',
'wpml-translation-management'
),
$step
)
) . PHP_EOL;
break;
}
}
$error .= esc_html( $this->progress->get_last_migration_error() );
$error .= '</pre>';
$message[] = $error;
} else {
$message[] = esc_html__(
'Please wait a few minutes and try again to see if theres a temporary problem.',
'wpml-translation-management'
);
}
$text = $title . '<p>' . implode( '</p><p>', $message ) . '</p>';
$button_label = __( 'Try again', 'wpml-translation-management' );
$button_url = add_query_arg(
array(
WPML_TM_ICL20_Migration_Support::PREFIX
. 'nonce' => wp_create_nonce(
WPML_TM_ICL20_Migration_Support::PREFIX
. 'reset'
),
WPML_TM_ICL20_Migration_Support::PREFIX
. 'action' => WPML_TM_ICL20_Migration_Support::PREFIX
. 'reset',
)
) . '#icl20-migration';
$retry_action = $this->notices->get_new_notice_action( $button_label, $button_url, false, false, true );
$actions[] = $retry_action;
if ( $locked ) {
$wpml_support_action = $this->notices->get_new_notice_action(
__(
'WPML Support',
'wpml-translation-management'
),
'https://wpml.org/forums/'
);
$wpml_support_action->set_link_target( '_blank' );
$actions[] = $wpml_support_action;
} else {
$support_url = add_query_arg(
array(
'page' => WPML_PLUGIN_FOLDER . '/menu/support.php',
),
admin_url( 'admin.php' )
) . '#icl20-migration';
$action = $this->notices->get_new_notice_action(
__(
'Error details',
'wpml-translation-management'
),
$support_url
);
$actions[] = $action;
}
$this->create_notice( $text, $actions );
}
/**
* Builds the notice shown when the migration is required
*/
private function build_migration_required() {
$message = array();
$actions = array();
$link_pattern = '<a href="%1$s" target="_blank">%2$s</a>';
$ask_us_link = sprintf(
$link_pattern,
'https://wpml.org/forums/topic/im-not-sure-if-i-need-to-run-icanlocalize-migration/?utm_source=plugin&utm_medium=gui&utm_campaign=wpmltm',
esc_html__( 'Ask us', 'wpml-translation-management' )
);
$button_label = esc_html__( 'Start the update', 'wpml-translation-management' );
$title = '<h3>WPML needs to update your ICanLocalize account settings</h3>';
$message[] = esc_html__(
'WPML 3.9 changes the way it works with ICanLocalize. This requires WPML to move to a new interface with ICanLocalize.',
'wpml-translation-management'
);
$message[] = esc_html__(
'If you are in a production site, you have to run this update before you can send more content for translation and receive completed translations.',
'wpml-translation-management'
);
$message[] = esc_html__(
"If this is not your production site (it's a staging or testing site), please do not run the update.",
'wpml-translation-management'
);
$message[] = esc_html__(
'Running this update on a non-production site will make it impossible to correctly run it on the production site.',
'wpml-translation-management'
);
$message[] = '';
$message[] = sprintf( esc_html__( 'Not sure? %s.', 'wpml-translation-management' ), $ask_us_link );
$message[] = '';
$message[] = $this->get_user_confirmation_input();
$text = $title . '<p>' . implode( '</p><p>', $message ) . '</p>';
$actions[] = $this->notices->get_new_notice_action( $button_label, '#', false, false, true );
$this->create_notice( $text, $actions );
}
/**
* @param $text
* @param array $actions
*/
private function create_notice( $text, array $actions = array() ) {
$notice = $this->notices->create_notice( self::NOTICE_MIGRATION_REQUIRED_ID, $text, self::NOTICE_GROUP );
$notice->set_css_class_types( array( 'error' ) );
$notice->set_exclude_from_pages(
array(
'sitepress-multilingual-cms/menu/support.php',
)
);
foreach ( $actions as $action ) {
$notice->add_action( $action );
}
$this->notices->add_notice( $notice );
}
/**
* Builds the notice shown when the migration completes
*/
private function build_migration_completed() {
$message = array();
$message[] = esc_html__(
'WPML updated your connection to ICanLocalize. You can continue sending content to translation.',
'wpml-translation-management'
);
$text = '<p>' . implode( '</p><p>', $message ) . '</p>';
$notice = $this->notices->create_notice( self::NOTICE_MIGRATION_COMPLETED_ID, $text, self::NOTICE_GROUP );
$notice->set_css_class_types( array( 'warning' ) );
$notice->set_exclude_from_pages(
array(
'sitepress-multilingual-cms/menu/support.php',
)
);
$notice->set_dismissible( true );
$this->notices->add_notice( $notice );
}
/**
* Required by `\WPML_TM_ICL20_Migration_Notices::build_migration_required`
*/
public function admin_enqueue_scripts() {
wp_enqueue_script(
'wpml-icl20-migrate-confirm',
WPML_TM_URL . '/classes/ICL-20-migration/res/migration-required.js'
);
}
/**
* @return string
*/
private function get_user_confirmation_input() {
$id = 'wpml-icl20-migrate-confirm';
$label = esc_html__( 'This is indeed my production site', 'wpml-translation-management' );
$data_action = esc_attr( WPML_TM_ICL20_Migration_Support::PREFIX . 'user_confirm' );
$data_nonce = esc_attr( wp_create_nonce( WPML_TM_ICL20_Migration_Support::PREFIX . 'user_confirm' ) );
$html_pattern = '<input type="checkbox" value="1" id="%1$s" data-action="%2$s" data-nonce="%3$s"><label for="%1$s">%4$s</label>';
return sprintf( $html_pattern, $id, $data_action, $data_nonce, $label );
}
}

View File

@@ -0,0 +1,99 @@
<?php
/**
* @author OnTheGo Systems
*/
class WPML_TM_ICL20_Migration_Support {
const PREFIX = 'icl20-migration-reset-';
const TIMESTAMP_FORMAT = 'Y-m-d H:i:s';
private $can_rollback;
private $progress;
private $template_service;
function __construct(
IWPML_Template_Service $template_service,
WPML_TM_ICL20_Migration_Progress $progress,
$can_rollback = false
) {
$this->template_service = $template_service;
$this->progress = $progress;
$this->can_rollback = $can_rollback;
}
function add_hooks() {
add_action( 'wpml_support_page_after', array( $this, 'show' ) );
}
public function parse_request() {
$nonce_arg = self::PREFIX . 'nonce';
$action_arg = self::PREFIX . 'action';
if ( array_key_exists( $nonce_arg, $_GET ) && array_key_exists( $action_arg, $_GET ) ) {
$nonce = filter_var( $_GET[ $nonce_arg ] );
$action = filter_var( $_GET[ $action_arg ] );
if ( wp_verify_nonce( $nonce, $action ) ) {
if ( self::PREFIX . 'reset' === $action ) {
update_option( WPML_TM_ICL20_Migration_Progress::OPTION_KEY_MIGRATION_LOCKED, false, false );
}
if ( self::PREFIX . 'rollback' === $action && $this->can_rollback ) {
do_action( 'wpml_tm_icl20_migration_rollback' );
}
}
$redirect_to = remove_query_arg( array( $nonce_arg, $action_arg ) );
wp_safe_redirect( $redirect_to, 302, 'WPML' );
}
}
public function show() {
$model = $this->get_model();
echo $this->template_service->show( $model, 'main.twig' );
}
private function get_model() {
$reset_target_url = add_query_arg( array(
self::PREFIX . 'nonce' => wp_create_nonce( self::PREFIX . 'reset' ),
self::PREFIX . 'action' => self::PREFIX . 'reset',
) );
$reset_target_url .= '#icl20-migration';
$model = array(
'title' => __( 'Migration to ICL 2.0', 'wpml-translation-management' ),
'data' => array(
__( 'Number of attempts made',
'wpml-translation-management' ) => $this->progress->get_current_attempts_count(),
__( 'Last attempt was on',
'wpml-translation-management' ) => date( self::TIMESTAMP_FORMAT,
$this->progress->get_last_attempt_timestamp() ),
__( 'Last error', 'wpml-translation-management' ) => $this->progress->get_last_migration_error(),
),
'buttons' => array(
'reset' => array(
'type' => 'primary',
'label' => __( 'Try again', 'wpml-translation-management' ),
'url' => $reset_target_url,
),
),
);
if ( $this->can_rollback ) {
$rollback_target_url = add_query_arg( array(
self::PREFIX . 'nonce' => wp_create_nonce( self::PREFIX
. 'rollback' ),
self::PREFIX . 'action' => self::PREFIX . 'rollback',
) );
$model['buttons']['rollback'] = array(
'type' => 'secondary',
'label' => __( 'Rollback migration (use at your own risk!)',
'wpml-translation-management' ),
'url' => $rollback_target_url,
);
}
return $model;
}
}