Files
CHIEFSOFT\ameye df3a033196 first commit
2024-06-08 17:09:23 -04:00

465 lines
18 KiB
PHP

<?php
/**
* @file classes/migration/upgrade/v3_4_0/MergeLocalesMigration.php
*
* Copyright (c) 2014-2021 Simon Fraser University
* Copyright (c) 2000-2021 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class MergeLocalesMigration
*
* @brief Change Locales from locale_countryCode localization folder notation to locale localization folder notation
*/
namespace PKP\migration\upgrade\v3_4_0;
use Exception;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Collection;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use PKP\db\DAORegistry;
use PKP\install\DowngradeNotSupportedException;
abstract class MergeLocalesMigration extends \PKP\migration\Migration
{
protected string $CONTEXT_TABLE = '';
protected string $CONTEXT_SETTINGS_TABLE = '';
protected string $CONTEXT_COLUMN = '';
/**
* Run the migrations.
*/
public function up(): void
{
// This change fixes the locale column length on the static_page_settings
// which in 3.1.0 version was varchar(5).
if (Schema::hasTable('static_page_settings')) {
Schema::table('static_page_settings', function (Blueprint $table) {
$table->string('locale', 14)->change();
});
}
if (empty($this->CONTEXT_TABLE) || empty($this->CONTEXT_SETTINGS_TABLE) || empty($this->CONTEXT_COLUMN)) {
throw new Exception('Upgrade could not be completed because required properties for the MergeLocalesMigration migration are undefined.');
}
// All _settings tables.
foreach ($this->getSettingsTables() as $tableName => [$entityIdColumnName, $primaryKeyColumnName]) {
if (!Schema::hasTable($tableName) || !Schema::hasColumn($tableName, 'locale')) {
continue;
}
foreach (self::getAffectedLocales() as $source => $target) {
DB::table($tableName)
->where('locale', $source)
->update(['locale' => $target]);
}
}
// Tables
// site
$site = DB::table('site')
->select(['supported_locales', 'installed_locales', 'primary_locale'])
->first();
$this->updateArrayLocaleNoId($site->supported_locales, 'site', 'supported_locales');
$this->updateArrayLocaleNoId($site->installed_locales, 'site', 'installed_locales');
$this->updateSingleValueLocaleNoId($site->primary_locale, 'site', 'primary_locale');
Schema::table('site', function (Blueprint $table) {
$table->string('installed_locales')->default('en')->change();
});
// users
$migration = $this;
$users = DB::table('users')->chunkById(1000, function ($users) use ($migration) {
foreach ($users as $user) {
$migration->updateArrayLocale($user->locales, 'users', 'locales', 'user_id', $user->user_id);
}
}, 'user_id');
// submissions
$submissions = DB::table('submissions')->chunkById(1000, function ($submissions) use ($migration) {
foreach ($submissions as $submission) {
$migration->updateSingleValueLocale($submission->locale, 'submissions', 'locale', 'submission_id', $submission->submission_id);
}
}, 'submission_id');
// email_templates_default_data
$emailTemplatesDefaultData = DB::table('email_templates_default_data')
->get();
foreach ($emailTemplatesDefaultData as $emailTemplatesDefaultDataCurrent) {
$this->updateSingleValueLocaleEmailData($emailTemplatesDefaultDataCurrent->locale, 'email_templates_default_data', $emailTemplatesDefaultDataCurrent->email_key, $emailTemplatesDefaultData);
}
Schema::table('email_templates_default_data', function (Blueprint $table) {
$table->string('locale')->default('en')->change();
});
// Context
$contexts = DB::table($this->CONTEXT_TABLE)
->get();
foreach ($contexts as $context) {
$this->updateSingleValueLocale($context->primary_locale, $this->CONTEXT_TABLE, 'primary_locale', $this->CONTEXT_COLUMN, $context->{$this->CONTEXT_COLUMN});
}
$contextSettingsFormLocales = DB::table($this->CONTEXT_SETTINGS_TABLE)
->where('setting_name', '=', 'supportedFormLocales')
->get();
foreach ($contextSettingsFormLocales as $contextSettingsFormLocale) {
$this->updateArrayLocaleSetting($contextSettingsFormLocale->setting_value, $this->CONTEXT_SETTINGS_TABLE, 'supportedFormLocales', $this->CONTEXT_COLUMN, $contextSettingsFormLocale->{$this->CONTEXT_COLUMN});
}
$contextSettingsFormLocales = DB::table($this->CONTEXT_SETTINGS_TABLE)
->where('setting_name', '=', 'supportedLocales')
->get();
foreach ($contextSettingsFormLocales as $contextSettingsFormLocale) {
$this->updateArrayLocaleSetting($contextSettingsFormLocale->setting_value, $this->CONTEXT_SETTINGS_TABLE, 'supportedLocales', $this->CONTEXT_COLUMN, $contextSettingsFormLocale->{$this->CONTEXT_COLUMN});
}
$contextSettingsFormLocales = DB::table($this->CONTEXT_SETTINGS_TABLE)
->where('setting_name', '=', 'supportedSubmissionLocales')
->get();
foreach ($contextSettingsFormLocales as $contextSettingsFormLocale) {
$this->updateArrayLocaleSetting($contextSettingsFormLocale->setting_value, $this->CONTEXT_SETTINGS_TABLE, 'supportedSubmissionLocales', $this->CONTEXT_COLUMN, $contextSettingsFormLocale->{$this->CONTEXT_COLUMN});
}
// plugin_settings
// customBlockManager
$blockPluginName = 'customblockmanagerplugin';
$blockLocalizedSettingNames = ['blockTitle', 'blockContent'];
$contextIds = DB::table($this->CONTEXT_TABLE)
->get()
->pluck($this->CONTEXT_COLUMN);
foreach ($contextIds as $contextId) {
$blocks = DB::table('plugin_settings')
->where('plugin_name', '=', $blockPluginName)
->where('setting_name', '=', 'blocks')
->where('context_id', '=', $contextId)
->get()
->pluck('setting_value');
if (!$blocks->isEmpty()) {
$blocksArray = json_decode($blocks[0], true);
foreach ($blocksArray as $block) {
foreach ($blockLocalizedSettingNames as $blockLocalizedSettingName) {
$blockLocalizedContent = DB::table('plugin_settings')
->where('plugin_name', '=', $block)
->where('setting_name', '=', $blockLocalizedSettingName)
->where('context_id', '=', $contextId)
->first();
if (isset($blockLocalizedContent)) {
$this->updateArrayKeysLocaleSetting($blockLocalizedContent->setting_value, 'plugin_settings', 'plugin_setting_id', $blockLocalizedContent->plugin_setting_id);
}
}
}
$pluginSettingsDao = DAORegistry::getDAO('PluginSettingsDAO'); /** @var PluginSettingsDAO $pluginSettingsDao */
$cache = $pluginSettingsDao->_getCache($contextId, $blockPluginName);
$cache->flush();
}
}
}
public function updateArrayLocaleNoId(string $dbLocales, string $table, string $column)
{
$siteSupportedLocales = json_decode($dbLocales) ?? [];
if ($siteSupportedLocales !== false) {
$newLocales = [];
foreach ($siteSupportedLocales as $siteSupportedLocale) {
$updatedLocale = $this->getUpdatedLocale($siteSupportedLocale);
if (!is_null($updatedLocale)) {
if (!in_array($updatedLocale, $newLocales)) {
$newLocales[] = $updatedLocale;
}
} else {
$newLocales[] = $siteSupportedLocale;
}
}
DB::table($table)
->update([
$column => $newLocales
]);
}
}
public function updateArrayLocale(string $dbLocales, string $table, string $column, string $tableKeyColumn, int $id)
{
$siteSupportedLocales = json_decode($dbLocales) ?? [];
$newLocales = [];
foreach ($siteSupportedLocales as $siteSupportedLocale) {
$updatedLocale = $this->getUpdatedLocale($siteSupportedLocale);
if (!is_null($updatedLocale)) {
if (!in_array($updatedLocale, $newLocales)) {
$newLocales[] = $updatedLocale;
}
} else {
$newLocales[] = $siteSupportedLocale;
}
}
DB::table($table)
->where($tableKeyColumn, '=', $id)
->update([
$column => $newLocales
]);
}
public function updateArrayLocaleSetting(string $dbLocales, string $table, string $settingValue, string $tableKeyColumn, int $id)
{
$siteSupportedLocales = json_decode($dbLocales) ?? [];
if ($siteSupportedLocales !== false) {
$newLocales = [];
foreach ($siteSupportedLocales as $siteSupportedLocale) {
$updatedLocale = $this->getUpdatedLocale($siteSupportedLocale);
if (!is_null($updatedLocale)) {
if (!in_array($updatedLocale, $newLocales)) {
$newLocales[] = $updatedLocale;
}
} else {
$newLocales[] = $siteSupportedLocale;
}
}
DB::table($table)
->where($tableKeyColumn, '=', $id)
->where('setting_name', '=', $settingValue)
->update([
'setting_value' => $newLocales
]);
}
}
public function updateArrayKeysLocaleSetting(string $dbLocales, string $table, string $tableKeyColumn, int $id)
{
$siteSupportedLocales = json_decode($dbLocales, true) ?? [];
if ($siteSupportedLocales !== false) {
$newLocales = [];
foreach (array_keys($siteSupportedLocales) as $siteSupportedLocaleKey) {
$updatedLocale = $this->getUpdatedLocale($siteSupportedLocaleKey);
if (!is_null($updatedLocale)) {
$newLocales[$updatedLocale] = $siteSupportedLocales[$siteSupportedLocaleKey];
} else {
$newLocales[$siteSupportedLocaleKey] = $siteSupportedLocales[$siteSupportedLocaleKey];
}
}
$jsonString = json_encode($newLocales);
DB::table($table)
->where($tableKeyColumn, '=', $id)
->update([
'setting_value' => $jsonString
]);
}
}
public function updateSingleValueLocale(?string $localevalue, string $table, string $column, string $tableKeyColumn, int $id)
{
if ($localevalue === null) {
return;
}
$updatedLocale = $this->getUpdatedLocale($localevalue);
if (!is_null($updatedLocale)) {
DB::table($table)
->where($tableKeyColumn, '=', $id)
->update([
$column => $updatedLocale
]);
}
}
public function updateSingleValueLocaleNoId(string $localevalue, string $table, string $column)
{
$updatedLocale = $this->getUpdatedLocale($localevalue);
if (!is_null($updatedLocale)) {
DB::table($table)
->update([
$column => $updatedLocale
]);
}
}
public function updateSingleValueLocaleEmailData(string $localevalue, string $table, string $email_key, Collection $allEmailTemplateData)
{
$localeRows = DB::table($table)
->where('email_key', '=', $email_key)
->where('locale', '=', $localevalue);
$stillExists = $localeRows->exists();
if ($stillExists) {
$updatedLocale = $this->getUpdatedLocale($localevalue);
// if this is null we should do nothing - we are not handling this locale
if (!is_null($updatedLocale)) {
// if the updatedLocale is the same as the setting's locale we should do nothing
// Check if the database already has an updated locale with the same value -
$hasAlreadyExistingUpdatedLocale = DB::table($table)
->where('email_key', '=', $email_key)
->where('locale', '=', $updatedLocale)
->exists();
// if so, it is safe to delete the currently processed value.
if ($hasAlreadyExistingUpdatedLocale) {
$localeRows->delete();
} else {
$localeRows->update(['locale' => $updatedLocale]);
}
}
}
}
/**
* Returns null if no conversion is available or
* a key value pair collection that the key is the output locale and the value is the defaultLocale.
*/
public function getUpdatedLocale(string $localeValue): ?string
{
$affectedLocales = $this->getAffectedLocales();
if ($affectedLocales->keys()->contains($localeValue)) {
$localeTransformation = $affectedLocales[$localeValue];
return $localeTransformation;
}
return null;
}
/**
* Reverse the downgrades
*
* @throws DowngradeNotSupportedException
*/
public function down(): void
{
throw new DowngradeNotSupportedException();
}
/**
* Get a list of settings tables, keyed by table name. Values are [entity_id_column_name, settings_table_id_column_name].
*/
protected static function getSettingsTables(): Collection
{
return collect([
'announcement_settings' => ['announcement_id', 'announcement_setting_id'],
'announcement_type_settings' => ['type_id', 'announcement_type_setting_id'],
'author_settings' => ['author_id', 'author_setting_id'],
'category_settings' => ['category_id', 'category_setting_id'],
'citation_settings' => ['citation_id', 'citation_setting_id'],
'controlled_vocab_entry_settings' => ['controlled_vocab_entry_id', 'controlled_vocab_entry_setting_id'],
'data_object_tombstone_settings' => ['tombstone_id', 'tombstone_setting_id'],
'email_templates_settings' => ['email_id', 'email_template_setting_id'],
'event_log_settings' => ['log_id', 'event_log_setting_id'],
'filter_settings' => ['filter_id', 'filter_setting_id'],
'genre_settings' => ['genre_id', 'genre_setting_id'],
'library_file_settings' => ['file_id', 'library_file_setting_id'],
'navigation_menu_item_assignment_settings' => ['navigation_menu_item_assignment_id', 'navigation_menu_item_assignment_setting_id'],
'navigation_menu_item_settings' => ['navigation_menu_item_id', 'navigation_menu_item_setting_id'],
'notification_settings' => ['notification_id', 'notification_setting_id'],
'notification_subscription_settings' => ['setting_id', 'notification_subscription_setting_id'],
'plugin_settings' => ['context_id', 'plugin_setting_id'],
'publication_settings' => ['publication_id', 'publication_setting_id'],
'review_form_element_settings' => ['review_form_element_id', 'review_form_element_setting_id'],
'review_form_settings' => ['review_form_id', 'review_form_setting_id'],
'submission_file_settings' => ['submission_file_id', 'submission_file_setting_id'],
'submission_settings' => ['submission_id', 'submission_setting_id'],
'user_group_settings' => ['user_group_id', 'user_group_setting_id'],
'user_settings' => ['user_id', 'user_setting_id'],
'site_settings' => [null, 'site_setting_id'],
'funder_settings' => ['funder_id', 'funder_setting_id'],
'funder_award_settings' => ['funder_award_id', 'funder_award_setting_id'],
'static_page_settings' => ['static_page_id', 'static_page_setting_id'],
]);
}
/**
* Returns the effected locales along with the corresponding rename for each
*/
public static function getAffectedLocales(): Collection
{
return collect([
'es_ES' => 'es',
'en_US' => 'en',
'sr_RS@cyrillic' => 'sr@cyrillic',
'sr_RS@latin' => 'sr@latin',
'el_GR' => 'el',
'de_DE' => 'de',
'da_DK' => 'da',
'cs_CZ' => 'cs',
'ca_ES' => 'ca',
'bs_BA' => 'bs',
'bg_BG' => 'bg',
'be_BY@cyrillic' => 'be@cyrillic',
'az_AZ' => 'az',
'ar_IQ' => 'ar',
'fa_IR' => 'fa',
'fi_FI' => 'fi',
'gd_GB' => 'gd',
'gl_ES' => 'gl',
'he_IL' => 'he',
'hi_IN' => 'hi',
'hr_HR' => 'hr',
'hu_HU' => 'hu',
'hy_AM' => 'hy',
'id_ID' => 'id',
'is_IS' => 'is',
'it_IT' => 'it',
'ja_JP' => 'ja',
'ka_GE' => 'ka',
'kk_KZ' => 'kk',
'ko_KR' => 'ko',
'ku_IQ' => 'ku',
'lt_LT' => 'lt',
'lv_LV' => 'lv',
'mk_MK' => 'mk',
'mn_MN' => 'mn',
'ms_MY' => 'ms',
'nb_NO' => 'nb',
'nl_NL' => 'nl',
'pl_PL' => 'pl',
'ro_RO' => 'ro',
'ru_RU' => 'ru',
'si_LK' => 'si',
'sk_SK' => 'sk',
'sl_SI' => 'sl',
'sv_SE' => 'sv',
'tr_TR' => 'tr',
'uk_UA' => 'uk',
'ur_PK' => 'ur',
'uz_UZ@cyrillic' => 'uz@cyrillic',
'uz_UZ@latin' => 'uz@latin',
'vi_VN' => 'vi',
'eu_ES' => 'eu',
'sw_KE' => 'sw',
'zh_TW' => 'zh_Hant'
]);
}
}