Skip to content

Commit 4cfe524

Browse files
authored
Merge Automattic fork changes (#180)
This PR merges the changes from [the Automattic SQLite fork](https://github.com/Automattic/sqlite-database-integration) as [Automattic is resuming WordPress contributions](https://automattic.com/2025/05/29/returning-to-core/). The fork will be archived and can be found here: https://github.com/Automattic/sqlite-database-integration List or PRs: https://github.com/Automattic/sqlite-database-integration/pulls?q=is%3Apr **Let's merge this PR as is without squashing. These individual commits carry a lot of context.**
2 parents 271163b + a6a760e commit 4cfe524

File tree

58 files changed

+17735
-1694
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

58 files changed

+17735
-1694
lines changed

.gitattributes

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@
55
composer.json export-ignore
66
phpcs.xml.dist export-ignore
77
phpunit.xml.dist export-ignore
8+
wp-setup.sh export-ignore
89
/.github export-ignore
910
/grammar-tools export-ignore
1011
/tests export-ignore
11-
/wip export-ignore
12-
/wp-includes/mysql export-ignore
13-
/wp-includes/parser export-ignore
1412
/wp-includes/sqlite/class-wp-sqlite-crosscheck-db.php export-ignore
13+
/wordpress export-ignore

.github/workflows/phpunit-tests.yml

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,7 @@ jobs:
1717
fail-fast: false
1818
matrix:
1919
os: [ ubuntu-latest ]
20-
# NOTE: There does not appear to be a single phpunit version that supports all
21-
# PHP versions tested here. For now, we are removing PHP 7.0. and 7.1 tests
22-
# in order to run a single phpunit version for PHP 7.2 and up.
23-
php: [ '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3' ]
20+
php: [ '7.2', '7.3', '7.4', '8.0', '8.1', '8.2', '8.3', '8.4' ]
2421

2522
with:
2623
os: ${{ matrix.os }}

.github/workflows/verify-version.yml

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
name: Verify plugin version
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
9+
jobs:
10+
verify-version:
11+
name: Assert the WordPress plugin header declares the same version as the SQLITE_DRIVER_VERSION constant
12+
runs-on: ubuntu-latest
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- name: Extract version from "load.php"
17+
id: load_version
18+
run: |
19+
VERSION=$(grep "Version:" load.php | sed "s/.*Version: \([^ ]*\).*/\1/")
20+
echo "load_version=$VERSION" >> $GITHUB_OUTPUT
21+
22+
- name: Extract version from "version.php"
23+
id: const_version
24+
run: |
25+
VERSION=$(php -r "require 'version.php'; echo SQLITE_DRIVER_VERSION;")
26+
echo "const_version=$VERSION" >> $GITHUB_OUTPUT
27+
28+
- name: Compare versions
29+
run: |
30+
if [ "${{ steps.load_version.outputs.load_version }}" != "${{ steps.const_version.outputs.const_version }}" ]; then
31+
echo "Version mismatch detected!"
32+
echo " load.php version: ${{ steps.load_version.outputs.load_version }}"
33+
echo " version.php constant: ${{ steps.const_version.outputs.const_version }}"
34+
exit 1
35+
fi
Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,142 @@
1+
/*
2+
* Wrap the "composer run wp-tests-phpunit" command to process tests
3+
* that are expected to error and fail at the moment.
4+
*
5+
* This makes sure that the CI job passes, while explicitly tracking
6+
* the issues that need to be addressed. Ideally, over time this script
7+
* will become obsolete when all errors and failures are resolved.
8+
*/
9+
const { execSync } = require( 'child_process' );
10+
const fs = require( 'fs' );
11+
const path = require( 'path' );
12+
13+
const expectedErrors = [
14+
'Tests_DB_Charset::test_strip_invalid_text',
15+
'Tests_DB::test_db_reconnect',
16+
'Tests_DB::test_get_col_info',
17+
'Tests_DB::test_process_fields_value_too_long_for_field with data set "invalid chars"',
18+
'Tests_DB::test_process_fields_value_too_long_for_field with data set "too long"',
19+
'Tests_DB::test_process_fields',
20+
];
21+
22+
const expectedFailures = [
23+
'Tests_Admin_wpSiteHealth::test_object_cache_thresholds with data set #2',
24+
'Tests_Admin_wpSiteHealth::test_object_cache_thresholds with data set #3',
25+
'Tests_Comment::test_wp_new_comment_respects_comment_field_lengths',
26+
'Tests_Comment::test_wp_update_comment',
27+
'Tests_DB_dbDelta::test_spatial_indices',
28+
'Tests_DB::test_charset_switched_to_utf8mb4',
29+
'Tests_DB::test_close',
30+
'Tests_DB::test_delete_value_too_long_for_field with data set "too long"',
31+
'Tests_DB::test_has_cap',
32+
'Tests_DB::test_insert_value_too_long_for_field with data set "too long"',
33+
'Tests_DB::test_mysqli_flush_sync',
34+
'Tests_DB::test_non_unicode_collations',
35+
'Tests_DB::test_query_value_contains_invalid_chars',
36+
'Tests_DB::test_replace_value_too_long_for_field with data set "too long"',
37+
'Tests_DB::test_replace',
38+
'Tests_DB::test_supports_collation',
39+
'Tests_DB::test_update_value_too_long_for_field with data set "too long"',
40+
'Tests_Menu_Walker_Nav_Menu::test_start_el_with_empty_attributes with data set #1',
41+
'Tests_Menu_Walker_Nav_Menu::test_start_el_with_empty_attributes with data set #2',
42+
'Tests_Menu_Walker_Nav_Menu::test_start_el_with_empty_attributes with data set #3',
43+
'Tests_Menu_Walker_Nav_Menu::test_start_el_with_empty_attributes with data set #4',
44+
'Tests_Menu_Walker_Nav_Menu::test_start_el_with_empty_attributes with data set #5',
45+
'Tests_Menu_Walker_Nav_Menu::test_start_el_with_empty_attributes with data set #6',
46+
'Tests_Menu_Walker_Nav_Menu::test_start_el_with_empty_attributes with data set #7',
47+
'Tests_Menu_wpNavMenu::test_wp_nav_menu_should_not_have_has_children_class_with_custom_depth',
48+
'WP_Test_REST_Posts_Controller::test_get_items_orderby_modified_query',
49+
];
50+
51+
console.log( 'Running WordPress PHPUnit tests with expected failures tracking...' );
52+
console.log( 'Expected errors:', expectedErrors );
53+
console.log( 'Expected failures:', expectedFailures );
54+
55+
try {
56+
try {
57+
execSync(
58+
`composer run wp-test-phpunit -- --log-junit=phpunit-results.xml --verbose`,
59+
{ stdio: 'inherit' }
60+
);
61+
console.log( '\n⚠️ All tests passed, checking if expected errors/failures occurred...' );
62+
} catch ( error ) {
63+
console.log( '\n⚠️ Some tests errored/failed (expected). Analyzing results...' );
64+
}
65+
66+
// Read the JUnit XML test output:
67+
const junitOutputFile = path.join( __dirname, '..', '..', 'wordpress', 'phpunit-results.xml' );
68+
if ( ! fs.existsSync( junitOutputFile ) ) {
69+
console.error( 'Error: JUnit output file not found!' );
70+
process.exit( 1 );
71+
}
72+
const junitXml = fs.readFileSync( junitOutputFile, 'utf8' );
73+
74+
// Extract test info from the XML:
75+
const actualErrors = [];
76+
const actualFailures = [];
77+
for ( const testcase of junitXml.matchAll( /<testcase([^>]*)\/>|<testcase([^>]*)>([\s\S]*?)<\/testcase>/g ) ) {
78+
const attributes = {};
79+
const attributesString = testcase[2] ?? testcase[1];
80+
for ( const attribute of attributesString.matchAll( /(\w+)="([^"]*)"/g ) ) {
81+
attributes[attribute[1]] = attribute[2];
82+
}
83+
84+
const content = testcase[3] ?? '';
85+
const fqn = attributes.class ? `${attributes.class}::${attributes.name}` : attributes.name;
86+
const hasError = content.includes( '<error' );
87+
const hasFailure = content.includes( '<failure' );
88+
89+
if ( hasError ) {
90+
actualErrors.push( fqn );
91+
}
92+
93+
if ( hasFailure ) {
94+
actualFailures.push( fqn );
95+
}
96+
}
97+
98+
let isSuccess = true;
99+
100+
// Check if all expected errors actually errored
101+
const unexpectedNonErrors = expectedErrors.filter( test => ! actualErrors.includes( test ) );
102+
if ( unexpectedNonErrors.length > 0 ) {
103+
console.error( '\n❌ The following tests were expected to error but did not:' );
104+
unexpectedNonErrors.forEach( test => console.error( ` - ${test}` ) );
105+
isSuccess = false;
106+
}
107+
108+
// Check if all expected failures actually failed
109+
const unexpectedPasses = expectedFailures.filter( test => ! actualFailures.includes( test ) );
110+
if ( unexpectedPasses.length > 0 ) {
111+
console.error( '\n❌ The following tests were expected to fail but passed:' );
112+
unexpectedPasses.forEach( test => console.error( ` - ${test}` ) );
113+
isSuccess = false;
114+
}
115+
116+
// Check for unexpected errors
117+
const unexpectedErrors = actualErrors.filter( test => ! expectedErrors.includes( test ) );
118+
if ( unexpectedErrors.length > 0 ) {
119+
console.error( '\n❌ The following tests errored unexpectedly:' );
120+
unexpectedErrors.forEach( test => console.error( ` - ${test}` ) );
121+
isSuccess = false;
122+
}
123+
124+
// Check for unexpected failures
125+
const unexpectedFailures = actualFailures.filter( test => ! expectedFailures.includes( test ) );
126+
if ( unexpectedFailures.length > 0 ) {
127+
console.error( '\n❌ The following tests failed unexpectedly:' );
128+
unexpectedFailures.forEach( test => console.error( ` - ${test}` ) );
129+
isSuccess = false;
130+
}
131+
132+
if ( isSuccess ) {
133+
console.log( '\n✅ All tests behaved as expected!' );
134+
process.exit( 0 );
135+
} else {
136+
console.log( '\n❌ Some tests did not behave as expected!' );
137+
process.exit( 1 );
138+
}
139+
} catch ( error ) {
140+
console.error( '\n❌ Script execution error:', error.message );
141+
process.exit( 1 );
142+
}
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
name: WordPress Tests
2+
3+
on:
4+
push:
5+
branches:
6+
- main
7+
pull_request:
8+
9+
jobs:
10+
test:
11+
name: WordPress PHPUnit Tests
12+
runs-on: ubuntu-latest
13+
timeout-minutes: 20
14+
15+
steps:
16+
- name: Checkout repository
17+
uses: actions/checkout@v4
18+
19+
- name: Set up Docker Buildx
20+
uses: docker/setup-buildx-action@v3
21+
22+
- name: Set UID and GID for PHP in WordPress images
23+
run: |
24+
echo "PHP_FPM_UID=$(id -u)" >> $GITHUB_ENV
25+
echo "PHP_FPM_GID=$(id -g)" >> $GITHUB_ENV
26+
27+
- name: Setup WordPress test environment
28+
run: composer run wp-setup
29+
30+
- name: Start WordPress test environment
31+
run: composer run wp-test-start
32+
33+
- name: Run WordPress PHPUnit tests
34+
run: node .github/workflows/wp-tests-phpunit-run.js
35+
36+
- name: Stop Docker containers
37+
if: always()
38+
run: composer run wp-test-clean

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,4 @@ composer.lock
55
._.DS_Store
66
.DS_Store
77
._*
8+
/wordpress

activate.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ function ( $result ) {
7575
* When the plugin gets merged in wp-core, this is not to be ported.
7676
*/
7777
function sqlite_plugin_copy_db_file() {
78-
// Bail early if the SQLite3 class does not exist.
79-
if ( ! class_exists( 'SQLite3' ) ) {
78+
// Bail early if the PDO SQLite extension is not loaded.
79+
if ( ! extension_loaded( 'pdo_sqlite' ) ) {
8080
return;
8181
}
8282

admin-notices.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ function sqlite_plugin_admin_notice() {
1919
return;
2020
}
2121

22-
// If SQLite is not detected, bail early.
23-
if ( ! class_exists( 'SQLite3' ) ) {
22+
// If PDO SQLite is not loaded, bail early.
23+
if ( ! extension_loaded( 'pdo_sqlite' ) ) {
2424
printf(
2525
'<div class="notice notice-error"><p>%s</p></div>',
26-
esc_html__( 'The SQLite Integration plugin is active, but the SQLite3 class is missing from your server. Please make sure that SQLite is enabled in your PHP installation.', 'sqlite-database-integration' )
26+
esc_html__( 'The SQLite Integration plugin is active, but the PDO SQLite extension is missing from your server. Please make sure that PDO SQLite is enabled in your PHP installation.', 'sqlite-database-integration' )
2727
);
2828
return;
2929
}

admin-page.php

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -47,11 +47,7 @@ function sqlite_integration_admin_screen() {
4747
?>
4848
</p>
4949
<?php else : ?>
50-
<?php if ( ! class_exists( 'SQLite3' ) ) : ?>
51-
<div class="notice notice-error">
52-
<p><?php esc_html_e( 'We detected that the SQLite3 class is missing from your server. Please make sure that SQLite is enabled in your PHP installation before proceeding.', 'sqlite-database-integration' ); ?></p>
53-
</div>
54-
<?php elseif ( ! extension_loaded( 'pdo_sqlite' ) ) : ?>
50+
<?php if ( ! extension_loaded( 'pdo_sqlite' ) ) : ?>
5551
<div class="notice notice-error">
5652
<p><?php esc_html_e( 'We detected that the PDO SQLite driver is missing from your server (the pdo_sqlite extension is not loaded). Please make sure that SQLite is enabled in your PHP installation before proceeding.', 'sqlite-database-integration' ); ?></p>
5753
</div>
@@ -130,7 +126,8 @@ function sqlite_plugin_adminbar_item( $admin_bar ) {
130126
global $wpdb;
131127

132128
if ( defined( 'SQLITE_DB_DROPIN_VERSION' ) && defined( 'DB_ENGINE' ) && 'sqlite' === DB_ENGINE ) {
133-
$title = '<span style="color:#46B450;">' . __( 'Database: SQLite', 'sqlite-database-integration' ) . '</span>';
129+
$suffix = defined( 'WP_SQLITE_AST_DRIVER' ) && WP_SQLITE_AST_DRIVER ? ' (AST)' : '';
130+
$title = '<span style="color:#46B450;">' . __( 'Database: SQLite', 'sqlite-database-integration' ) . $suffix . '</span>';
134131
} elseif ( stripos( $wpdb->db_server_info(), 'maria' ) !== false ) {
135132
$title = '<span style="color:#DC3232;">' . __( 'Database: MariaDB', 'sqlite-database-integration' ) . '</span>';
136133
} else {

composer.json

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
"issues": "https://github.com/wordpress/sqlite-database-integration/issues"
99
},
1010
"require": {
11-
"php": ">=7.0"
11+
"php": ">=7.2",
12+
"ext-pdo": "*",
13+
"ext-pdo_sqlite": "*"
1214
},
1315
"require-dev": {
1416
"ext-mbstring": "*",
@@ -24,7 +26,8 @@
2426
"allow-plugins": {
2527
"dealerdirect/phpcodesniffer-composer-installer": true,
2628
"phpstan/extension-installer": true
27-
}
29+
},
30+
"process-timeout": 3600
2831
},
2932
"scripts": {
3033
"check-cs": [
@@ -35,6 +38,22 @@
3538
],
3639
"test": [
3740
"phpunit"
41+
],
42+
"wp-setup": [
43+
"./wp-setup.sh"
44+
],
45+
"wp-run": [
46+
"npm --prefix wordpress run"
47+
],
48+
"wp-test-start": [
49+
"npm --prefix wordpress run env:start",
50+
"npm --prefix wordpress run env:install"
51+
],
52+
"wp-test-phpunit": [
53+
"npm --prefix wordpress run test:php --"
54+
],
55+
"wp-test-clean": [
56+
"npm --prefix wordpress run env:clean"
3857
]
3958
}
4059
}

0 commit comments

Comments
 (0)