Skip to content

Refactor: Modularize Locale service and fix DSN path parsing#11152

Open
khoinp1012 wants to merge 1 commit intoappwrite:mainfrom
khoinp1012:feature/locale-refactor
Open

Refactor: Modularize Locale service and fix DSN path parsing#11152
khoinp1012 wants to merge 1 commit intoappwrite:mainfrom
khoinp1012:feature/locale-refactor

Conversation

@khoinp1012
Copy link

This Pull Request refactors the Locale Service into a modular, action-based architecture, aligning it with the latest Appwrite Platform standards. It also includes a critical bug fix for database connection strings and improves system startup resilience.

🚀 Key Changes:
Modular Locale Actions: Migrated the monolithic Locale controller logic into individual, reusable Action classes under src/Appwrite/Platform/Modules/Locale/Http/Locale/.
Get: General locale information.
ListCodes: Available locale codes.
ListContinents, ListCountries, ListCountriesEU, ListCountriesPhones: Specialized geography listings.
ListCurrencies: Currency information.
ListLanguages: Language support.
Platform Integration: Integrated the new Locale module into the Appwrite Platform module registration (Appwrite.php).
DSN Path Bug Fix: Fixed an issue in app/init/registers.php where database names were parsed incorrectly if a leading slash was present in the DSN path (e.g., mysql://user:pass@host/db).
Startup Resilience: Increased database connection retry logic in app/http.php to ensure the server starts reliably even when MariaDB takes longer to initialize in some environments.
🛠 Verification:
Created and executed standalone unit tests within the Docker environment to verify the new Action classes.
Verified that all Locale endpoints correctly load their respective data from the Utopia\Locale source.
Validated that the ltrim fix correctly resolves the "Unknown database" errors caused by DSN formatting.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 17, 2026

📝 Walkthrough

Walkthrough

This PR performs a major architectural refactoring by removing the legacy Swoole-based HTTP server implementation (app/http.php, 607 lines) and development Docker stack (docker-compose.yml, 1302 lines), along with environment and gitignore configuration files. In parallel, it migrates locale API endpoints from the monolithic controller at app/controllers/api/locale.php to a new modular platform architecture under src/Appwrite/Platform/Modules/Locale/. Eight new endpoint handler classes are introduced (Get, ListCodes, ListContinents, ListCountries, ListCountriesEU, ListCountriesPhones, ListCurrencies, ListLanguages) alongside module registration and HTTP service infrastructure. A minor DSN database name handling fix removes leading slashes in app/init/registers.php.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Notes

The review requires verification across multiple dimensions: confirming the removed HTTP server logic has been properly replaced by the new modular architecture, ensuring all eight migrated locale endpoints function equivalently to their predecessors, validating that no request handling or error logic is lost during the transition, and checking that module registration is correctly integrated. While the eight new endpoint classes follow a highly repetitive pattern (reducing individual review burden per file), the two large file deletions—particularly app/http.php containing database provisioning, request dispatching, and lifecycle management—demand careful confirmation that their responsibilities have been adequately transferred. The straightforward removal of configuration files and the focused DSN trim operation have lower complexity but contribute to overall scope.

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the two main changes: modularizing the Locale service and fixing DSN path parsing, which are the primary focus of this PR.
Description check ✅ Passed The description is directly related to the changeset, detailing the Locale service refactoring, module integration, DSN bug fix, and startup resilience improvements that are reflected in the file changes.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🤖 Fix all issues with AI agents
In `@src/Appwrite/Platform/Modules/Locale/Http/Locale/Get.php`:
- Around line 71-75: The foreach loop is declaring an unused key variable
($code) and keeps scanning after a match; change the loop to iterate over values
only (foreach ($currencies as $element)) and add a break once you assign
$currency inside the conditional that checks isset($element['locations']) &&
isset($element['code']) && in_array($record['country']['iso_code'],
$element['locations']) so the loop stops after the first match.

In `@src/Appwrite/Platform/Modules/Locale/Http/Locale/ListCountriesPhones.php`:
- Around line 52-60: The foreach currently declares ($list as $code => $name)
but still references $list[$code], leaving $name unused; update the loop in
ListCountriesPhones (the foreach over $list) to use the provided $name variable
where the phone value is needed (replace $list[$code] with $name) when
constructing the Document (the 'code' => '+' . ... expression) so you avoid the
redundant array lookup and the unused $name variable.

Comment on lines +71 to +75
foreach ($currencies as $code => $element) {
if (isset($element['locations']) && isset($element['code']) && \in_array($record['country']['iso_code'], $element['locations'])) {
$currency = $element['code'];
}
}
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Remove unused loop variable $code.

The static analysis tool correctly identifies that $code is unused in this loop. Additionally, the loop continues iterating even after finding a matching currency, which is inefficient.

Proposed fix
-            foreach ($currencies as $code => $element) {
-                if (isset($element['locations']) && isset($element['code']) && \in_array($record['country']['iso_code'], $element['locations'])) {
-                    $currency = $element['code'];
-                }
-            }
+            foreach ($currencies as $element) {
+                if (isset($element['locations'], $element['code']) && \in_array($record['country']['iso_code'], $element['locations'])) {
+                    $currency = $element['code'];
+                    break;
+                }
+            }
🧰 Tools
🪛 PHPMD (2.15.0)

71-71: Avoid unused local variables such as '$code'. (undefined)

(UnusedLocalVariable)

🤖 Prompt for AI Agents
In `@src/Appwrite/Platform/Modules/Locale/Http/Locale/Get.php` around lines 71 -
75, The foreach loop is declaring an unused key variable ($code) and keeps
scanning after a match; change the loop to iterate over values only (foreach
($currencies as $element)) and add a break once you assign $currency inside the
conditional that checks isset($element['locations']) && isset($element['code'])
&& in_array($record['country']['iso_code'], $element['locations']) so the loop
stops after the first match.

Comment on lines +52 to +60
\asort($list);

foreach ($list as $code => $name) {
if ($locale->getText('countries.' . \strtolower($code), false) !== false) {
$output[] = new Document([
'code' => '+' . $list[$code],
'countryCode' => $code,
'countryName' => $locale->getText('countries.' . \strtolower($code)),
]);
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Use the foreach value to avoid an unused variable.
Line 54 introduces $name but it is never used; use it directly and avoid the extra $list[$code] lookup.

🛠️ Proposed fix
-        foreach ($list as $code => $name) {
+        foreach ($list as $code => $name) {
             if ($locale->getText('countries.' . \strtolower($code), false) !== false) {
                 $output[] = new Document([
-                    'code' => '+' . $list[$code],
+                    'code' => '+' . $name,
                     'countryCode' => $code,
                     'countryName' => $locale->getText('countries.' . \strtolower($code)),
                 ]);
             }
         }
🧰 Tools
🪛 PHPMD (2.15.0)

54-54: Avoid unused local variables such as '$name'. (undefined)

(UnusedLocalVariable)

🤖 Prompt for AI Agents
In `@src/Appwrite/Platform/Modules/Locale/Http/Locale/ListCountriesPhones.php`
around lines 52 - 60, The foreach currently declares ($list as $code => $name)
but still references $list[$code], leaving $name unused; update the loop in
ListCountriesPhones (the foreach over $list) to use the provided $name variable
where the phone value is needed (replace $list[$code] with $name) when
constructing the Document (the 'code' => '+' . ... expression) so you avoid the
redundant array lookup and the unused $name variable.

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.

1 participant