-
Notifications
You must be signed in to change notification settings - Fork 1k
Add early check for iconv/mbstring extensions to prevent fatal errors #6185
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
base: main
Are you sure you want to change the base?
Conversation
Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
Co-authored-by: swissspidy <841956+swissspidy@users.noreply.github.com>
Codecov Report❌ Patch coverage is
📢 Thoughts on this report? Let us know! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adds an early check for mbstring/iconv extensions to prevent fatal errors during WP-CLI bootstrap. When Symfony's polyfill-mbstring requires ext-iconv but both extensions are missing, WP-CLI encounters a fatal error. The solution adds a validation check early in the bootstrap process to provide a clear error message instead.
- Added extension check in
php/boot-fs.phpafter PHP version check to exit gracefully with a helpful error message - Added unit tests to verify the extension check exists and at least one extension is available
- Added Behat scenario to test the extension check behavior
Reviewed changes
Copilot reviewed 4 out of 4 changed files in this pull request and generated 1 comment.
| File | Description |
|---|---|
| php/boot-fs.php | Added early extension check for mbstring/iconv with clear error messaging |
| tests/BootFsTest.php | Unit tests to verify extension check exists and environment has required extensions |
| tests/bootstrap.php | Load TestCase class from wp-cli-tests package for test compatibility |
| features/bootstrap.feature | Behat scenario testing the extension check logic with mock file |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| * Test that the boot-fs.php file contains the extension check | ||
| */ | ||
| public function testExtensionCheckExists() { | ||
| $boot_fs_content = file_get_contents( WP_CLI_ROOT . '/php/boot-fs.php' ); | ||
|
|
||
| // Ensure file was read successfully | ||
| $this->assertNotFalse( $boot_fs_content, 'Could not read boot-fs.php file' ); | ||
|
|
||
| // Check that the file contains the extension check | ||
| $this->assertStringContainsString( 'extension_loaded', $boot_fs_content ); | ||
| $this->assertStringContainsString( 'mbstring', $boot_fs_content ); | ||
| $this->assertStringContainsString( 'iconv', $boot_fs_content ); | ||
| $this->assertStringContainsString( 'WP-CLI requires the mbstring or iconv PHP extension', $boot_fs_content ); | ||
| } | ||
|
|
||
| /** |
Copilot
AI
Jan 9, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The test testExtensionCheckExists() uses string matching to verify the extension check exists in the boot-fs.php file. This approach is fragile because it tests implementation details rather than behavior. If the code is refactored (e.g., strings are changed, variable names updated), the test could fail even if the functionality works correctly.
Consider testing the behavior instead by using a Behat scenario (which already exists) or by testing the actual exit behavior when extensions are missing. However, given that boot-fs.php is early bootstrap code that terminates the process, string matching may be a pragmatic approach in this specific case.
| * Test that the boot-fs.php file contains the extension check | |
| */ | |
| public function testExtensionCheckExists() { | |
| $boot_fs_content = file_get_contents( WP_CLI_ROOT . '/php/boot-fs.php' ); | |
| // Ensure file was read successfully | |
| $this->assertNotFalse( $boot_fs_content, 'Could not read boot-fs.php file' ); | |
| // Check that the file contains the extension check | |
| $this->assertStringContainsString( 'extension_loaded', $boot_fs_content ); | |
| $this->assertStringContainsString( 'mbstring', $boot_fs_content ); | |
| $this->assertStringContainsString( 'iconv', $boot_fs_content ); | |
| $this->assertStringContainsString( 'WP-CLI requires the mbstring or iconv PHP extension', $boot_fs_content ); | |
| } | |
| /** |
|
This looks solid overall 👍 One option could be to exclude this block from coverage, or alternatively rely on the existing Behat scenario as sufficient behavioral coverage for this case. Curious what you think is the preferred approach here. |
Symfony's
polyfill-mbstringrequiresext-iconvbut Symfony doesn't requirepolyfill-iconv. When bothmbstringandiconvextensions are missing, WP-CLI encounters a fatal error during bootstrap.Changes
php/boot-fs.php: Added extension check after PHP version check. Exits with clear error message if both extensions are missing.tests/BootFsTest.php: Unit tests verify the check exists and at least one extension is available in test environments.features/bootstrap.feature: Behat scenario tests the extension check logic.tests/bootstrap.php: LoadTestCaseclass fromwp-cli-testspackage for test compatibility.Related Issues
Addresses issues raised in #4700 and #4682 regarding the Symfony polyfill dependency chain.
Warning
Firewall rules blocked me from connecting to one or more addresses (expand for details)
I tried to connect to the following addresses, but was blocked by firewall rules:
example.com/usr/bin/php php vendor/bin/phpunit --color=always --bootstrap ./vendor/wp-cli/wp-cli-tests/tests/bootstrap.php '-d short_open_tag=Off' '-d error_reporting=E_ALL' '-n' '-l' './bundle/rmccue/requests/src/Transsh(dns block)nosuchhost_asdf_asdf_asdf.com/usr/bin/php php vendor/bin/phpunit --color=always --bootstrap ./vendor/wp-cli/wp-cli-tests/tests/bootstrap.php '-d short_open_tag=Off' '-d error_reporting=E_ALL' '-n' '-l' './bundle/rmccue/requests/src/Transsh(dns block)If you need me to access, download, or install something from one of these locations, you can either:
Original prompt
💡 You can make Copilot smarter by setting up custom instructions, customizing its development environment and configuring Model Context Protocol (MCP) servers. Learn more Copilot coding agent tips in the docs.