Skip to content

Load polyfills correctly for the new sqlite version (v2.2.22)#24

Merged
katinthehatsite merged 12 commits intomainfrom
fix/new-structure-compatibility
Apr 9, 2026
Merged

Load polyfills correctly for the new sqlite version (v2.2.22)#24
katinthehatsite merged 12 commits intomainfrom
fix/new-structure-compatibility

Conversation

@katinthehatsite
Copy link
Copy Markdown
Contributor

@katinthehatsite katinthehatsite commented Apr 8, 2026

Closes STU-1529

In v2.2.22+ for the sqlite-database-integration, php-polyfills.php moved to wp-includes/database/php-polyfills.php. If you try to push a newly created site in Studio with that version, it will immediately fail due not being able to load php-polyfills.php. This PR adds a backwards compatible fix for it.

Testing instructions

  • Create a new site in Studio (does not matter with which PHP version)
  • Connect WP.com site
  • Try pushing the site
  • Confirm that the push fails

  • Copy the fixed SQLiteDatabaseIntegrationLoader.php from this branch to ~/.studio/server-files/sqlite-command/src/SQLiteDatabaseIntegrationLoader.php
  • Pin the version to prevent the app from overwriting your changes on restart: set the contents of ~/.studio/server-files/sqlite-command/version to v99.99.99
  • Restart Studio
  • Create a new site with any PHP version (you can use PHP 8.5 for good measure)
  • Go to the Sync tab
  • Connect a WP.com site
  • Start the push process
  • Confirm there are no errors due to loading polyfills (there will be another error in PHP 8.5 - all other versions will work fine with this fix - related to deprecated warning but it will be solved in a different Studio PR)

@katinthehatsite katinthehatsite self-assigned this Apr 8, 2026
@katinthehatsite katinthehatsite force-pushed the fix/new-structure-compatibility branch from b098ba7 to 100d0a4 Compare April 8, 2026 13:52
@katinthehatsite katinthehatsite requested a review from a team April 8, 2026 15:42
Copy link
Copy Markdown
Contributor

@fredrikekelund fredrikekelund left a comment

Choose a reason for hiding this comment

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

Rather than supporting two different file structures, I think we should consider updating the version check for the sqlite-database-integration plugin.

@fredrikekelund
Copy link
Copy Markdown
Contributor

The PR tests well, though. I can confirm that it fixes the problem for me locally 👍

@fredrikekelund
Copy link
Copy Markdown
Contributor

OK, hold on a minute… Studio checks for remote updates to this dependency, but not for sqlite-database-integration. That means we ship a variable version of this dependency but a fixed version of sqlite-database-integration.

Zooming out for a moment, this seems like a less-than-ideal strategy because these two dependencies are actually relatively tightly coupled. Nonetheless, that's how it works. So my suggestion to support a single file structure in sqlite-database-integration wouldn't really work, because we can't be sure which bundled version of sqlite-database-integration the user has locally.

@fredrikekelund
Copy link
Copy Markdown
Contributor

It looks like the failed tests are due to some recent update in https://github.com/wp-cli/wp-cli-tests. AFAICT, we didn't run those tests in other recent PRs.

Copy link
Copy Markdown
Contributor

@fredrikekelund fredrikekelund left a comment

Choose a reason for hiding this comment

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

This PR works well – it does what it says on the tin 👍

However, I still can't push a site using PHP 8.5, so it doesn't fix STU-1529 for me. Here are my error logs for when I try to push a site that uses PHP 8.5.

["wp_commentmeta","wp_comments","wp_links","wp_options","wp_postmeta","wp_posts","wp_term_relationships","wp_term_taxonomy","wp_termmeta","wp_terms","wp_usermeta","wp_users"]
Error occurred in handler for 'exportSiteForPush': Error: Database export failed: PHP Deprecated:  Case statements followed by a semicolon (;) are deprecated, use a colon (:) instead in phar:///tmp/wp-cli.phar/vendor/react/promise/src/functions.php on line 369

    at exportDatabaseToMultipleFiles (/Users/fredrik/Code/studio/apps/studio/dist/main/index.js:28293:11)
    at async DefaultExporter.addDatabase (/Users/fredrik/Code/studio/apps/studio/dist/main/index.js:28553:24)
    at async DefaultExporter.export (/Users/fredrik/Code/studio/apps/studio/dist/main/index.js:28450:7)
    at async exportBackup (/Users/fredrik/Code/studio/apps/studio/dist/main/index.js:28691:9)
    at async exportSiteForPush (/Users/fredrik/Code/studio/apps/studio/dist/main/index.js:44236:5)
    at async Session.<anonymous> (node:electron/js2c/browser_init:2:116791)

