diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index 92ea6c4b6..efc34d490 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -7,7 +7,7 @@ jobs:
         runs-on: ubuntu-latest
         strategy:
             matrix:
-                php: ['7.2', '7.3', '7.4', '8.0', '8.1']
+                php: ['7.2', '7.3', '7.4', '8.0', '8.1', '8.2']
 
             fail-fast: false
 
diff --git a/src/Application/UI/Presenter.php b/src/Application/UI/Presenter.php
index 676e5f31e..5fbeb6ac0 100644
--- a/src/Application/UI/Presenter.php
+++ b/src/Application/UI/Presenter.php
@@ -15,6 +15,7 @@
 use Nette\Application\Responses;
 use Nette\Http;
 use Nette\Utils\Arrays;
+use Throwable;
 
 
 /**
@@ -52,6 +53,9 @@ abstract class Presenter extends Control implements Application\IPresenter
 	/** @var array<callable(self): void>  Occurs when the presenter is starting */
 	public $onStartup = [];
 
+	/** @var array<callable(self, Throwable|null): void>  Occurs after presenter processed a signal */
+	public $onAfterSignal = [];
+
 	/** @var array<callable(self): void>  Occurs when the presenter is rendering after beforeRender */
 	public $onRender = [];
 
@@ -230,7 +234,17 @@ public function run(Application\Request $request): Application\Response
 
 			// SIGNAL HANDLING
 			// calls $this->handle<Signal>()
-			$this->processSignal();
+			$signalException = null;
+			try {
+				$this->processSignal();
+			} catch (Throwable $signalException) {
+				// Handled bellow
+			} finally {
+				Arrays::invoke($this->onAfterSignal, $this, $signalException);
+				if ($signalException !== null) {
+					throw $signalException;
+				}
+			}
 
 			// RENDERING VIEW
 			$this->beforeRender();
