Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

pkp/pkp-lib#10729 fix I9707_WeblateUILocales, consider locales in arr… #10734

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

bozana
Copy link
Collaborator

@bozana bozana commented Dec 18, 2024

…ays and setting values

s. #10729

Comment on lines +25 to +27
protected string $CONTEXT_TABLE = '';
protected string $CONTEXT_SETTINGS_TABLE = '';
protected string $CONTEXT_COLUMN = '';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the pattern at the other migration of this PR is better (i.e. you're forced to provide the values):

Suggested change
protected string $CONTEXT_TABLE = '';
protected string $CONTEXT_SETTINGS_TABLE = '';
protected string $CONTEXT_COLUMN = '';
abstract protected function getContextTable(): string;
abstract protected function getContextSettingsTable(): string;
abstract protected function getContextIdColumn(): string;

Comment on lines +96 to +100
DB::select(
"
SELECT DISTINCT TABLE_NAME
FROM INFORMATION_SCHEMA.COLUMNS
WHERE COLUMN_NAME = ? AND {$schemaLocName} = ?",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the database has few tables/columns to loop through, then the Schema::getAllTables() (or the DB::getDoctrineSchemaManager()->listXXX()) together with the Schema::getColumns() will provide a better compatibility and simplify the code.

It's also possible to cache the return of getAllTables()/getColumns() to have less database requests.

Comment on lines +205 to +209
$affectedLocales = $this->getAffectedLocales();
if (!in_array($localeValue, array_keys($affectedLocales))) {
return null;
}
return $affectedLocales[$localeValue];
Copy link
Contributor

@jonasraoni jonasraoni Jan 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
$affectedLocales = $this->getAffectedLocales();
if (!in_array($localeValue, array_keys($affectedLocales))) {
return null;
}
return $affectedLocales[$localeValue];
return $this->getAffectedLocales()[$localeValue] ?? null;

Or a safer option with fallback (requires reviewing if it makes sense on the call sites)

Suggested change
$affectedLocales = $this->getAffectedLocales();
if (!in_array($localeValue, array_keys($affectedLocales))) {
return null;
}
return $affectedLocales[$localeValue];
return $this->getAffectedLocales()[$localeValue] ?? $localeValue;

Comment on lines +37 to +38
$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()]))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given the database has few tables/columns to loop through, then the Schema::getAllTables() (or the DB::getDoctrineSchemaManager()->listXXX()) together with the Schema::getColumns() will provide a better compatibility and simplify the code.

It's also possible to cache the return of getAllTables()/getColumns() to have less database requests.

$this->updateArrayLocale($site->installed_locales, 'site', 'installed_locales');

// users locales
$migration = $this;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this isn't needed, you can just use $this inside the function.

Comment on lines +40 to +42
foreach ($affectedLocales as $uiLocale => $weblateLocale) {
DB::table($sc->TABLE_NAME ?? $sc->table_name)->where($l, '=', $uiLocale)->update([$l => $weblateLocale]);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This loop can be turned into a single query:
...->whereIn($l, $uiLocales)->update([$l => DB::raw("CASE {$l} WHEN X THEN A WHEN Y THEN B END")]);.

Comment on lines +56 to +60
DB::table('users')->chunkById(1000, function ($users) use ($migration) {
foreach ($users as $user) {
$migration->updateArrayLocale($user->locales, 'users', 'locales', null, 'user_id', $user->user_id);
}
}, 'user_id');
Copy link
Contributor

@jonasraoni jonasraoni Jan 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As these "array" columns are using JSON, then the updateArrayLocale() method could be updated to issue a single query, basically a sequence of self-enclosed replaces (e.g. locales = REPLACE(REPLACE(locales, '"X"', "A"), '"Y"', "B")).

Some installations have thousands of users, due to spammers, so anything that avoids looping through the users is worth in my opinion.

->first();

if (isset($blockLocalizedContent)) {
$this->updateArrayKeysLocaleSetting($blockLocalizedContent->setting_value, 'plugin_settings', 'plugin_setting_id', $blockLocalizedContent->plugin_setting_id);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I reviewed fast, but it seems to me that this method is doing something similar to the updateArrayLocale().

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants