Skip to content

Commit

Permalink
Merge pull request #10734 from bozana/10729
Browse files Browse the repository at this point in the history
#10729 fix I9707_WeblateUILocales, consider locales in arr…
  • Loading branch information
bozana authored Jan 19, 2025
2 parents e598e9f + f504637 commit adacbdb
Show file tree
Hide file tree
Showing 2 changed files with 124 additions and 87 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
/**
* @file classes/migration/upgrade/v3_5_0/I9425_SeparateUIAndSubmissionLocales.php
*
* Copyright (c) 2024 Simon Fraser University
* Copyright (c) 2024 John Willinsky
* Copyright (c) 2025 Simon Fraser University
* Copyright (c) 2025 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class I9425_SeparateUIAndSubmissionLocales
Expand All @@ -14,11 +14,11 @@

namespace PKP\migration\upgrade\v3_5_0;

use Illuminate\Database\PostgresConnection;
use DateInterval;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use APP\core\Application;
use PKP\install\DowngradeNotSupportedException;
use PKP\migration\Migration;

Expand Down Expand Up @@ -50,9 +50,9 @@ public function up(): void

$update = function (object $localeId, string $settingName, string $settingValue): void {
DB::table($this->getContextSettingsTable())
->where($this->getContextIdColumn(), '=', $localeId->{$this->getContextIdColumn()})
->where('setting_name', '=', $settingName)
->update(['setting_value' => $settingValue]);
->where($this->getContextIdColumn(), '=', $localeId->{$this->getContextIdColumn()})
->where('setting_name', '=', $settingName)
->update(['setting_value' => $settingValue]);
};

$pluck = fn (object $localeId, string $settingName): array => json_decode(
Expand Down Expand Up @@ -88,71 +88,25 @@ public function up(): void
/**
* Update locale character lengths
*/

$schemaLocName = (DB::connection() instanceof PostgresConnection)
? 'TABLE_CATALOG'
: 'TABLE_SCHEMA';

$updateLength = fn (string $l) => collect(
DB::select("
SELECT DISTINCT TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME = ? AND $schemaLocName = ?",
[$l, DB::connection()->getDatabaseName()]
)
)->each(fn (\stdClass $sc) => Schema::table(
$sc->TABLE_NAME ?? $sc->table_name,
fn (Blueprint $table) => collect(Schema::getColumns($sc->TABLE_NAME ?? $sc->table_name))
->where('name', $l)
->first(default:[])['nullable'] ?? false
? $table->string($l, 28)->nullable()->change()
: $table->string($l, 28)->change()
)
);

$updateLength('primary_locale');
$updateLength('locale');

/**
* Convert locales
*/

$localesTable = [
"be@cyrillic" => "be",
"bs" => "bs_Latn",
"fr_FR" => "fr",
"nb" => "nb_NO",
"sr@cyrillic" => "sr_Cyrl",
"sr@latin" => "sr_Latn",
"uz@cyrillic" => "uz",
"uz@latin" => "uz_Latn",
"zh_CN" => "zh_Hans",
];

$tableNames = array_merge([
'author_settings',
'controlled_vocab_entry_settings',
'publication_settings',
'submission_file_settings',
'submission_settings',
'submissions',
], Application::get()->getName() === 'omp'
? ['publication_format_settings', 'submission_chapter_settings',]
: ['publication_galley_settings', 'publication_galleys',]
);

collect($tableNames)
->each(fn (string $tn) => collect(DB::table($tn)->select('locale')->distinct()->get())
->each(function (\stdClass $sc) use ($tn, $localesTable) {
if (isset($localesTable[$sc->locale])) {
DB::table($tn)
->where('locale', '=', $sc->locale)
->update([
'locale' => $localesTable[$sc->locale]
]);
}
})
// Cache will be cleared at the end of I9707_WeblateUILocales
$key = 'localeUpdates1 day';
$tableLocaleColumns = Cache::remember($key, DateInterval::createFromDateString('1 day'), function () {
$tableLocaleColumns = [];
foreach (Schema::getTables() as $table) {
$columns = collect(Schema::getColumns($table['name']))->whereIn('name', ['primary_locale', 'locale']);
if ($columns->count() > 0) {
$tableLocaleColumns[$table['name']] = $columns;
}
}
return $tableLocaleColumns;
});

foreach ($tableLocaleColumns as $tableName => $localeColumns) {
$localeColumns->each(
fn ($column) =>
Schema::table($tableName, fn (Blueprint $table) => $table->string($column['name'], 28)->nullable($column['nullable'])->change())
);
}
}

