@@ -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 *
@@ -728,6 +741,15 @@ public function rollBack(): bool {
728741 */
729742 // phpcs:ignore WordPress.NamingConventions.ValidFunctionName.MethodNameInvalid
730743 public function inTransaction (): bool {
744+ if ( PHP_VERSION_ID < 80400 ) {
745+ /*
746+ * On PHP < 8.4, the "PDO::inTransaction()" method is not reliable.
747+ *
748+ * @see https://bugs.php.net/bug.php?id=81227
749+ * @see https://github.com/php/php-src/pull/14268
750+ */
751+ return $ this ->in_transaction ;
752+ }
731753 return $ this ->connection ->get_pdo ()->inTransaction ();
732754 }
733755
@@ -1335,6 +1357,7 @@ private function begin_wrapper_transaction(): void {
13351357 $ wrapper_transaction_type = 'savepoint ' ;
13361358 } else {
13371359 // For write transactions, we must use "BEGIN IMMEDIATE".
1360+ // @see self::begin_user_transaction() method comments.
13381361 $ stmt = $ this ->connection ->prepare ( $ this ->is_readonly ? 'BEGIN ' : 'BEGIN IMMEDIATE ' );
13391362 $ wrapper_transaction_type = 'transaction ' ;
13401363 }
@@ -1343,6 +1366,7 @@ private function begin_wrapper_transaction(): void {
13431366 throw $ this ->new_driver_exception ( 'Failed to begin wrapper transaction. ' );
13441367 }
13451368 $ this ->wrapper_transaction_type = $ wrapper_transaction_type ;
1369+ $ this ->in_transaction = true ;
13461370 }
13471371
13481372 /**
@@ -1353,17 +1377,20 @@ private function commit_wrapper_transaction(): void {
13531377 return ;
13541378 }
13551379
1380+ $ in_transaction = $ this ->in_transaction ;
13561381 if ( 'savepoint ' === $ this ->wrapper_transaction_type ) {
13571382 $ savepoint_name = $ this ->get_internal_savepoint_name ( 'wrapper ' );
13581383 $ stmt = $ this ->connection ->prepare ( sprintf ( 'RELEASE SAVEPOINT %s ' , $ savepoint_name ) );
13591384 } else {
1360- $ stmt = $ this ->connection ->prepare ( 'COMMIT ' );
1385+ $ stmt = $ this ->connection ->prepare ( 'COMMIT ' );
1386+ $ in_transaction = false ;
13611387 }
13621388
13631389 if ( ! $ stmt ->execute () ) {
13641390 throw $ this ->new_driver_exception ( 'Failed to commit wrapper transaction. ' );
13651391 }
13661392 $ this ->wrapper_transaction_type = null ;
1393+ $ this ->in_transaction = $ in_transaction ;
13671394 }
13681395
13691396 /**
@@ -1386,6 +1413,7 @@ private function begin_user_transaction(): void {
13861413 * @see self::begin_wrapper_transaction()
13871414 */
13881415 $ this ->connection ->query ( 'BEGIN IMMEDIATE ' );
1416+ $ this ->in_transaction = true ;
13891417 }
13901418
13911419 /**
@@ -1397,6 +1425,7 @@ private function commit_user_transaction(): void {
13971425 return ;
13981426 }
13991427 $ this ->connection ->query ( 'COMMIT ' );
1428+ $ this ->in_transaction = false ;
14001429 }
14011430
14021431 /**
@@ -1408,6 +1437,7 @@ private function rollback_user_transaction(): void {
14081437 return ;
14091438 }
14101439 $ this ->connection ->query ( 'ROLLBACK ' );
1440+ $ this ->in_transaction = false ;
14111441 }
14121442
14131443 /**
0 commit comments