@@ -780,7 +794,8 @@ protected function createRequest(
 		string $destination,
 		array $args,
 		string $mode
-	): ?string {
+	): ?string
+	{
 		// note: createRequest supposes that saveState(), run() & tryCall() behaviour is final
 
 		$this->lastCreatedRequest = $this->lastCreatedRequestFlag = null;
@@ -1034,7 +1049,8 @@ public static function argsToParams(
 		array &$args,
 		array $supplemental = [],
 		?array &$missing = null
-	): void {
+	): void
+	{
 		$i = 0;
 		$rm = new \ReflectionMethod($class, $method);
 		foreach ($rm->getParameters() as $param) {
diff --git a/src/Bridges/ApplicationDI/ApplicationExtension.php b/src/Bridges/ApplicationDI/ApplicationExtension.php
index 285e44f45..9104d5c55 100644
--- a/src/Bridges/ApplicationDI/ApplicationExtension.php
+++ b/src/Bridges/ApplicationDI/ApplicationExtension.php
@@ -211,7 +211,8 @@ private function findPresenters(): array
 	public static function initializeBlueScreenPanel(
 		Tracy\BlueScreen $blueScreen,
 		Nette\Application\Application $application
-	): void {
+	): void
+	{
 		$blueScreen->addPanel(function (?\Throwable $e) use ($application, $blueScreen): ?array {
 			$dumper = $blueScreen->getDumper();
 			return $e ? null : [
diff --git a/src/Bridges/ApplicationLatte/DefaultTemplate.php b/src/Bridges/ApplicationLatte/DefaultTemplate.php
index f064605db..21eb5792d 100644
--- a/src/Bridges/ApplicationLatte/DefaultTemplate.php
+++ b/src/Bridges/ApplicationLatte/DefaultTemplate.php
@@ -18,6 +18,7 @@
  * @method bool isLinkCurrent(string $destination = null, ...$args)
  * @method bool isModuleCurrent(string $module)
  */
+#[\AllowDynamicProperties]
 final class DefaultTemplate extends Template
 {
 	/** @var Nette\Application\UI\Presenter */
diff --git a/src/Bridges/ApplicationLatte/TemplateFactory.php b/src/Bridges/ApplicationLatte/TemplateFactory.php
index 7684bb7aa..a86705048 100644
--- a/src/Bridges/ApplicationLatte/TemplateFactory.php
+++ b/src/Bridges/ApplicationLatte/TemplateFactory.php
@@ -132,7 +132,8 @@ private function setupLatte2(
 		?UI\Control $control,
 		?UI\Presenter $presenter,
 		Template $template
-	): void {
+	): void
+	{
 		if ($latte->onCompile instanceof \Traversable) {
 			$latte->onCompile = iterator_to_array($latte->onCompile);
 		}
diff --git a/src/Bridges/ApplicationTracy/RoutingPanel.php b/src/Bridges/ApplicationTracy/RoutingPanel.php
index f53b5595d..0455e12c6 100644
--- a/src/Bridges/ApplicationTracy/RoutingPanel.php
+++ b/src/Bridges/ApplicationTracy/RoutingPanel.php
@@ -92,7 +92,8 @@ private function analyse(
 		?string $path = null,
 		int $level = -1,
 		int $flag = 0
-	): void {
+	): void
+	{
 		if ($router instanceof Routing\RouteList) {
 			if ($httpRequest) {
 				try {
diff --git a/tests/Bridges.Latte2/UIMacros.link.2.phpt b/tests/Bridges.Latte2/UIMacros.link.2.phpt
index 0d5723ddb..efa955b66 100644
--- a/tests/Bridges.Latte2/UIMacros.link.2.phpt
+++ b/tests/Bridges.Latte2/UIMacros.link.2.phpt
@@ -91,7 +91,7 @@ link:['login']
 <a href="link:['default!#hash',10,20]"></a>
 EOD
 
-, strtr($latte->renderToString(<<<'EOD'
+	, strtr($latte->renderToString(<<<'EOD'
 {plink Homepage:}
 
 {plink  Homepage: }
@@ -122,4 +122,4 @@ EOD
 
 <a n:href="default!#hash 10, 20"></a>
 EOD
-, $params), ['&#039;' => "'", '&apos;' => "'", '&#123;' => '{']));
+		, $params), ['&#039;' => "'", '&apos;' => "'", '&#123;' => '{']));
diff --git a/tests/Bridges.Latte3/{control}.phpt b/tests/Bridges.Latte3/{control}.phpt
index 224a5a187..0b22e87d8 100644
--- a/tests/Bridges.Latte3/{control}.phpt
+++ b/tests/Bridges.Latte3/{control}.phpt
@@ -51,7 +51,7 @@ Assert::match(
 				$ʟ_tmp->renderType() /* line 1 */;
 		%A%
 		XX
-,
+	,
 	$latte->compile('{control form:type}'),
 );
 
diff --git a/tests/Bridges.Latte3/{link}.2.phpt b/tests/Bridges.Latte3/{link}.2.phpt
index f745b3211..3b5a63cbc 100644
--- a/tests/Bridges.Latte3/{link}.2.phpt
+++ b/tests/Bridges.Latte3/{link}.2.phpt
@@ -90,7 +90,7 @@ Assert::match(<<<'EOD'
 	<a href="link:['default!#hash',10,20]"></a>
 	EOD
 
-, strtr($latte->renderToString(<<<'EOD'
+	, strtr($latte->renderToString(<<<'EOD'
 	{plink Homepage:}
 
 	{plink  Homepage: }
@@ -121,4 +121,4 @@ Assert::match(<<<'EOD'
 
 	<a n:href="default!#hash 10, 20"></a>
 	EOD
-, $params), ['&#039;' => "'", '&apos;' => "'", '&#123;' => '{']));
+		, $params), ['&#039;' => "'", '&apos;' => "'", '&#123;' => '{']));
diff --git a/tests/UI/Component.isLinkCurrent().asserts.php b/tests/UI/Component.isLinkCurrent().asserts.php
index 4875726b2..e99957ba9 100644
--- a/tests/UI/Component.isLinkCurrent().asserts.php
+++ b/tests/UI/Component.isLinkCurrent().asserts.php
@@ -24,7 +24,8 @@ function callIsComponentLinkCurrent(
 	Application\Request $request,
 	$destination,
 	array $args
-): bool {
+): bool
+{
 	$url = new Http\UrlScript('http://localhost/index.php', '/index.php');
 	$presenterFactory = Mockery::mock(Nette\Application\IPresenterFactory::class);
 	$presenterFactory->shouldReceive('getPresenterClass')->andReturn('TestPresenter');
diff --git a/tests/UI/Presenter.storeRequest().phpt b/tests/UI/Presenter.storeRequest().phpt
index d32861228..c61482497 100644
--- a/tests/UI/Presenter.storeRequest().phpt
+++ b/tests/UI/Presenter.storeRequest().phpt
@@ -36,7 +36,8 @@ class MockSession extends Http\Session
 	public function getSection(
 		string $section,
 		string $class = Nette\Http\SessionSection::class
-	): Nette\Http\SessionSection {
+	): Nette\Http\SessionSection
+	{
 		return $this->testSection;
 	}
 }