Comment on lines +127 to +166
$db = $plugin_directory . '/wp-includes/database';
return [
"$db/version.php",
"$db/parser/class-wp-parser-grammar.php",
"$db/parser/class-wp-parser.php",
"$db/parser/class-wp-parser-node.php",
"$db/parser/class-wp-parser-token.php",
"$db/mysql/class-wp-mysql-token.php",
"$db/mysql/class-wp-mysql-lexer.php",
"$db/mysql/class-wp-mysql-parser.php",
"$db/sqlite/class-wp-sqlite-pdo-user-defined-functions.php",
"$db/sqlite/class-wp-sqlite-connection.php",
"$db/sqlite/class-wp-sqlite-configurator.php",
"$db/sqlite/class-wp-sqlite-driver.php",
"$db/sqlite/class-wp-sqlite-driver-exception.php",
"$db/sqlite/class-wp-sqlite-information-schema-builder.php",
"$db/sqlite/class-wp-sqlite-information-schema-exception.php",
"$db/sqlite/class-wp-sqlite-information-schema-reconstructor.php",
];
}

$wp = $plugin_directory . '/wp-includes';
return [
$plugin_directory . '/version.php',
"$wp/parser/class-wp-parser-grammar.php",
"$wp/parser/class-wp-parser.php",
"$wp/parser/class-wp-parser-node.php",
"$wp/parser/class-wp-parser-token.php",
"$wp/mysql/class-wp-mysql-token.php",
"$wp/mysql/class-wp-mysql-lexer.php",
"$wp/mysql/class-wp-mysql-parser.php",
"$wp/sqlite/class-wp-sqlite-pdo-user-defined-functions.php",
"$wp/sqlite-ast/class-wp-sqlite-connection.php",
"$wp/sqlite-ast/class-wp-sqlite-configurator.php",
"$wp/sqlite-ast/class-wp-sqlite-driver.php",
"$wp/sqlite-ast/class-wp-sqlite-driver-exception.php",
"$wp/sqlite-ast/class-wp-sqlite-information-schema-builder.php",
"$wp/sqlite-ast/class-wp-sqlite-information-schema-exception.php",
"$wp/sqlite-ast/class-wp-sqlite-information-schema-reconstructor.php",
];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Since we're not using the same array to load the files, the $db and $wp prefixing seems kind of arbitrary to me. I'd spell out the full $plugin_directory . $path

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Comment on lines +177 to +181
require_once "$sqlite/class-wp-sqlite-lexer.php";
require_once "$sqlite/class-wp-sqlite-query-rewriter.php";
require_once "$sqlite/class-wp-sqlite-translator.php";
require_once "$sqlite/class-wp-sqlite-token.php";
require_once "$sqlite/class-wp-sqlite-pdo-user-defined-functions.php";
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Nitpicking, but still, I'd definitely spell out the full $plugin_directory . $path here.

Copy link
Copy Markdown
Contributor

@JanJakes JanJakes left a comment

Choose a reason for hiding this comment

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

Thanks for working on this! I totally missed the wp-pdo-mysql-on-sqlite.php back-compatibility angle. Sorry about that. I shared a few ideas for improvements and simplifications.

