@@ -504,6 +504,19 @@ class WP_SQLite_Driver {
504504 */
505505 private $ wrapper_transaction_type = null ;
506506
507+ /**
508+ * Whether an SQLite transaction is active in the current session.
509+ *
510+ * This is a polyfill of the "PDO::inTransaction()" method for PHP < 8.4,
511+ * where the "PDO::inTransaction()" method is not reliable with SQLite.
512+ *
513+ * @see https://bugs.php.net/bug.php?id=81227
514+ * @see https://github.com/php/php-src/pull/14268
515+ *
516+ * @var bool
517+ */
518+ private $ in_transaction = false ;
519+
507520 /**
508521 * Whether a MySQL table lock is active.
509522 *
@@ -719,6 +732,15 @@ public function rollBack(): bool {
719732 */
720733 // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid
721734 public function inTransaction (): bool {
735+ if ( PHP_VERSION_ID < 80400 ) {
736+ /*
737+ * On PHP < 8.4, the "PDO::inTransaction()" method is not reliable.
738+ *
739+ * @see https://bugs.php.net/bug.php?id=81227
740+ * @see https://github.com/php/php-src/pull/14268
741+ */
742+ return $ this ->in_transaction ;
743+ }
722744 return $ this ->connection ->get_pdo ()->inTransaction ();
723745 }
724746
@@ -1326,6 +1348,7 @@ private function begin_wrapper_transaction(): void {
13261348 $ wrapper_transaction_type = 'savepoint ' ;
13271349 } else {
13281350 // For write transactions, we must use "BEGIN IMMEDIATE".
1351+ // @see self::begin_user_transaction() method comments.
13291352 $ stmt = $ this ->connection ->prepare ( $ this ->is_readonly ? 'BEGIN ' : 'BEGIN IMMEDIATE ' );
13301353 $ wrapper_transaction_type = 'transaction ' ;
13311354 }
@@ -1334,6 +1357,7 @@ private function begin_wrapper_transaction(): void {
13341357 throw $ this ->new_driver_exception ( 'Failed to begin wrapper transaction. ' );
13351358 }
13361359 $ this ->wrapper_transaction_type = $ wrapper_transaction_type ;
1360+ $ this ->in_transaction = true ;
13371361 }
13381362
13391363 /**
@@ -1344,17 +1368,20 @@ private function commit_wrapper_transaction(): void {
13441368 return ;
13451369 }
13461370
1371+ $ in_transaction = $ this ->in_transaction ;
13471372 if ( 'savepoint ' === $ this ->wrapper_transaction_type ) {
13481373 $ savepoint_name = $ this ->get_internal_savepoint_name ( 'wrapper ' );
13491374 $ stmt = $ this ->connection ->prepare ( sprintf ( 'RELEASE SAVEPOINT %s ' , $ savepoint_name ) );
13501375 } else {
1351- $ stmt = $ this ->connection ->prepare ( 'COMMIT ' );
1376+ $ stmt = $ this ->connection ->prepare ( 'COMMIT ' );
1377+ $ in_transaction = false ;
13521378 }
13531379
13541380 if ( ! $ stmt ->execute () ) {
13551381 throw $ this ->new_driver_exception ( 'Failed to commit wrapper transaction. ' );
13561382 }
13571383 $ this ->wrapper_transaction_type = null ;
1384+ $ this ->in_transaction = $ in_transaction ;
13581385 }
13591386
13601387 /**
@@ -1377,6 +1404,7 @@ private function begin_user_transaction(): void {
13771404 * @see self::begin_wrapper_transaction()
13781405 */
13791406 $ this ->connection ->query ( 'BEGIN IMMEDIATE ' );
1407+ $ this ->in_transaction = true ;
13801408 }
13811409
13821410 /**
@@ -1388,6 +1416,7 @@ private function commit_user_transaction(): void {
13881416 return ;
13891417 }
13901418 $ this ->connection ->query ( 'COMMIT ' );
1419+ $ this ->in_transaction = false ;
13911420 }
13921421
13931422 /**
@@ -1399,6 +1428,7 @@ private function rollback_user_transaction(): void {
13991428 return ;
14001429 }
14011430 $ this ->connection ->query ( 'ROLLBACK ' );
1431+ $ this ->in_transaction = false ;
14021432 }
14031433
14041434 /**
0 commit comments