From d9c936f64be7adf84156fb2b4e79999308c7bf59 Mon Sep 17 00:00:00 2001 From: Senne Van Den Bogaert Date: Mon, 6 Jul 2026 10:17:16 +0200 Subject: [PATCH 01/12] Fix TimedPublishSubscriber for doctrine/dbal 4.x - Replace removed Connection::executeUpdate() with executeStatement() - Use plain (non colon-prefixed) named parameters as required by DBAL 4 - Pass an explicit Types::DATETIME_MUTABLE type for the bound Carbon/DateTime value - Log caught exceptions at debug level instead of swallowing them silently Fixes #3748 --- src/Event/Subscriber/TimedPublishSubscriber.php | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/Event/Subscriber/TimedPublishSubscriber.php b/src/Event/Subscriber/TimedPublishSubscriber.php index 922382d57..cc46c3696 100644 --- a/src/Event/Subscriber/TimedPublishSubscriber.php +++ b/src/Event/Subscriber/TimedPublishSubscriber.php @@ -7,7 +7,9 @@ use Bolt\Doctrine\TablePrefixTrait; use Bolt\Entity\Content; use Carbon\Carbon; +use Doctrine\DBAL\Types\Types; use Doctrine\Persistence\ManagerRegistry; +use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\KernelEvents; use Throwable; @@ -20,13 +22,15 @@ class TimedPublishSubscriber implements EventSubscriberInterface private object $defaultConnection; private string $tablePrefix; + private LoggerInterface $logger; - public function __construct($tablePrefix, ManagerRegistry $managerRegistry) + public function __construct($tablePrefix, ManagerRegistry $managerRegistry, LoggerInterface $logger) { $this->defaultConnection = $managerRegistry->getConnection('default'); $this->tablePrefix = $this ->setTablePrefixes($tablePrefix, $managerRegistry) ->getTablePrefix($managerRegistry->getManager('default')); + $this->logger = $logger; } /** @@ -49,10 +53,11 @@ public function onKernelRequest(): void ); try { - $conn->executeUpdate($queryPublish, [':now' => $now]); - $conn->executeUpdate($queryDepublish, [':now' => $now]); - } catch (Throwable) { + $conn->executeStatement($queryPublish, ['now' => $now], ['now' => Types::DATETIME_MUTABLE]); + $conn->executeStatement($queryDepublish, ['now' => $now], ['now' => Types::DATETIME_MUTABLE]); + } catch (Throwable $exception) { // Fail silently, output user-friendly exception elsewhere. + $this->logger->debug('Failed to publish/depublish timed content', ['exception' => $exception]); } } From 7d7b4551d69a569cfeac4278c072312c5eaed5bd Mon Sep 17 00:00:00 2001 From: Senne Van Den Bogaert Date: Mon, 6 Jul 2026 10:29:39 +0200 Subject: [PATCH 02/12] Fix PHPStan: type connection as Doctrine\DBAL\Connection Typing $defaultConnection as the generic 'object' (as returned by ManagerRegistry::getConnection()) hid the executeStatement() method from PHPStan. Narrow it to Doctrine\DBAL\Connection instead, and drop the now-obsolete baseline entry for the old executeUpdate() call. --- phpstan-baseline.php | 6 ------ src/Event/Subscriber/TimedPublishSubscriber.php | 7 +++++-- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index 1f8323a41..e1e807a2a 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -2665,12 +2665,6 @@ 'count' => 1, 'path' => __DIR__ . '/src/Event/Subscriber/AuthSubscriber.php', ]; -$ignoreErrors[] = [ - 'message' => '#^Call to an undefined method object\\:\\:executeUpdate\\(\\)\\.$#', - 'identifier' => 'method.notFound', - 'count' => 2, - 'path' => __DIR__ . '/src/Event/Subscriber/TimedPublishSubscriber.php', -]; $ignoreErrors[] = [ 'message' => '#^Method Bolt\\\\Event\\\\Subscriber\\\\TimedPublishSubscriber\\:\\:__construct\\(\\) has parameter \\$tablePrefix with no type specified\\.$#', 'identifier' => 'missingType.parameter', diff --git a/src/Event/Subscriber/TimedPublishSubscriber.php b/src/Event/Subscriber/TimedPublishSubscriber.php index cc46c3696..ac002d424 100644 --- a/src/Event/Subscriber/TimedPublishSubscriber.php +++ b/src/Event/Subscriber/TimedPublishSubscriber.php @@ -7,6 +7,7 @@ use Bolt\Doctrine\TablePrefixTrait; use Bolt\Entity\Content; use Carbon\Carbon; +use Doctrine\DBAL\Connection; use Doctrine\DBAL\Types\Types; use Doctrine\Persistence\ManagerRegistry; use Psr\Log\LoggerInterface; @@ -20,13 +21,15 @@ class TimedPublishSubscriber implements EventSubscriberInterface public const PRIORITY = 30; - private object $defaultConnection; + private Connection $defaultConnection; private string $tablePrefix; private LoggerInterface $logger; public function __construct($tablePrefix, ManagerRegistry $managerRegistry, LoggerInterface $logger) { - $this->defaultConnection = $managerRegistry->getConnection('default'); + /** @var Connection $connection */ + $connection = $managerRegistry->getConnection('default'); + $this->defaultConnection = $connection; $this->tablePrefix = $this ->setTablePrefixes($tablePrefix, $managerRegistry) ->getTablePrefix($managerRegistry->getManager('default')); From 756cad209aa4c9efaa0a5489d562ea50b382b4d9 Mon Sep 17 00:00:00 2001 From: Senne Van Den Bogaert Date: Mon, 6 Jul 2026 10:33:24 +0200 Subject: [PATCH 03/12] Apply Rector: promote $logger to constructor property Matches CI's ClassPropertyAssignToConstructorPromotionRector suggestion. --- phpstan-baseline.php | 4 +++- src/Event/Subscriber/TimedPublishSubscriber.php | 4 +--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index e1e807a2a..1c6e06974 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -1,4 +1,6 @@ -getConnection('default'); @@ -33,7 +32,6 @@ public function __construct($tablePrefix, ManagerRegistry $managerRegistry, Logg $this->tablePrefix = $this ->setTablePrefixes($tablePrefix, $managerRegistry) ->getTablePrefix($managerRegistry->getManager('default')); - $this->logger = $logger; } /** From dfb5b4638e304b0f956f54d96cf6ac2f8f5fc9a2 Mon Sep 17 00:00:00 2001 From: Senne Van Den Bogaert Date: Mon, 6 Jul 2026 10:35:07 +0200 Subject: [PATCH 04/12] Update stale comment per PR review Clarify that the failure is silent for the user, but logged at debug level for diagnostics. --- src/Event/Subscriber/TimedPublishSubscriber.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Event/Subscriber/TimedPublishSubscriber.php b/src/Event/Subscriber/TimedPublishSubscriber.php index fc1208061..ced3ac4d4 100644 --- a/src/Event/Subscriber/TimedPublishSubscriber.php +++ b/src/Event/Subscriber/TimedPublishSubscriber.php @@ -57,7 +57,7 @@ public function onKernelRequest(): void $conn->executeStatement($queryPublish, ['now' => $now], ['now' => Types::DATETIME_MUTABLE]); $conn->executeStatement($queryDepublish, ['now' => $now], ['now' => Types::DATETIME_MUTABLE]); } catch (Throwable $exception) { - // Fail silently, output user-friendly exception elsewhere. + // Fail silently for the user, but log at debug level for diagnostics. $this->logger->debug('Failed to publish/depublish timed content', ['exception' => $exception]); } } From 1016793264fefa1f270bc63a91bab1837d7289fd Mon Sep 17 00:00:00 2001 From: Senne Van Den Bogaert Date: Mon, 6 Jul 2026 10:36:55 +0200 Subject: [PATCH 05/12] Apply ECS coding standard: split constructor params onto multiple lines --- src/Event/Subscriber/TimedPublishSubscriber.php | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Event/Subscriber/TimedPublishSubscriber.php b/src/Event/Subscriber/TimedPublishSubscriber.php index ced3ac4d4..84cd3738c 100644 --- a/src/Event/Subscriber/TimedPublishSubscriber.php +++ b/src/Event/Subscriber/TimedPublishSubscriber.php @@ -24,8 +24,11 @@ class TimedPublishSubscriber implements EventSubscriberInterface private Connection $defaultConnection; private string $tablePrefix; - public function __construct($tablePrefix, ManagerRegistry $managerRegistry, private LoggerInterface $logger) - { + public function __construct( + $tablePrefix, + ManagerRegistry $managerRegistry, + private LoggerInterface $logger + ) { /** @var Connection $connection */ $connection = $managerRegistry->getConnection('default'); $this->defaultConnection = $connection; From 80620e1b5ed9acc2fc5f409825f3da80a308acc5 Mon Sep 17 00:00:00 2001 From: Bob van de Vijver Date: Mon, 20 Jul 2026 16:03:45 +0200 Subject: [PATCH 06/12] Update src/Event/Subscriber/TimedPublishSubscriber.php --- src/Event/Subscriber/TimedPublishSubscriber.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Event/Subscriber/TimedPublishSubscriber.php b/src/Event/Subscriber/TimedPublishSubscriber.php index 84cd3738c..902bd225c 100644 --- a/src/Event/Subscriber/TimedPublishSubscriber.php +++ b/src/Event/Subscriber/TimedPublishSubscriber.php @@ -29,9 +29,7 @@ public function __construct( ManagerRegistry $managerRegistry, private LoggerInterface $logger ) { - /** @var Connection $connection */ - $connection = $managerRegistry->getConnection('default'); - $this->defaultConnection = $connection; + $this->defaultConnection = $managerRegistry->getConnection('default'); $this->tablePrefix = $this ->setTablePrefixes($tablePrefix, $managerRegistry) ->getTablePrefix($managerRegistry->getManager('default')); From fd4ac41f0629fd5951b8994458756048450425ad Mon Sep 17 00:00:00 2001 From: Bob van de Vijver Date: Mon, 20 Jul 2026 16:04:28 +0200 Subject: [PATCH 07/12] Update phpstan-baseline.php --- phpstan-baseline.php | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index 1c6e06974..52e703a2b 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -1,6 +1,4 @@ - Date: Mon, 20 Jul 2026 16:05:12 +0200 Subject: [PATCH 08/12] Update phpstan-baseline.php --- phpstan-baseline.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/phpstan-baseline.php b/phpstan-baseline.php index 52e703a2b..e1e807a2a 100644 --- a/phpstan-baseline.php +++ b/phpstan-baseline.php @@ -1,4 +1,4 @@ - Date: Mon, 20 Jul 2026 16:07:36 +0200 Subject: [PATCH 09/12] Apply suggestions from code review Co-authored-by: Bob van de Vijver --- src/Event/Subscriber/TimedPublishSubscriber.php | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Event/Subscriber/TimedPublishSubscriber.php b/src/Event/Subscriber/TimedPublishSubscriber.php index 902bd225c..50461a4aa 100644 --- a/src/Event/Subscriber/TimedPublishSubscriber.php +++ b/src/Event/Subscriber/TimedPublishSubscriber.php @@ -6,6 +6,7 @@ use Bolt\Doctrine\TablePrefixTrait; use Bolt\Entity\Content; +use Bolt\Log\LoggerTrait; use Carbon\Carbon; use Doctrine\DBAL\Connection; use Doctrine\DBAL\Types\Types; @@ -24,11 +25,8 @@ class TimedPublishSubscriber implements EventSubscriberInterface private Connection $defaultConnection; private string $tablePrefix; - public function __construct( - $tablePrefix, - ManagerRegistry $managerRegistry, - private LoggerInterface $logger - ) { + public function __construct($tablePrefix, ManagerRegistry $managerRegistry) + { $this->defaultConnection = $managerRegistry->getConnection('default'); $this->tablePrefix = $this ->setTablePrefixes($tablePrefix, $managerRegistry) From 9977786e746668739a70058ebc3aa53788d6fee1 Mon Sep 17 00:00:00 2001 From: Bob van de Vijver Date: Mon, 20 Jul 2026 16:08:04 +0200 Subject: [PATCH 10/12] Update src/Event/Subscriber/TimedPublishSubscriber.php --- src/Event/Subscriber/TimedPublishSubscriber.php | 1 - 1 file changed, 1 deletion(-) diff --git a/src/Event/Subscriber/TimedPublishSubscriber.php b/src/Event/Subscriber/TimedPublishSubscriber.php index 50461a4aa..70e434d36 100644 --- a/src/Event/Subscriber/TimedPublishSubscriber.php +++ b/src/Event/Subscriber/TimedPublishSubscriber.php @@ -11,7 +11,6 @@ use Doctrine\DBAL\Connection; use Doctrine\DBAL\Types\Types; use Doctrine\Persistence\ManagerRegistry; -use Psr\Log\LoggerInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\HttpKernel\KernelEvents; use Throwable; From 2747f2f35f89056801c510fbd141a17ce3afa681 Mon Sep 17 00:00:00 2001 From: Bob van de Vijver Date: Mon, 20 Jul 2026 16:12:37 +0200 Subject: [PATCH 11/12] loggertrait --- src/Event/Subscriber/TimedPublishSubscriber.php | 1 + 1 file changed, 1 insertion(+) diff --git a/src/Event/Subscriber/TimedPublishSubscriber.php b/src/Event/Subscriber/TimedPublishSubscriber.php index 70e434d36..7cbe5ac3c 100644 --- a/src/Event/Subscriber/TimedPublishSubscriber.php +++ b/src/Event/Subscriber/TimedPublishSubscriber.php @@ -17,6 +17,7 @@ class TimedPublishSubscriber implements EventSubscriberInterface { + use LoggerTrait; use TablePrefixTrait; public const PRIORITY = 30; From a85b839d9ba8c5b5d1c538a3a62f6762407c5e26 Mon Sep 17 00:00:00 2001 From: Bob van de Vijver Date: Mon, 20 Jul 2026 16:13:07 +0200 Subject: [PATCH 12/12] Revert "Update src/Event/Subscriber/TimedPublishSubscriber.php" This reverts commit c4df3833516d5983872d27f4883b842ab53b2fcc. --- src/Event/Subscriber/TimedPublishSubscriber.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/Event/Subscriber/TimedPublishSubscriber.php b/src/Event/Subscriber/TimedPublishSubscriber.php index 7cbe5ac3c..224e2ccc0 100644 --- a/src/Event/Subscriber/TimedPublishSubscriber.php +++ b/src/Event/Subscriber/TimedPublishSubscriber.php @@ -27,7 +27,9 @@ class TimedPublishSubscriber implements EventSubscriberInterface public function __construct($tablePrefix, ManagerRegistry $managerRegistry) { - $this->defaultConnection = $managerRegistry->getConnection('default'); + /** @var Connection $connection */ + $connection = $managerRegistry->getConnection('default'); + $this->defaultConnection = $connection; $this->tablePrefix = $this ->setTablePrefixes($tablePrefix, $managerRegistry) ->getTablePrefix($managerRegistry->getManager('default'));