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,99 @@
<?php
namespace WPML\ST\Upgrade\Command;
use WPML\Element\API\Languages;
use WPML\FP\Cast;
use WPML\FP\Fns;
use WPML\FP\Logic;
use WPML\FP\Lst;
use WPML\FP\Obj;
use WPML\FP\Relation;
use WPML\FP\Str;
use WPML\LIB\WP\Option;
use WPML\ST\MO\File\ManagerFactory;
use function WPML\FP\partial;
use function WPML\FP\pipe;
class MigrateMultilingualWidgets implements \IWPML_St_Upgrade_Command {
public function run() {
$multiLingualWidgets = Option::getOr( 'widget_text_icl', [] );
$multiLingualWidgets = array_filter( $multiLingualWidgets, Logic::complement( 'is_scalar' ) );
if ( ! $multiLingualWidgets ) {
return true;
}
$textWidgets = Option::getOr( 'widget_text', [] );
if ( $textWidgets ) {
$theHighestTextWidgetId = max( Obj::keys( $textWidgets ) );
} else {
$theHighestTextWidgetId = 0;
$textWidgets['_multiwidget'] = 1;
}
$transformWidget = pipe(
Obj::renameProp( 'icl_language', 'wpml_language' ),
Obj::over( Obj::lensProp( 'wpml_language' ), Logic::ifElse( Relation::equals( 'multilingual' ), Fns::always( 'all' ), Fns::identity() ) )
);
$oldToNewIdMap = [];
foreach ( $multiLingualWidgets as $id => $widget ) {
$newId = ++ $theHighestTextWidgetId;
$oldToNewIdMap[ $id ] = $newId;
$textWidgets = Obj::assoc( $newId, $transformWidget( $widget ), $textWidgets );
}
Option::update( 'widget_text', $textWidgets );
Option::delete( 'widget_text_icl' );
$sidebars = wp_get_sidebars_widgets();
$sidebars = $this->convertSidebarsConfig( $sidebars, $oldToNewIdMap );
wp_set_sidebars_widgets( $sidebars );
$this->convertWidgetsContentStrings();
return true;
}
private function convertSidebarsConfig( $sidebars, array $oldToNewIdMap ) {
$isMultilingualWidget = Str::startsWith( 'text_icl' );
$extractIdNumber = pipe( Str::split( '-' ), Lst::last(), Cast::toInt() );
$mapWidgetId = Logic::ifElse(
$isMultilingualWidget,
pipe( $extractIdNumber, Obj::prop( Fns::__, $oldToNewIdMap ), Str::concat( 'text-' ) ),
Fns::identity()
);
return Fns::map( Fns::map( $mapWidgetId ), $sidebars );
}
private function convertWidgetsContentStrings() {
global $wpdb;
$wpdb->query("
UPDATE {$wpdb->prefix}icl_strings
SET `name` = CONCAT( 'widget body - ', MD5(`value`))
WHERE `name` LIKE 'widget body - text_icl%'
");
$locales = Fns::map( Languages::getWPLocale(), Languages::getSecondaries() );
Fns::map( partial( [ ManagerFactory::create(), 'add' ], 'Widgets' ), $locales );
}
public function run_ajax() {
}
public function run_frontend() {
}
public static function get_command_id() {
return __CLASS__;
}
}

View File

@@ -0,0 +1,76 @@
<?php
namespace WPML\ST\Upgrade\Command;
use WPML\ST\MO\File\Manager;
use WPML\ST\MO\Generate\Process\SingleSiteProcess;
use WPML\ST\MO\Generate\Process\Status;
use WPML\ST\MO\Notice\RegenerationInProgressNotice;
use WPML_Installation;
use function WPML\Container\make;
class RegenerateMoFilesWithStringNames implements \IWPML_St_Upgrade_Command {
const WPML_VERSION_FOR_THIS_COMMAND = '4.3.4';
/** @var Status $status */
private $status;
/** @var SingleSiteProcess $singleProcess */
private $singleProcess;
/**
* @param Status $status
* @param SingleSiteProcess $singleProcess We use run the single site process because
* the migration command runs once per site.
*/
public function __construct( Status $status, SingleSiteProcess $singleProcess ) {
$this->status = $status;
$this->singleProcess = $singleProcess;
}
public function run() {
if ( ! ( $this->hasWpmlStartedBeforeThisCommand() && Manager::hasFiles() ) ) {
$this->status->markComplete();
return true;
}
$this->singleProcess->runPage();
if ( $this->singleProcess->isCompleted() ) {
\wpml_get_admin_notices()->remove_notice(
RegenerationInProgressNotice::GROUP,
RegenerationInProgressNotice::ID
);
return true;
}
\wpml_get_admin_notices()->add_notice( make( RegenerationInProgressNotice::class ) );
return false;
}
/**
* @return bool
*/
private function hasWpmlStartedBeforeThisCommand() {
return (bool) version_compare(
get_option( WPML_Installation::WPML_START_VERSION_KEY, '0.0.0' ),
self::WPML_VERSION_FOR_THIS_COMMAND,
'<'
);
}
public function run_ajax() {
}
public function run_frontend() {
}
public static function get_command_id() {
return __CLASS__;
}
}

View File

@@ -0,0 +1,92 @@
<?php
/**
* WPML_ST_Upgrade_Command_Factory class file.
*
* @package wpml-string-translation
*/
use function WPML\Container\make;
use WPML\ST\Upgrade\Command\RegenerateMoFilesWithStringNames;
use WPML\ST\Upgrade\Command\MigrateMultilingualWidgets;
/**
* Class WPML_ST_Upgrade_Command_Factory
*/
class WPML_ST_Upgrade_Command_Factory {
/**
* WP db instance.
*
* @var wpdb wpdb
*/
private $wpdb;
/**
* SitePress instance.
*
* @var SitePress
*/
private $sitepress;
/**
* WPML_ST_Upgrade_Command_Factory constructor.
*
* @param wpdb $wpdb WP db instance.
* @param SitePress $sitepress SitePress instance.
*/
public function __construct( wpdb $wpdb, SitePress $sitepress ) {
$this->wpdb = $wpdb;
$this->sitepress = $sitepress;
}
/**
* Create upgrade commands.
*
* @param string $class_name Name of upgrade command class.
*
* @throws WPML_ST_Upgrade_Command_Not_Found_Exception Exception when command not found.
* @return IWPML_St_Upgrade_Command
*/
public function create( $class_name ) {
switch ( $class_name ) {
case 'WPML_ST_Upgrade_Migrate_Originals':
$result = new WPML_ST_Upgrade_Migrate_Originals( $this->wpdb, $this->sitepress );
break;
case 'WPML_ST_Upgrade_Display_Strings_Scan_Notices':
$themes_and_plugins_settings = new WPML_ST_Themes_And_Plugins_Settings();
$result = new WPML_ST_Upgrade_Display_Strings_Scan_Notices( $themes_and_plugins_settings );
break;
case 'WPML_ST_Upgrade_DB_String_Packages':
$result = new WPML_ST_Upgrade_DB_String_Packages( $this->wpdb );
break;
case 'WPML_ST_Upgrade_MO_Scanning':
$result = new WPML_ST_Upgrade_MO_Scanning( $this->wpdb );
break;
case 'WPML_ST_Upgrade_DB_String_Name_Index':
$result = new WPML_ST_Upgrade_DB_String_Name_Index( $this->wpdb );
break;
case 'WPML_ST_Upgrade_DB_Longtext_String_Value':
$result = new WPML_ST_Upgrade_DB_Longtext_String_Value( $this->wpdb );
break;
case 'WPML_ST_Upgrade_DB_Strings_Add_Translation_Priority_Field':
$result = new WPML_ST_Upgrade_DB_Strings_Add_Translation_Priority_Field( $this->wpdb );
break;
case 'WPML_ST_Upgrade_DB_String_Packages_Word_Count':
$result = new WPML_ST_Upgrade_DB_String_Packages_Word_Count( wpml_get_upgrade_schema() );
break;
case '\WPML\ST\Upgrade\Command\RegenerateMoFilesWithStringNames':
$isBackground = true;
$result = new RegenerateMoFilesWithStringNames(
\WPML\ST\MO\Generate\Process\ProcessFactory::createStatus( $isBackground ),
\WPML\ST\MO\Generate\Process\ProcessFactory::createSingle( $isBackground )
);
break;
case MigrateMultilingualWidgets::class:
$result = new MigrateMultilingualWidgets();
break;
default:
throw new WPML_ST_Upgrade_Command_Not_Found_Exception( $class_name );
}
return $result;
}
}

View File

@@ -0,0 +1,14 @@
<?php
class WPML_ST_Upgrade_Command_Not_Found_Exception extends InvalidArgumentException {
/**
* @param string $class_name
* @param int $code
* @param Exception $previous
*/
public function __construct( $class_name, $code = 0, Exception $previous = null ) {
$msg = sprintf( 'Class %s is not valid String Translation upgrade strategy', $class_name );
parent::__construct( $msg, $code, $previous );
}
}

View File

@@ -0,0 +1,86 @@
<?php
/**
* WPML_ST_Upgrade_DB_Longtext_String_Value class file.
*
* @package wpml-string-translation
*/
/**
* Class WPML_ST_Upgrade_DB_Longtext_String_Value
*/
class WPML_ST_Upgrade_DB_Longtext_String_Value implements IWPML_St_Upgrade_Command {
/**
* WP db instance.
*
* @var wpdb
*/
private $wpdb;
/**
* WPML_ST_Upgrade_DB_Longtext_String_Value constructor.
*
* @param wpdb $wpdb WP db instance.
*/
public function __construct( wpdb $wpdb ) {
$this->wpdb = $wpdb;
}
/**
* Run upgrade.
*
* @return bool
*/
public function run() {
$result = true;
$table_name = $this->wpdb->prefix . 'icl_strings';
if ( count( (array) $this->wpdb->get_results( "SHOW TABLES LIKE '{$table_name}'" ) ) ) {
$sql = "
ALTER TABLE {$table_name}
MODIFY COLUMN `value` LONGTEXT NOT NULL;
";
$result = false !== $this->wpdb->query( $sql );
}
$table_name = $this->wpdb->prefix . 'icl_string_translations';
if ( count( (array) $this->wpdb->get_results( "SHOW TABLES LIKE '{$table_name}'" ) ) ) {
$sql = "
ALTER TABLE {$table_name}
MODIFY COLUMN `value` LONGTEXT NULL DEFAULT NULL,
MODIFY COLUMN `mo_string` LONGTEXT NULL DEFAULT NULL;
";
$result = ( false !== $this->wpdb->query( $sql ) ) && $result;
}
return $result;
}
/**
* Run upgrade in ajax.
*
* @return bool
*/
public function run_ajax() {
return $this->run();
}
/**
* Run upgrade on frontend.
*
* @return bool
*/
public function run_frontend() {
return $this->run();
}
/**
* Get command id.
*
* @return string
*/
public static function get_command_id() {
return __CLASS__;
}
}

View File

@@ -0,0 +1,44 @@
<?php
class WPML_ST_Upgrade_DB_String_Name_Index implements IWPML_St_Upgrade_Command {
/** @var wpdb */
private $wpdb;
/**
* @param wpdb $wpdb
*/
public function __construct( wpdb $wpdb ) {
$this->wpdb = $wpdb;
}
public function run() {
$result = true;
$table_name = $this->wpdb->prefix . 'icl_strings';
if ( 0 !== count( $this->wpdb->get_results( "SHOW TABLES LIKE '{$table_name}'" ) ) ) {
$sql = "SHOW KEYS FROM {$table_name} WHERE Key_name='icl_strings_name'";
if ( 0 === count( $this->wpdb->get_results( $sql ) ) ) {
$sql = "
ALTER TABLE {$this->wpdb->prefix}icl_strings
ADD INDEX `icl_strings_name` (`name` ASC);
";
$result = false !== $this->wpdb->query( $sql );
}
}
return $result;
}
public function run_ajax() {
$this->run();
}
public function run_frontend() {
$this->run();
}
public static function get_command_id() {
return __CLASS__ . '_2';
}
}

View File

@@ -0,0 +1,41 @@
<?php
class WPML_ST_Upgrade_DB_String_Packages_Word_Count implements IWPML_St_Upgrade_Command {
/** @var WPML_Upgrade_Schema $upgrade_schema */
private $upgrade_schema;
public function __construct( WPML_Upgrade_Schema $upgrade_schema ) {
$this->upgrade_schema = $upgrade_schema;
}
public function run() {
$table = 'icl_string_packages';
$column = 'word_count';
if ( ! $this->upgrade_schema->does_table_exist( $table ) ) {
return false;
}
if ( ! $this->upgrade_schema->does_column_exist( $table, $column ) ) {
return (bool) $this->upgrade_schema->add_column( $table, $column, 'VARCHAR(2000) DEFAULT NULL' );
}
return true;
}
public function run_ajax() {
return $this->run();
}
public function run_frontend() {
return $this->run();
}
/**
* @return string
*/
public static function get_command_id() {
return __CLASS__;
}
}

View File

@@ -0,0 +1,53 @@
<?php
/**
* Class WPML_ST_Upgrade_DB_String_Packages
*/
class WPML_ST_Upgrade_DB_String_Packages implements IWPML_St_Upgrade_Command {
private $wpdb;
/**
* WPML_ST_Upgrade_DB_String_Packages constructor.
*
* @param wpdb $wpdb
*/
public function __construct( wpdb $wpdb ) {
$this->wpdb = $wpdb;
}
public function run() {
$sql_get_st_package_table_name = "SHOW TABLES LIKE '{$this->wpdb->prefix}icl_string_packages'";
$st_packages_table_exist = $this->wpdb->get_var( $sql_get_st_package_table_name ) === "{$this->wpdb->prefix}icl_string_packages";
if ( ! $st_packages_table_exist ) {
return false;
}
$sql_get_post_id_column_from_st_package = "SHOW COLUMNS FROM {$this->wpdb->prefix}icl_string_packages LIKE 'post_id'";
$post_id_column_exists = $st_packages_table_exist
? $this->wpdb->get_var( $sql_get_post_id_column_from_st_package ) === 'post_id'
: false;
if ( ! $post_id_column_exists ) {
$sql = "ALTER TABLE {$this->wpdb->prefix}icl_string_packages ADD COLUMN `post_id` INTEGER";
return (bool) $this->wpdb->query( $sql );
}
return true;
}
public function run_ajax() {
return $this->run();
}
public function run_frontend() {
}
/**
* @return string
*/
public static function get_command_id() {
return __CLASS__ . '_2.4.2';
}
}

View File

@@ -0,0 +1,56 @@
<?php
class WPML_ST_Upgrade_DB_Strings_Add_Translation_Priority_Field implements IWPML_St_Upgrade_Command {
/** @var wpdb */
private $wpdb;
/**
* @param wpdb $wpdb
*/
public function __construct( wpdb $wpdb ) {
$this->wpdb = $wpdb;
}
public function run() {
$result = null;
$table_name = $this->wpdb->prefix . 'icl_strings';
if ( 0 !== count( $this->wpdb->get_results( "SHOW TABLES LIKE '{$table_name}'" ) ) ) {
$sql = "SHOW FIELDS FROM {$table_name} WHERE FIELD = 'translation_priority'";
if ( 0 === count( $this->wpdb->get_results( $sql ) ) ) {
$sql = "ALTER TABLE {$this->wpdb->prefix}icl_strings
ADD COLUMN `translation_priority` varchar(160) NOT NULL";
$result = false !== $this->wpdb->query( $sql );
}
if ( false !== $result ) {
$sql = "SHOW KEYS FROM {$table_name} WHERE Key_name='icl_strings_translation_priority'";
if ( 0 === count( $this->wpdb->get_results( $sql ) ) ) {
$sql = "
ALTER TABLE {$this->wpdb->prefix}icl_strings
ADD INDEX `icl_strings_translation_priority` ( `translation_priority` ASC )
";
$result = false !== $this->wpdb->query( $sql );
} else {
$result = true;
}
}
}
return (bool) $result;
}
public function run_ajax() {
return $this->run();
}
public function run_frontend() {
return $this->run();
}
public static function get_command_id() {
return __CLASS__;
}
}

View File

@@ -0,0 +1,39 @@
<?php
class WPML_ST_Upgrade_Display_Strings_Scan_Notices implements IWPML_St_Upgrade_Command {
/** @var WPML_ST_Themes_And_Plugins_Settings */
private $settings;
/**
* WPML_ST_Upgrade_Display_Strings_Scan_Notices constructor.
*
* @param WPML_ST_Themes_And_Plugins_Settings $settings
*/
public function __construct( WPML_ST_Themes_And_Plugins_Settings $settings ) {
$this->settings = $settings;
}
public static function get_command_id() {
return __CLASS__;
}
public function run() {
$this->maybe_add_missing_setting();
return ! $this->settings->display_notices_setting_is_missing();
}
public function run_ajax() {
return false;
}
public function run_frontend() {
return false;
}
private function maybe_add_missing_setting() {
if ( $this->settings->display_notices_setting_is_missing() ) {
$this->settings->create_display_notices_setting();
}
}
}

View File

@@ -0,0 +1,167 @@
<?php
class WPML_ST_Upgrade_Migrate_Originals implements IWPML_St_Upgrade_Command {
/** @var wpdb $wpdb */
private $wpdb;
/** @var SitePress sitepress */
private $sitepress;
private $translations = array();
private $not_translated = array();
private $active_languages;
public function __construct( wpdb $wpdb, SitePress $sitepress ) {
$this->wpdb = $wpdb;
$this->sitepress = $sitepress;
$active_languages = $this->sitepress->get_active_languages();
foreach ( $active_languages as $lang ) {
$this->active_languages[] = $lang['code'];
}
}
public static function get_command_id() {
return __CLASS__;
}
public function run() {
if ( $this->is_migration_required() ) {
if ( current_user_can( 'manage_options' ) ) {
$this->sitepress->get_wp_api()->add_action( 'admin_notices', array( $this, 'update_message' ) );
}
return false;
} else {
return true;
}
}
function update_message() {
?>
<div id="wpml-st-upgrade-migrate-originals" class="update-nag notice notice-info" style="display:block">
<p>
<?php esc_html_e( "WPML needs to update the database. This update will help improve WPML's performance when fetching translated strings.", 'wpml-string-translation' ); ?>
<br /><br />
<button class="wpml-st-upgrade-migrate-originals"><?php esc_html_e( 'Update Now', 'wpml-string-translation' ); ?></button> <span class="spinner" style="float: none"></span>
</p>
<?php wp_nonce_field( 'wpml-st-upgrade-migrate-originals-nonce', 'wpml-st-upgrade-migrate-originals-nonce' ); ?>
</div>
<div id="wpml-st-upgrade-migrate-originals-complete" class="update-nag notice notice-info" style="display:none">
<p>
<?php esc_html_e( 'The database has been updated.', 'wpml-string-translation' ); ?>
<br /><br />
<button class="wpml-st-upgrade-migrate-originals-close"><?php esc_html_e( 'Close', 'wpml-string-translation' ); ?></button>
</p>
<?php wp_nonce_field( 'wpml-st-upgrade-migrate-originals-nonce', 'wpml-st-upgrade-migrate-originals-nonce' ); ?>
</div>
<script type="text/javascript">
jQuery( function( $ ) {
jQuery( '.wpml-st-upgrade-migrate-originals' ).click( function() {
jQuery( this ).prop( 'disabled', true );
jQuery( this ).parent().find( '.spinner' ).css( 'visibility', 'visible' );
jQuery.ajax({
url: ajaxurl,
type: "POST",
data: {
action: 'wpml-st-upgrade-migrate-originals',
nonce: jQuery( '#wpml-st-upgrade-migrate-originals-nonce' ).val()
},
success: function ( response ) {
jQuery( '#wpml-st-upgrade-migrate-originals' ).hide();
jQuery( '#wpml-st-upgrade-migrate-originals-complete' ).css( 'display', 'block' );
}
});
});
jQuery( '.wpml-st-upgrade-migrate-originals-close' ).click( function() {
jQuery( '#wpml-st-upgrade-migrate-originals-complete' ).hide();
});
});
</script>
<?php
}
public function run_ajax() {
if ( $this->is_migration_required() ) {
$this->get_strings_without_translations();
$this->get_originals_with_translations();
$this->migrate_translations();
}
return true;
}
public function run_frontend() {}
private function is_migration_required() {
$query = "
SELECT id
FROM {$this->wpdb->prefix}icl_strings
WHERE context LIKE 'plugin %' OR context LIKE 'theme %'
LIMIT 1";
$found = $this->wpdb->get_var( $query );
return $found > 0;
}
private function get_strings_without_translations() {
foreach ( $this->active_languages as $lang ) {
$res_args = array( $lang, $lang );
$res_query = "
SELECT
s.value,
s.id
FROM {$this->wpdb->prefix}icl_strings s
WHERE s.id NOT IN (
SELECT st.string_id FROM {$this->wpdb->prefix}icl_string_translations st
WHERE st.language=%s
)
AND s.language!=%s
";
$res_prepare = $this->wpdb->prepare( $res_query, $res_args );
$this->not_translated[ $lang ] = $this->wpdb->get_results( $res_prepare, ARRAY_A );
}
}
private function get_originals_with_translations() {
foreach ( $this->active_languages as $lang ) {
$res_args = array( ICL_TM_COMPLETE, $lang );
$res_query = "
SELECT
st.value AS tra,
s.value AS org
FROM {$this->wpdb->prefix}icl_strings s
LEFT JOIN {$this->wpdb->prefix}icl_string_translations st
ON s.id=st.string_id
WHERE st.status=%d AND st.language=%s
";
$res_prepare = $this->wpdb->prepare( $res_query, $res_args );
$result = $this->wpdb->get_results( $res_prepare, ARRAY_A );
$strings = array();
foreach ( $result as $string ) {
$strings[ $string['org'] ] = $string['tra'];
}
$this->translations[ $lang ] = $strings;
}
}
private function migrate_translations() {
foreach ( $this->active_languages as $lang ) {
foreach ( $this->not_translated[ $lang ] as $not_translated ) {
if ( isset( $this->translations[ $lang ][ $not_translated['value'] ] ) ) {
icl_add_string_translation( $not_translated['id'], $lang, $this->translations[ $lang ][ $not_translated['value'] ], ICL_TM_COMPLETE );
break;
}
}
}
}
}

View File

@@ -0,0 +1,88 @@
<?php
class WPML_ST_Upgrade_MO_Scanning implements IWPML_St_Upgrade_Command {
/** @var wpdb $wpdb */
private $wpdb;
private static $sql = "
CREATE TABLE `PREFIXicl_mo_files_domains` (
`id` int(11) PRIMARY KEY NOT NULL AUTO_INCREMENT,
`file_path` varchar(250) NOT NULL,
`file_path_md5` varchar(32) NOT NULL,
`domain` varchar(160) NOT NULL,
`status` varchar(20) NOT NULL DEFAULT %s,
`num_of_strings` int(11) NOT NULL DEFAULT '0',
`last_modified` int(11) NOT NULL,
`component_type` enum('plugin','theme','other') NOT NULL DEFAULT 'other',
`component_id` varchar(100) DEFAULT NULL,
UNIQUE KEY `file_path_md5_UNIQUE` (`file_path_md5`)
)
";
/**
* @param wpdb $wpdb
*/
public function __construct( wpdb $wpdb ) {
$this->wpdb = $wpdb;
}
public function run() {
return $this->create_table() && $this->add_mo_value_field_if_does_not_exist();
}
private function create_table() {
$table_name = $this->wpdb->prefix . 'icl_mo_files_domains';
$this->wpdb->query( "DROP TABLE IF EXISTS `{$table_name}`" );
$sql = str_replace( 'PREFIX', $this->wpdb->prefix, self::$sql );
$sql = $this->wpdb->prepare(
$sql,
array( WPML_ST_Translations_File_Entry::NOT_IMPORTED )
);
$sql .= $this->get_charset_collate();
return false !== $this->wpdb->query( $sql );
}
private function add_mo_value_field_if_does_not_exist() {
$result = true;
$table_name = $this->wpdb->prefix . 'icl_string_translations';
if ( 0 === count( $this->wpdb->get_results( "SHOW COLUMNS FROM `{$table_name}` LIKE 'mo_string'" ) ) ) {
$sql = "
ALTER TABLE {$table_name}
ADD COLUMN `mo_string` TEXT NULL DEFAULT NULL AFTER `value`;
";
$result = false !== $this->wpdb->query( $sql );
}
return $result;
}
public function run_ajax() {
return $this->run();
}
public function run_frontend() {
return $this->run();
}
public static function get_command_id() {
return __CLASS__ . '_4' ;
}
/**
* @return string
*/
private function get_charset_collate() {
$charset_collate = '';
if ( method_exists( $this->wpdb, 'has_cap' ) && $this->wpdb->has_cap( 'collation' ) ) {
$charset_collate = $this->wpdb->get_charset_collate();
}
return $charset_collate;
}
}

View File

@@ -0,0 +1,27 @@
<?php
class WPML_ST_Upgrade_String_Index {
/** @var wpdb */
private $wpdb;
const OPTION_NAME = 'wpml_string_table_ok_for_mo_import';
/**
* @param wpdb $wpdb
*/
public function __construct( wpdb $wpdb ) {
$this->wpdb = $wpdb;
}
public function is_uc_domain_name_context_index_unique() {
$key_exists = get_option( self::OPTION_NAME );
if ( ! $key_exists ) {
$sql = "SHOW KEYS FROM {$this->wpdb->prefix}icl_strings WHERE Key_name='uc_domain_name_context_md5' AND Non_unique = 0";
$key_exists = 0 < count( $this->wpdb->get_results( $sql ) ) ? 'yes' : 'no';
update_option( self::OPTION_NAME, $key_exists, true );
}
return 'yes' === $key_exists;
}
}

View File

@@ -0,0 +1,221 @@
<?php
/**
* WPML_ST_Upgrade class file.
*
* @package wpml-string-translation
*/
/**
* Class WPML_ST_Upgrade
*/
class WPML_ST_Upgrade {
const TRANSIENT_UPGRADE_IN_PROGRESS = 'wpml_st_upgrade_in_progress';
/**
* SitePress instance.
*
* @var SitePress $sitepress
*/
private $sitepress;
/**
* Upgrade Command Factory instance.
*
* @var WPML_ST_Upgrade_Command_Factory
*/
private $command_factory;
/**
* Upgrade in progress flag.
*
* @var bool $upgrade_in_progress
*/
private $upgrade_in_progress;
/**
* WPML_ST_Upgrade constructor.
*
* @param SitePress $sitepress SitePress instance.
* @param WPML_ST_Upgrade_Command_Factory|null $command_factory Upgrade Command Factory instance.
*/
public function __construct( SitePress $sitepress, WPML_ST_Upgrade_Command_Factory $command_factory = null ) {
$this->sitepress = $sitepress;
$this->command_factory = $command_factory;
}
/**
* Run upgrade.
*/
public function run() {
if ( get_transient( self::TRANSIENT_UPGRADE_IN_PROGRESS ) ) {
return;
}
if ( $this->sitepress->get_wp_api()->is_admin() ) {
if ( $this->sitepress->get_wp_api()->constant( 'DOING_AJAX' ) ) {
$this->run_ajax();
} else {
$this->run_admin();
}
} else {
$this->run_front_end();
}
$this->set_upgrade_completed();
}
/**
* Run admin.
*/
private function run_admin() {
$this->maybe_run( 'WPML_ST_Upgrade_Migrate_Originals' );
$this->maybe_run( 'WPML_ST_Upgrade_Display_Strings_Scan_Notices' );
$this->maybe_run( 'WPML_ST_Upgrade_DB_String_Packages' );
$this->maybe_run( 'WPML_ST_Upgrade_MO_Scanning' );
$this->maybe_run( 'WPML_ST_Upgrade_DB_String_Name_Index' );
$this->maybe_run( 'WPML_ST_Upgrade_DB_Longtext_String_Value' );
$this->maybe_run( 'WPML_ST_Upgrade_DB_Strings_Add_Translation_Priority_Field' );
$this->maybe_run( 'WPML_ST_Upgrade_DB_String_Packages_Word_Count' );
$this->maybe_run( '\WPML\ST\Upgrade\Command\RegenerateMoFilesWithStringNames' );
$this->maybe_run( \WPML\ST\Upgrade\Command\MigrateMultilingualWidgets::class );
}
/**
* Run ajax.
*/
private function run_ajax() {
$this->maybe_run_ajax( 'WPML_ST_Upgrade_Migrate_Originals' );
// It has to be maybe_run.
$this->maybe_run( 'WPML_ST_Upgrade_MO_Scanning' );
$this->maybe_run( 'WPML_ST_Upgrade_DB_String_Packages_Word_Count' );
}
/**
* Run on frontend.
*/
private function run_front_end() {
$this->maybe_run( 'WPML_ST_Upgrade_MO_Scanning' );
$this->maybe_run( 'WPML_ST_Upgrade_DB_String_Packages_Word_Count' );
}
/**
* Maybe run command.
*
* @param string $class Command class name.
*/
private function maybe_run( $class ) {
if ( ! $this->has_command_been_executed( $class ) ) {
$this->set_upgrade_in_progress();
$upgrade = $this->command_factory->create( $class );
if ( $upgrade->run() ) {
$this->mark_command_as_executed( $class );
}
}
}
/**
* Maybe run command in ajax.
*
* @param string $class Command class name.
*/
private function maybe_run_ajax( $class ) {
if ( ! $this->has_command_been_executed( $class ) ) {
$this->run_ajax_command( $class );
}
}
/**
* Run command in ajax.
*
* @param string $class Command class name.
*/
private function run_ajax_command( $class ) {
if ( $this->nonce_ok( $class ) ) {
$upgrade = $this->command_factory->create( $class );
if ( $upgrade->run_ajax() ) {
$this->mark_command_as_executed( $class );
$this->sitepress->get_wp_api()->wp_send_json_success( '' );
}
}
}
/**
* Check nonce.
*
* @param string $class Command class name.
*
* @return bool
*/
private function nonce_ok( $class ) {
$ok = false;
$class = strtolower( $class );
$class = str_replace( '_', '-', $class );
if ( isset( $_POST['action'] ) && $_POST['action'] === $class ) {
$nonce = $this->filter_nonce_parameter();
if ( $this->sitepress->get_wp_api()->wp_verify_nonce( $nonce, $class . '-nonce' ) ) {
$ok = true;
}
}
return $ok;
}
/**
* Check if command was executed.
*
* @param string $class Command class name.
*
* @return bool
*/
public function has_command_been_executed( $class ) {
$id = call_user_func( [ $class, 'get_command_id' ] );
$settings = $this->sitepress->get_setting( 'st', [] );
return isset( $settings[ $id . '_has_run' ] );
}
/**
* Mark command as executed.
*
* @param string $class Command class name.
*/
public function mark_command_as_executed( $class ) {
$id = call_user_func( [ $class, 'get_command_id' ] );
$settings = $this->sitepress->get_setting( 'st', [] );
$settings[ $id . '_has_run' ] = true;
$this->sitepress->set_setting( 'st', $settings, true );
wp_cache_flush();
}
/**
* Filter nonce.
*
* @return mixed
*/
protected function filter_nonce_parameter() {
return filter_input( INPUT_POST, 'nonce', FILTER_SANITIZE_FULL_SPECIAL_CHARS );
}
/**
* Set flag that upgrade is in process.
*/
private function set_upgrade_in_progress() {
if ( ! $this->upgrade_in_progress ) {
$this->upgrade_in_progress = true;
set_transient( self::TRANSIENT_UPGRADE_IN_PROGRESS, true, MINUTE_IN_SECONDS );
}
}
/**
* Mark upgrade as completed.
*/
private function set_upgrade_completed() {
if ( $this->upgrade_in_progress ) {
$this->upgrade_in_progress = false;
delete_transient( self::TRANSIENT_UPGRADE_IN_PROGRESS );
}
}
}

View File

@@ -0,0 +1,12 @@
<?php
interface IWPML_St_Upgrade_Command {
public function run();
public function run_ajax();
public function run_frontend();
public static function get_command_id();
}

View File

@@ -0,0 +1,103 @@
<?php
class WPML_ST_Repair_Strings_Schema {
const OPTION_HAS_RUN = 'wpml_st_repair_string_schema_has_run';
/** @var IWPML_St_Upgrade_Command $upgrade_command */
private $upgrade_command;
/** @var WPML_Notices $notices */
private $notices;
/** @var array $args */
private $args;
/** @var string $db_error */
private $db_error;
/** @var array $has_run */
private $has_run = array();
public function __construct( WPML_Notices $notices, array $args, $db_error ) {
$this->notices = $notices;
$this->args = $args;
$this->db_error = $db_error;
}
public function set_command( IWPML_St_Upgrade_Command $upgrade_command ) {
$this->upgrade_command = $upgrade_command;
}
/** @return bool */
public function run() {
$this->has_run = get_option( self::OPTION_HAS_RUN, array() );
if ( ! $this->upgrade_command || array_key_exists( $this->get_command_id(), $this->has_run ) ) {
$this->add_notice();
return false;
}
if ( $this->run_upgrade_command() ) {
return true;
}
$this->add_notice();
return false;
}
/** @return bool */
private function run_upgrade_command() {
if ( ! $this->acquire_lock() ) {
return false;
}
$success = $this->upgrade_command->run();
$this->has_run[ $this->get_command_id() ] = true;
update_option( self::OPTION_HAS_RUN, $this->has_run, false );
$this->release_lock();
return (bool) $success;
}
private function get_command_id() {
return get_class( $this->upgrade_command );
}
/** @return bool */
private function acquire_lock() {
if ( get_transient( WPML_ST_Upgrade::TRANSIENT_UPGRADE_IN_PROGRESS ) ) {
return false;
}
set_transient( WPML_ST_Upgrade::TRANSIENT_UPGRADE_IN_PROGRESS, true, MINUTE_IN_SECONDS );
return true;
}
private function release_lock() {
delete_transient( WPML_ST_Upgrade::TRANSIENT_UPGRADE_IN_PROGRESS );
}
private function add_notice() {
$text = '<p>' . sprintf(
esc_html__( 'We have detected a problem with some tables in the database. Please contact %1$sWPML support%2$s to get this fixed.', 'wpml-string-translation' ),
'<a href="https://wpml.org/forums/forum/english-support/" class="otgs-external-link" rel="noopener" target="_blank">',
'</a>'
) . '</p>';
$text .= '<pre>' . $this->db_error . '</pre>';
if ( $this->upgrade_command ) {
$notice_id = $this->get_command_id();
} else {
$notice_id = 'default';
$text .= '<pre>' . print_r( $this->args, true ) . '</pre>';
}
$notice = $this->notices->create_notice( $notice_id, $text, __CLASS__ );
$notice->set_hideable( true );
$notice->set_css_class_types( array( 'notice-error' ) );
$this->notices->add_notice( $notice );
}
}