From 6f3e23625772ab2d7cc96764e5b65ba2ce897b65 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Thu, 16 May 2024 23:58:24 +0200 Subject: [PATCH 1/8] [BUGFIX] HTML Response not set properly on controller --- Classes/Controller/CheckoutController.php | 31 ++++++++++++------- .../FacilityClearCacheAfterUpdate.php | 2 +- Classes/Service/FluidService.php | 16 ++++++++-- .../TCA/tx_reserve_domain_model_order.php | 3 ++ .../TCA/tx_reserve_domain_model_period.php | 3 ++ .../tx_reserve_domain_model_reservation.php | 3 ++ ext_emconf.php | 2 +- 7 files changed, 45 insertions(+), 15 deletions(-) diff --git a/Classes/Controller/CheckoutController.php b/Classes/Controller/CheckoutController.php index b6468b3e..ddc0c64f 100644 --- a/Classes/Controller/CheckoutController.php +++ b/Classes/Controller/CheckoutController.php @@ -21,6 +21,7 @@ use JWeiland\Reserve\Service\DataTablesService; use JWeiland\Reserve\Utility\CacheUtility; use JWeiland\Reserve\Utility\OrderSessionUtility; +use Psr\Http\Message\ResponseInterface; use TYPO3\CMS\Core\Type\ContextualFeedbackSeverity; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Annotation as Extbase; @@ -74,7 +75,7 @@ public function injectCancellationService(CancellationService $cancellationServi $this->cancellationService = $cancellationService; } - public function listAction(): void + public function listAction(): ResponseInterface { $facilities = $this->facilityRepository->findByUids(GeneralUtility::trimExplode(',', $this->settings['facility'])); $this->view->assign('facilities', $facilities); @@ -89,9 +90,11 @@ public function listAction(): void ] ); CacheUtility::addFacilityToCurrentPageCacheTags((int)$this->settings['facility']); + + return $this->htmlResponse(); } - public function formAction(Period $period): void + public function formAction(Period $period): ResponseInterface { if (!$period->isBookable()) { $this->redirect('list'); @@ -108,12 +111,14 @@ public function formAction(Period $period): void $order = GeneralUtility::makeInstance(Order::class); $order->setBookedPeriod($period); $this->view->assign('order', $order); + + return $this->htmlResponse(); } /** * @Extbase\Validate("JWeiland\Reserve\Domain\Validation\OrderValidator", param="order") */ - public function createAction(Order $order, int $furtherParticipants = 0): void + public function createAction(Order $order, int $furtherParticipants = 0): ResponseInterface { if (!( $order->_isNew() @@ -125,13 +130,13 @@ public function createAction(Order $order, int $furtherParticipants = 0): void '', ContextualFeedbackSeverity::ERROR ); - $this->redirect('list'); + return $this->redirect('list'); } if ($this->checkoutService->checkout($order, (int)$this->settings['orderPid'], $furtherParticipants)) { $this->checkoutService->sendConfirmationMail($order); $this->addFlashMessage(LocalizationUtility::translate('reservation.created', 'reserve')); - $this->redirect('list'); + return $this->redirect('list'); } $this->addFlashMessage( @@ -140,10 +145,10 @@ public function createAction(Order $order, int $furtherParticipants = 0): void ContextualFeedbackSeverity::ERROR ); - $this->redirect('form', null, null, ['period' => $order->getBookedPeriod()]); + return $this->redirect('form', null, null, ['period' => $order->getBookedPeriod()]); } - public function confirmAction(string $email, string $activationCode): void + public function confirmAction(string $email, string $activationCode): ResponseInterface { $order = $this->orderRepository->findByEmailAndActivationCode($email, $activationCode); if ($order instanceof Order) { @@ -153,7 +158,7 @@ public function confirmAction(string $email, string $activationCode): void '', ContextualFeedbackSeverity::INFO ); - $this->redirect('list'); + return $this->redirect('list'); } $this->checkoutService->confirm($order); $this->view->assign('order', $order); @@ -164,9 +169,11 @@ public function confirmAction(string $email, string $activationCode): void ContextualFeedbackSeverity::ERROR ); } + + return $this->htmlResponse(); } - public function cancelAction(string $email, string $activationCode, bool $confirm = false): void + public function cancelAction(string $email, string $activationCode, bool $confirm = false): ResponseInterface { $order = $this->orderRepository->findByEmailAndActivationCode($email, $activationCode); @@ -177,7 +184,7 @@ public function cancelAction(string $email, string $activationCode, bool $confir '', ContextualFeedbackSeverity::ERROR ); - $this->redirect('list'); + return $this->redirect('list'); } $redirect = true; @@ -225,8 +232,10 @@ public function cancelAction(string $email, string $activationCode, bool $confir if ($redirect) { CacheUtility::clearPageCachesForPagesWithCurrentFacility($order->getBookedPeriod()->getFacility()->getUid()); - $this->redirect('list'); + return $this->redirect('list'); } + + return $this->htmlResponse(); } private function getAdditionalDefaultConfiguration(int $orderColumnBegin): array diff --git a/Classes/DataHandler/FacilityClearCacheAfterUpdate.php b/Classes/DataHandler/FacilityClearCacheAfterUpdate.php index 255c9eaf..e35a83ea 100644 --- a/Classes/DataHandler/FacilityClearCacheAfterUpdate.php +++ b/Classes/DataHandler/FacilityClearCacheAfterUpdate.php @@ -111,7 +111,7 @@ public function processDataHandlerResultAfterAllOperations(DataHandler $dataHand protected function replaceNewWithIds(array $ids): array { foreach ($ids as &$id) { - if (is_string($id) && str_starts_with($id, 'NEW')) { + if (is_string($id) && str_starts_with($id, 'NEW') && isset($this->dataHandler->substNEWwithIDs[$id])) { $id = $this->dataHandler->substNEWwithIDs[$id]; } } diff --git a/Classes/Service/FluidService.php b/Classes/Service/FluidService.php index 891e6600..b791ab98 100644 --- a/Classes/Service/FluidService.php +++ b/Classes/Service/FluidService.php @@ -11,6 +11,7 @@ namespace JWeiland\Reserve\Service; +use Psr\Http\Message\RequestInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface; use TYPO3\CMS\Fluid\View\StandaloneView; @@ -64,8 +65,8 @@ public function replaceMarkerByRenderedTemplate( string $content, array $vars = [] ): string { - $view = self::getStandaloneView(); - static::configureStandaloneViewForMailing($view); + $view = $this->getStandaloneView(); + $this->configureStandaloneViewForMailing($view); $view->assignMultiple($vars); $view->setTemplate($template); @@ -75,5 +76,16 @@ public function replaceMarkerByRenderedTemplate( private function getStandaloneView(): StandaloneView { return GeneralUtility::makeInstance(StandaloneView::class); + $view = GeneralUtility::makeInstance(StandaloneView::class); + if (!($view->getRequest() instanceof RequestInterface)) { + $view->setRequest($this->getRequest()); + } + + return $view; + } + + private function getRequest(): RequestInterface + { + return $GLOBALS['TYPO3_REQUEST']; } } diff --git a/Configuration/TCA/tx_reserve_domain_model_order.php b/Configuration/TCA/tx_reserve_domain_model_order.php index a79446b3..860167bb 100644 --- a/Configuration/TCA/tx_reserve_domain_model_order.php +++ b/Configuration/TCA/tx_reserve_domain_model_order.php @@ -33,6 +33,9 @@ 'typeicon_classes' => [ 'default' => 'tx_reserve_domain_model_order', ], + 'security' => [ + 'ignorePageTypeRestriction' => true, + ], ], 'types' => [ 0 => [ diff --git a/Configuration/TCA/tx_reserve_domain_model_period.php b/Configuration/TCA/tx_reserve_domain_model_period.php index ae553505..37acb3dd 100644 --- a/Configuration/TCA/tx_reserve_domain_model_period.php +++ b/Configuration/TCA/tx_reserve_domain_model_period.php @@ -33,6 +33,9 @@ 'typeicon_classes' => [ 'default' => 'tx_reserve_domain_model_period', ], + 'security' => [ + 'ignorePageTypeRestriction' => true, + ], ], 'types' => [ '1' => [ diff --git a/Configuration/TCA/tx_reserve_domain_model_reservation.php b/Configuration/TCA/tx_reserve_domain_model_reservation.php index 872ecc88..be83fda0 100644 --- a/Configuration/TCA/tx_reserve_domain_model_reservation.php +++ b/Configuration/TCA/tx_reserve_domain_model_reservation.php @@ -33,6 +33,9 @@ 'typeicon_classes' => [ 'default' => 'tx_reserve_domain_model_reservation', ], + 'security' => [ + 'ignorePageTypeRestriction' => true, + ], ], 'types' => [ '1' => [ diff --git a/ext_emconf.php b/ext_emconf.php index 9aa881ca..de9c72e5 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -7,7 +7,7 @@ 'author_email' => 'projects@jweiland.net', 'author_company' => 'jweiland.net', 'state' => 'stable', - 'version' => '3.0.0', + 'version' => '3.0.1', 'constraints' => [ 'depends' => [ 'typo3' => '12.4.8-12.4.99', From f572485bc7bad7da650757da47d7aa191733298d Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 21 May 2024 11:52:56 +0200 Subject: [PATCH 2/8] [BUGFIX] StandAloneView initialization issue fixed --- Classes/Service/FluidService.php | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/Classes/Service/FluidService.php b/Classes/Service/FluidService.php index b791ab98..987c6eaf 100644 --- a/Classes/Service/FluidService.php +++ b/Classes/Service/FluidService.php @@ -11,7 +11,7 @@ namespace JWeiland\Reserve\Service; -use Psr\Http\Message\RequestInterface; +use Psr\Http\Message\ServerRequestInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface; use TYPO3\CMS\Fluid\View\StandaloneView; @@ -43,6 +43,7 @@ public function configureStandaloneViewForMailing(StandaloneView $standaloneView $standaloneView->setTemplateRootPaths( $extbaseFrameworkConfiguration['view']['templateRootPaths'] ?? ['EXT:reserve/Resources/Private/Templates/'] ); + $standaloneView->setLayoutRootPaths( $extbaseFrameworkConfiguration['view']['layoutRootPaths'] ?? ['EXT:reserve/Resources/Private/Layouts/'] ); @@ -75,16 +76,13 @@ public function replaceMarkerByRenderedTemplate( private function getStandaloneView(): StandaloneView { - return GeneralUtility::makeInstance(StandaloneView::class); $view = GeneralUtility::makeInstance(StandaloneView::class); - if (!($view->getRequest() instanceof RequestInterface)) { - $view->setRequest($this->getRequest()); - } + $view->setRequest($this->getRequest()); return $view; } - private function getRequest(): RequestInterface + public function getRequest(): ServerRequestInterface { return $GLOBALS['TYPO3_REQUEST']; } From 2eed41f0b549eb7d88734492646c7918de9f0ba0 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 21 May 2024 12:12:32 +0200 Subject: [PATCH 3/8] [BUGFIX] Replaced deprecated function `strftime` --- Classes/Utility/QrCodeUtility.php | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Classes/Utility/QrCodeUtility.php b/Classes/Utility/QrCodeUtility.php index fde185af..a0b9b6cc 100644 --- a/Classes/Utility/QrCodeUtility.php +++ b/Classes/Utility/QrCodeUtility.php @@ -43,9 +43,9 @@ public static function generateQrCode(Reservation $reservation): ResultInterface sprintf( '%s %s %s %s', $bookedPeriod->getFacility()->getShortName() ?: $bookedPeriod->getFacility()->getName(), - strftime( + self::formatTime( LocalizationUtility::translate('date_format', 'reserve'), - $bookedPeriod->getDate()->getTimestamp() + (int)$bookedPeriod->getDate()->getTimestamp() ), $begin, $bookedPeriod->getEnd() ? (' - ' . $bookedPeriod->getEnd()->format('H:i')) : '' @@ -73,4 +73,16 @@ protected static function applyQrCodeSettingsFromFacility(BuilderInterface $buil ->logoResizeToWidth($facility->getQrCodeLogoWidth()); } } + + public static function formatTime(string $format, $timestamp = null): string + { + // Ensure the format is compatible with DateTime + $format = strtr($format, [ + '%a' => 'D', '%d' => 'd', '%m' => 'm', '%Y' => 'Y', + '%H' => 'H', '%M' => 'i', '%S' => 's', '%B' => 'F' + ]); + + $dateTime = new \DateTime(); + return $dateTime->setTimestamp($timestamp)->format($format); + } } From 6866af02c71218bd8c45e37ae1f6af1c0bfa48d3 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 21 May 2024 15:13:37 +0200 Subject: [PATCH 4/8] [BUGFIX] Frontend QR Code Scanner for Reserve Management had usage of relative paths with typo3conf --- Resources/Private/Partials/Scanner.html | 2 +- Resources/Public/JavaScript/qrReader.js | 18 ++++++++++++++---- Resources/Public/JavaScript/scanner.js | 4 +++- 3 files changed, 18 insertions(+), 6 deletions(-) diff --git a/Resources/Private/Partials/Scanner.html b/Resources/Private/Partials/Scanner.html index 1877fc79..0a187e34 100644 --- a/Resources/Private/Partials/Scanner.html +++ b/Resources/Private/Partials/Scanner.html @@ -8,7 +8,7 @@ - + diff --git a/Resources/Public/JavaScript/qrReader.js b/Resources/Public/JavaScript/qrReader.js index 3d013288..a4219323 100644 --- a/Resources/Public/JavaScript/qrReader.js +++ b/Resources/Public/JavaScript/qrReader.js @@ -1,5 +1,15 @@ -self.importScripts('/typo3conf/ext/reserve/Resources/Public/JavaScript/jsQR.js'); self.addEventListener("message", message => { - const { width, height, data } = message.data; - self.postMessage(jsQR(data, width, height)); -}); \ No newline at end of file + if (message.data.basePath) { + // Import jsQR dynamically using the base path + self.importScripts(message.data.basePath + '/jsQR.js'); + + // Setup the message handler to process QR code data + self.addEventListener("message", function(message) { + const { width, height, data } = message.data; + self.postMessage(jsQR(data, width, height)); + }); + + // Once the base path is set and script is imported, remove this listener + self.removeEventListener('message', message.callee); + } +}); diff --git a/Resources/Public/JavaScript/scanner.js b/Resources/Public/JavaScript/scanner.js index 1f75109e..346e4d03 100644 --- a/Resources/Public/JavaScript/scanner.js +++ b/Resources/Public/JavaScript/scanner.js @@ -18,6 +18,7 @@ $(() => { }); let canvasElement = document.getElementById('canvas'); + let basePath = canvasElement.getAttribute('data-base-path'); let activeScan = false; let video = null; let codeInImage = null; @@ -125,7 +126,8 @@ $(() => { requestAnimationFrame(tick); }); - let qrReader = new Worker(`/typo3conf/ext/reserve/Resources/Public/JavaScript/qrReader.js`); + let qrReader = new Worker(basePath + '/qrReader.js'); + qrReader.postMessage({basePath: basePath}); let qrReaderReady = true; function tick(timestamp) { From a2cd85b8327e96bcfa21612731ce75869c7c5f9c Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 21 May 2024 15:14:39 +0200 Subject: [PATCH 5/8] [BUGFIX] JsonView returned with proper response for the controller action --- Classes/Controller/ManagementController.php | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-) diff --git a/Classes/Controller/ManagementController.php b/Classes/Controller/ManagementController.php index fd6ae6a2..8f7e100a 100644 --- a/Classes/Controller/ManagementController.php +++ b/Classes/Controller/ManagementController.php @@ -16,6 +16,7 @@ use JWeiland\Reserve\Domain\Repository\PeriodRepository; use JWeiland\Reserve\Domain\Repository\ReservationRepository; use JWeiland\Reserve\Service\DataTablesService; +use Psr\Http\Message\ResponseInterface; use TYPO3\CMS\Core\Utility\GeneralUtility; use TYPO3\CMS\Extbase\Mvc\Controller\ActionController; use TYPO3\CMS\Extbase\Mvc\View\JsonView; @@ -55,7 +56,7 @@ protected function initializeView($view): void ]); } - public function overviewAction(): void + public function overviewAction(): ResponseInterface { $this->view->assign( 'periods', @@ -63,19 +64,25 @@ public function overviewAction(): void [(int)$this->settings['facility']] ) ); + + return $this->htmlResponse(); } - public function scannerAction(Period $period): void + public function scannerAction(Period $period): ResponseInterface { $this->view->assign('period', $period); + + return $this->htmlResponse(); } - public function periodAction(Period $period): void + public function periodAction(Period $period): ResponseInterface { $this->view->assign('period', $period); + + return $this->htmlResponse(); } - public function periodsOnSameDayAction(Period $period): void + public function periodsOnSameDayAction(Period $period): ResponseInterface { $this->view->assign( 'periods', @@ -84,9 +91,11 @@ public function periodsOnSameDayAction(Period $period): void (int)$this->settings['facility'] ) ); + + return $this->htmlResponse(); } - public function scanAction(Reservation $reservation, bool $entireOrder = false): string + public function scanAction(Reservation $reservation, bool $entireOrder = false): ResponseInterface { $view = $this->getJsonView(); $view->setVariablesToRender(['status']); @@ -130,7 +139,7 @@ public function scanAction(Reservation $reservation, bool $entireOrder = false): ] ); - return $view->render(); + return $this->jsonResponse($view->render()); } protected function getJsonView(): JsonView From 4bc23d62a7a280e477b6cad954624658a106a6b2 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 21 May 2024 15:15:43 +0200 Subject: [PATCH 6/8] [TASK] Authors updated --- composer.json | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/composer.json b/composer.json index 36283837..a189a519 100644 --- a/composer.json +++ b/composer.json @@ -9,6 +9,11 @@ { "name": "Stefan Frömken", "email": "projects@jweiland.net", + "role": "Lead Developer" + }, + { + "name": "Hoja Mustaffa Abdul Latheef", + "email": "projects@jweiland.net", "role": "Developer" } ], From fcd0c566650ef74a57a3003c72f6d48afcb70fb1 Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Tue, 21 May 2024 15:18:27 +0200 Subject: [PATCH 7/8] [TASK] Documentation updates with version --- Classes/Utility/QrCodeUtility.php | 2 +- Documentation/Changelog/Index.rst | 8 ++++++++ Documentation/Settings.cfg | 2 +- ext_emconf.php | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) diff --git a/Classes/Utility/QrCodeUtility.php b/Classes/Utility/QrCodeUtility.php index a0b9b6cc..dcd6d407 100644 --- a/Classes/Utility/QrCodeUtility.php +++ b/Classes/Utility/QrCodeUtility.php @@ -79,7 +79,7 @@ public static function formatTime(string $format, $timestamp = null): string // Ensure the format is compatible with DateTime $format = strtr($format, [ '%a' => 'D', '%d' => 'd', '%m' => 'm', '%Y' => 'Y', - '%H' => 'H', '%M' => 'i', '%S' => 's', '%B' => 'F' + '%H' => 'H', '%M' => 'i', '%S' => 's', '%B' => 'F', ]); $dateTime = new \DateTime(); diff --git a/Documentation/Changelog/Index.rst b/Documentation/Changelog/Index.rst index b3c48171..89b1e023 100644 --- a/Documentation/Changelog/Index.rst +++ b/Documentation/Changelog/Index.rst @@ -7,6 +7,14 @@ Changelog ========= +Version 3.0.1 +============= + +* [BUGFIX] HTML Response not set properly on controller +* [BUGFIX] StandAloneView initialization issue fixed +* [BUGFIX] Replaced deprecated function `strftime` +* [BUGFIX] Reserve management module broken because of relative path 'typo3conf' usage in javascript + Version 3.0.0 ============= diff --git a/Documentation/Settings.cfg b/Documentation/Settings.cfg index 05aee6a0..63c10193 100644 --- a/Documentation/Settings.cfg +++ b/Documentation/Settings.cfg @@ -4,7 +4,7 @@ [general] project = Reserve -version = 3.0.0 +version = 3.0.1 release = 3.0 copyright = by jweiland.net diff --git a/ext_emconf.php b/ext_emconf.php index de9c72e5..b6ad32a5 100644 --- a/ext_emconf.php +++ b/ext_emconf.php @@ -3,7 +3,7 @@ 'title' => 'Reserve', 'description' => 'This extension allows you to reserve tickets for one or more persons using a period table and a form. Each reservation has it’s own QR Code that can be scanned at the event.', 'category' => 'plugin', - 'author' => 'Stefan Froemken', + 'author' => 'Stefan Froemken, Hoja Mustaffa Abdul Latheef', 'author_email' => 'projects@jweiland.net', 'author_company' => 'jweiland.net', 'state' => 'stable', From 13ea6771963f655aab446c4d94277ed03634beae Mon Sep 17 00:00:00 2001 From: Hoja Mustaffa Abdul Latheef Date: Fri, 31 May 2024 12:44:54 +0200 Subject: [PATCH 8/8] [BUGFIX] Invalid tablename leads to malfunctioning cancellation of order --- Classes/Service/CancellationService.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Classes/Service/CancellationService.php b/Classes/Service/CancellationService.php index 053a5628..b7bd034c 100644 --- a/Classes/Service/CancellationService.php +++ b/Classes/Service/CancellationService.php @@ -72,7 +72,7 @@ public function cancel( // Remove with DataHandler $this->dataHandler->start([], []); - $this->dataHandler->deleteRecord('tx_yourext_domain_model_order', $order->getUid()); + $this->dataHandler->deleteRecord('tx_reserve_domain_model_order', $order->getUid()); $this->dataHandler->process_datamap(); CacheUtility::clearPageCachesForPagesWithCurrentFacility($order->getBookedPeriod()->getFacility()->getUid());