*/
private static function load_ast_driver( $plugin_directory, $new_structure ) {
if ( file_exists( $plugin_directory . '/wp-pdo-mysql-on-sqlite.php' ) ) {
require_once $plugin_directory . '/wp-pdo-mysql-on-sqlite.php';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Not keeping require_once $plugin_directory . '/wp-pdo-mysql-on-sqlite.php'; in 2.2.21 and 2.2.22 was an oversight, but rather than listing the plugin files, we can just add this:

} elseif ( file_exists( $plugin_directory . '/wp-includes/database/load.php' ) ) {
    require_once '$plugin_directory . '/wp-includes/database/load.php';
}

The rest of the diff is not needed.

Comment on lines +127 to +166
$db = $plugin_directory . '/wp-includes/database';
return [
"$db/version.php",
"$db/parser/class-wp-parser-grammar.php",
"$db/parser/class-wp-parser.php",
"$db/parser/class-wp-parser-node.php",
"$db/parser/class-wp-parser-token.php",
"$db/mysql/class-wp-mysql-token.php",
"$db/mysql/class-wp-mysql-lexer.php",
"$db/mysql/class-wp-mysql-parser.php",
"$db/sqlite/class-wp-sqlite-pdo-user-defined-functions.php",
"$db/sqlite/class-wp-sqlite-connection.php",
"$db/sqlite/class-wp-sqlite-configurator.php",
"$db/sqlite/class-wp-sqlite-driver.php",
"$db/sqlite/class-wp-sqlite-driver-exception.php",
"$db/sqlite/class-wp-sqlite-information-schema-builder.php",
"$db/sqlite/class-wp-sqlite-information-schema-exception.php",
"$db/sqlite/class-wp-sqlite-information-schema-reconstructor.php",
];
}

$wp = $plugin_directory . '/wp-includes';
return [
$plugin_directory . '/version.php',
"$wp/parser/class-wp-parser-grammar.php",
"$wp/parser/class-wp-parser.php",
"$wp/parser/class-wp-parser-node.php",
"$wp/parser/class-wp-parser-token.php",
"$wp/mysql/class-wp-mysql-token.php",
"$wp/mysql/class-wp-mysql-lexer.php",
"$wp/mysql/class-wp-mysql-parser.php",
"$wp/sqlite/class-wp-sqlite-pdo-user-defined-functions.php",
"$wp/sqlite-ast/class-wp-sqlite-connection.php",
"$wp/sqlite-ast/class-wp-sqlite-configurator.php",
"$wp/sqlite-ast/class-wp-sqlite-driver.php",
"$wp/sqlite-ast/class-wp-sqlite-driver-exception.php",
"$wp/sqlite-ast/class-wp-sqlite-information-schema-builder.php",
"$wp/sqlite-ast/class-wp-sqlite-information-schema-exception.php",
"$wp/sqlite-ast/class-wp-sqlite-information-schema-reconstructor.php",
];
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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


require_once $new_structure
? $plugin_directory . '/wp-includes/database/php-polyfills.php'
: $plugin_directory . '/php-polyfills.php';
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

These php-polyfills preloads are only relevant for the old structure. The new structure includes them in $plugin_directory . '/wp-includes/database/load.php'. See also https://github.com/Automattic/wp-cli-sqlite-command/pull/24/changes#r3057297293.

In other words, it's safe to include this file only if it exists:

if ( file_exists( $plugin_directory . '/php-polyfills.php' ) {
    require_once $plugin_directory . '/php-polyfills.php';
}

// We also need to selectively load the necessary classes from the plugin.
require_once $plugin_directory . '/php-polyfills.php';
// In v2.2.22+, files moved into wp-includes/database/ subdirectories.
$new_structure = file_exists( $plugin_directory . '/wp-includes/database/php-polyfills.php' );
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Maybe it's safer to check for the old structure, as in:

$old_structure = file_exists( $plugin_directory . '/php-polyfills.php' );

Or for the new structure using $plugin_directory . '/wp-includes/database/load.php'. It will be safer than relying on the existence of the polyfill file.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Applied the suggestion 👍


if ( $new_driver_enabled && file_exists( $plugin_directory . '/wp-pdo-mysql-on-sqlite.php' ) ) {
require_once $plugin_directory . '/wp-pdo-mysql-on-sqlite.php';
} elseif ( $new_driver_enabled ) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

@katinthehatsite This branch actually also needs to stay in the code for now. I guess I should've expressed it clearer, as in, let's only add the new case to the existing ones:

} elseif ( file_exists( $plugin_directory . '/wp-includes/database/load.php' ) ) {
	require_once $plugin_directory . '/wp-includes/database/load.php';
}

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Added them back now 👍

Copy link
Copy Markdown
Contributor

@JanJakes JanJakes left a comment

Choose a reason for hiding this comment

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

Looks good, thanks!

@katinthehatsite katinthehatsite merged commit 26cade0 into main Apr 9, 2026
56 checks passed
"email": "jeroen.pfeil@automattic.com"
}
],
"minimum-stability": "dev",
Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I tried without these but it did not work for using wp-cli/wp-cli": "^2.13 so Claude recommended adding this

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.

3 participants