/**
Expand Down
115 changes: 99 additions & 16 deletions classes/migration/upgrade/v3_5_0/I9707_WeblateUILocales.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
/**
* @file classes/migration/upgrade/v3_5_0/I9707_WeblateUILocales.php
*
* Copyright (c) 2024 Simon Fraser University
* Copyright (c) 2024 John Willinsky
* Copyright (c) 2025 Simon Fraser University
* Copyright (c) 2025 John Willinsky
* Distributed under the GNU GPL v3. For full terms see the file docs/COPYING.
*
* @class I9707_WeblateUILocales
Expand All @@ -14,19 +14,113 @@

namespace PKP\migration\upgrade\v3_5_0;

use Illuminate\Database\PostgresConnection;
use DateInterval;
use Illuminate\Database\Query\Builder;
use Illuminate\Support\Facades\Cache;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Schema;
use PKP\install\DowngradeNotSupportedException;
use PKP\migration\Migration;

class I9707_WeblateUILocales extends Migration
abstract class I9707_WeblateUILocales extends Migration
{
abstract protected function getContextTable(): string;
abstract protected function getContextSettingsTable(): string;
abstract protected function getContextIdColumn(): string;

/**
* Run the migrations.
*/
public function up(): void
{
$localesTable = [
$affectedLocales = $this->getAffectedLocales();

// update all locale and primary_locale columns
$cacheKey = 'localeUpdates1 day';
$tableLocaleColumns = Cache::remember($cacheKey, DateInterval::createFromDateString('1 day'), function () {
$tableLocaleColumns = [];
foreach (Schema::getTables() as $table) {
$columns = collect(Schema::getColumns($table['name']))->whereIn('name', ['primary_locale', 'locale']);
if ($columns->count() > 0) {
$tableLocaleColumns[$table['name']] = $columns;
}
}
return $tableLocaleColumns;
});

foreach ($tableLocaleColumns as $tableName => $localeColumns) {
$localeColumns->each(
fn ($column) =>
DB::table($tableName)
->whereIn($column['name'], array_keys($affectedLocales))
->update([$column['name'] => DB::raw(
"CASE {$column['name']} " . implode(' ', array_map(fn ($oldLocale, $newLocale) => "WHEN '{$oldLocale}' THEN '{$newLocale}'", array_keys($affectedLocales), array_values($affectedLocales))) . ' END'
)])
);
}

// site supported and installed locales
$this->updateArrayLocale('site', 'supported_locales');
$this->updateArrayLocale('site', 'installed_locales');

// users locales
$this->updateArrayLocale('users', 'locales');

// context supported locales
$supportedDefaultSubmissionLocale = DB::table($this->getContextSettingsTable())
->where('setting_name', '=', 'supportedDefaultSubmissionLocale')
->get()
->pluck('setting_value')
->first();
if (in_array($supportedDefaultSubmissionLocale, array_keys($affectedLocales))) {
DB::table($this->getContextSettingsTable())
->where('setting_name', '=', 'supportedDefaultSubmissionLocale')
->update(['setting_value' => $affectedLocales[$supportedDefaultSubmissionLocale]]);
}

$contextLocaleSettingNames = [
'supportedFormLocales',
'supportedLocales',
'supportedSubmissionLocales',
'supportedAddedSubmissionLocales',
'supportedSubmissionMetadataLocales',
];
$this->updateArrayLocale($this->getContextSettingsTable(), 'setting_value', $contextLocaleSettingNames);


// plugin_settings, customBlockManager
// assume that setting names blockTitle and blockContent are only used in customBlockManager
$blockLocalizedSettingNames = ['blockTitle', 'blockContent'];
$this->updateArrayLocale('plugin_settings', 'setting_value', $blockLocalizedSettingNames, true);

Cache::forget($cacheKey);
}

/**
* Update locale arrays, and locales as array keys
*/
public function updateArrayLocale(string $tableName, string $columnName, ?array $settingNames = null, ?bool $key = false)
{
$affectedLocales = $this->getAffectedLocales();
$key = $key ? ':' : '';
$replaceString = $columnName;
foreach ($affectedLocales as $oldLocale => $newLocale) {
$replaceString = "REPLACE({$replaceString}, '\"{$oldLocale}\"{$key}', '\"{$newLocale}\"{$key}')";
}
DB::table($tableName)
->when(
isset($settingNames),
fn (Builder $query) => $query->whereIn('setting_name', $settingNames)
)
->update([$columnName => DB::raw($replaceString)]);
}

/**
* Returns the effected locales along with the corresponding rename for each
*/
public static function getAffectedLocales(): array
{
return [
'be@cyrillic' => 'be',
'bs' => 'bs_Latn',
'fr_FR' => 'fr',
Expand All @@ -39,17 +133,6 @@ public function up(): void
'uz@latin' => 'uz_Latn',
'zh_CN' => 'zh_Hans',
];

$schemaLocName = (DB::connection() instanceof PostgresConnection) ? 'TABLE_CATALOG' : 'TABLE_SCHEMA';
$renameLocale = fn (string $l) => collect(DB::select("SELECT DISTINCT TABLE_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE COLUMN_NAME = ? AND {$schemaLocName} = ?", [$l, DB::connection()->getDatabaseName()]))
->each(function (\stdClass $sc) use ($l, $localesTable) {
foreach ($localesTable as $uiLocale => $weblateLocale) {
DB::table($sc->TABLE_NAME ?? $sc->table_name)->where($l, '=', $uiLocale)->update([$l => $weblateLocale]);
}
});

$renameLocale('primary_locale');
$renameLocale('locale');
}

/**
Expand Down

0 comments on commit adacbdb

Please sign in to comment.