From c6d24af33901e6625481f84bec9f8e3a2a42fe08 Mon Sep 17 00:00:00 2001 From: Olivier Buisard Date: Sun, 15 Sep 2024 13:20:45 -0400 Subject: [PATCH 1/9] Create Dispatcher --- administrator/components/com_guidedtours/src/Dispatcher | 1 + 1 file changed, 1 insertion(+) create mode 100644 administrator/components/com_guidedtours/src/Dispatcher diff --git a/administrator/components/com_guidedtours/src/Dispatcher b/administrator/components/com_guidedtours/src/Dispatcher new file mode 100644 index 0000000000000..8b137891791fe --- /dev/null +++ b/administrator/components/com_guidedtours/src/Dispatcher @@ -0,0 +1 @@ + From c78454a362936c7afb4dabc00393fd19df90624a Mon Sep 17 00:00:00 2001 From: Olivier Buisard Date: Sun, 15 Sep 2024 13:21:24 -0400 Subject: [PATCH 2/9] Delete administrator/components/com_guidedtours/src/Dispatcher --- administrator/components/com_guidedtours/src/Dispatcher | 1 - 1 file changed, 1 deletion(-) delete mode 100644 administrator/components/com_guidedtours/src/Dispatcher diff --git a/administrator/components/com_guidedtours/src/Dispatcher b/administrator/components/com_guidedtours/src/Dispatcher deleted file mode 100644 index 8b137891791fe..0000000000000 --- a/administrator/components/com_guidedtours/src/Dispatcher +++ /dev/null @@ -1 +0,0 @@ - From aaf16e2e7d09c2f3c0c4cc203940765d3d66cadb Mon Sep 17 00:00:00 2001 From: Olivier Buisard Date: Sun, 15 Sep 2024 13:23:12 -0400 Subject: [PATCH 3/9] Create Dispatcher.php --- .../src/Dispatcher/Dispatcher.php | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 administrator/components/com_guidedtours/src/Dispatcher/Dispatcher.php diff --git a/administrator/components/com_guidedtours/src/Dispatcher/Dispatcher.php b/administrator/components/com_guidedtours/src/Dispatcher/Dispatcher.php new file mode 100644 index 0000000000000..458e332c6f62f --- /dev/null +++ b/administrator/components/com_guidedtours/src/Dispatcher/Dispatcher.php @@ -0,0 +1,43 @@ + + * @license GNU General Public License version 2 or later; see LICENSE.txt + */ + +namespace Joomla\Component\Guidedtours\Administrator\Dispatcher; + +use Joomla\CMS\Access\Exception\NotAllowed; +use Joomla\CMS\Dispatcher\ComponentDispatcher; + +// phpcs:disable PSR1.Files.SideEffects +\defined('_JEXEC') or die; +// phpcs:enable PSR1.Files.SideEffects + +/** + * ComponentDispatcher class for com_guidedtours + * + * @since __DEPLOY_VERSION__ + */ +class Dispatcher extends ComponentDispatcher +{ + /** + * Method to check component access permission + * + * @return void + * + * @throws \Exception|NotAllowed + */ + protected function checkAccess() + { + $command = $this->input->getCmd('task', 'display'); + if ($this->app->isClient('administrator') && $command == 'ajax.fetchUserState') { + return; + } + + parent::checkAccess(); + } +} From a71f1d446fe1b2ae1b517a222bb02408486a9c8e Mon Sep 17 00:00:00 2001 From: Olivier Buisard Date: Sun, 15 Sep 2024 13:30:39 -0400 Subject: [PATCH 4/9] Typo --- .../components/com_guidedtours/src/Dispatcher/Dispatcher.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/components/com_guidedtours/src/Dispatcher/Dispatcher.php b/administrator/components/com_guidedtours/src/Dispatcher/Dispatcher.php index 458e332c6f62f..6bcf80ec50f39 100644 --- a/administrator/components/com_guidedtours/src/Dispatcher/Dispatcher.php +++ b/administrator/components/com_guidedtours/src/Dispatcher/Dispatcher.php @@ -2,7 +2,7 @@ /** * @package Joomla.Administrator - * @subpackage com_associations + * @subpackage com_guidedtours * * @copyright (C) 2017 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt From e45c0330bafa7bf577f04a613e3ab164ae926ef0 Mon Sep 17 00:00:00 2001 From: Olivier Buisard Date: Sun, 15 Sep 2024 13:31:13 -0400 Subject: [PATCH 5/9] Copyright year change --- .../components/com_guidedtours/src/Dispatcher/Dispatcher.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/components/com_guidedtours/src/Dispatcher/Dispatcher.php b/administrator/components/com_guidedtours/src/Dispatcher/Dispatcher.php index 6bcf80ec50f39..31a2470d6aa5f 100644 --- a/administrator/components/com_guidedtours/src/Dispatcher/Dispatcher.php +++ b/administrator/components/com_guidedtours/src/Dispatcher/Dispatcher.php @@ -4,7 +4,7 @@ * @package Joomla.Administrator * @subpackage com_guidedtours * - * @copyright (C) 2017 Open Source Matters, Inc. + * @copyright (C) 2024 Open Source Matters, Inc. * @license GNU General Public License version 2 or later; see LICENSE.txt */ From 5402bea69cd1ffee04147799552030b65599942a Mon Sep 17 00:00:00 2001 From: Olivier Buisard Date: Sun, 15 Sep 2024 23:58:12 -0400 Subject: [PATCH 6/9] Added check on context and tour id --- .../src/Controller/AjaxController.php | 151 +++++++++--------- 1 file changed, 77 insertions(+), 74 deletions(-) diff --git a/administrator/components/com_guidedtours/src/Controller/AjaxController.php b/administrator/components/com_guidedtours/src/Controller/AjaxController.php index 0dbf1929e04cb..851158e5878a5 100644 --- a/administrator/components/com_guidedtours/src/Controller/AjaxController.php +++ b/administrator/components/com_guidedtours/src/Controller/AjaxController.php @@ -38,87 +38,90 @@ public function fetchUserState() $user = $this->app->getIdentity(); $tourId = $this->app->input->getInt('tid', 0); - $stepNumber = $this->app->input->getString('sid', ''); + $stepNumber = $this->app->input->getInt('sid', 0); $context = $this->app->input->getString('context', ''); - if ($user != null && $user->id > 0) { - $actionState = ''; - - switch ($context) { - case 'tour.complete': - $actionState = 'completed'; - break; - case 'tour.cancel': - $actionState = 'delayed'; - break; - case 'tour.skip': - $actionState = 'skipped'; - break; - } + if ($user == null || $user->id <= 0) { + echo new JsonResponse(['success' => false, 'tourId' => $tourId], Text::_('COM_GUIDEDTOURS_USERSTATE_CONNECTEDONLY'), true); + $this->app->close(); + } + + if (!in_array($context, ['tour.complete', 'tour.cancel', 'tour.skip'])) { + echo new JsonResponse(['success' => false, 'tourId' => $tourId], Text::_('COM_GUIDEDTOURS_USERSTATE_WRONGCONTEXT'), true); + $this->app->close(); + } - PluginHelper::importPlugin('guidedtours'); - - // event onBeforeTourSaveUserState before save user tour state - $beforeEvent = AbstractEvent::create( - 'onBeforeTourSaveUserState', - [ - 'subject' => new \stdClass(), - 'tourId' => $tourId, - 'actionState' => $actionState, - 'stepNumber' => $stepNumber, - ] - ); - - $this->app->getDispatcher()->dispatch('onBeforeTourSaveUserState', $beforeEvent); - - // Save the tour state only when the tour auto-starts. - $tourModel = $this->getModel('Tour', 'Administrator'); - if ($tourModel->isAutostart($tourId)) { - $result = $tourModel->saveTourUserState($tourId, $actionState); - if ($result) { - $message = Text::sprintf('COM_GUIDEDTOURS_USERSTATE_STATESAVED', $user->id, $tourId); - } else { - $message = Text::sprintf('COM_GUIDEDTOURS_USERSTATE_STATENOTSAVED', $user->id, $tourId); - } + if ($tourId <= 0) { + echo new JsonResponse(['success' => false, 'tourId' => $tourId], Text::_('COM_GUIDEDTOURS_USERSTATE_BADTOURID'), true); + $this->app->close(); + } + + $actionState = ''; + + switch ($context) { + case 'tour.complete': + $actionState = 'completed'; + break; + case 'tour.cancel': + $actionState = 'delayed'; + break; + case 'tour.skip': + $actionState = 'skipped'; + break; + } + + PluginHelper::importPlugin('guidedtours'); + + // event onBeforeTourSaveUserState before save user tour state + $beforeEvent = AbstractEvent::create( + 'onBeforeTourSaveUserState', + [ + 'subject' => new \stdClass(), + 'tourId' => $tourId, + 'actionState' => $actionState, + 'stepNumber' => $stepNumber, + ] + ); + + $this->app->getDispatcher()->dispatch('onBeforeTourSaveUserState', $beforeEvent); + + // Save the tour state only when the tour auto-starts. + $tourModel = $this->getModel('Tour', 'Administrator'); + if ($tourModel->isAutostart($tourId)) { + $result = $tourModel->saveTourUserState($tourId, $actionState); + if ($result) { + $message = Text::sprintf('COM_GUIDEDTOURS_USERSTATE_STATESAVED', $user->id, $tourId); } else { - $result = false; $message = Text::sprintf('COM_GUIDEDTOURS_USERSTATE_STATENOTSAVED', $user->id, $tourId); } - - // event onAfterTourSaveUserState after save user tour state (may override message) - $afterEvent = AbstractEvent::create( - 'onAfterTourSaveUserState', - [ - 'subject' => new \stdClass(), - 'tourId' => $tourId, - 'actionState' => $actionState, - 'stepNumber' => $stepNumber, - 'result' => $result, - 'message' => &$message, - ] - ); - - $this->app->getDispatcher()->dispatch('onAfterTourSaveUserState', $afterEvent); - - // Construct the response data - $data = [ - 'tourId' => $tourId, - 'stepId' => $stepNumber, - 'context' => $context, - 'state' => $actionState, - ]; - echo new JsonResponse($data, $message); - $this->app->close(); } else { - // Construct the response data - $data = [ - 'success' => false, - 'tourId' => $tourId, - ]; - - $message = Text::_('COM_GUIDEDTOURS_USERSTATE_CONNECTEDONLY'); - echo new JsonResponse($data, $message, true); - $this->app->close(); + $result = false; + $message = Text::sprintf('COM_GUIDEDTOURS_USERSTATE_STATENOTSAVED', $user->id, $tourId); } + + // event onAfterTourSaveUserState after save user tour state (may override message) + $afterEvent = AbstractEvent::create( + 'onAfterTourSaveUserState', + [ + 'subject' => new \stdClass(), + 'tourId' => $tourId, + 'actionState' => $actionState, + 'stepNumber' => $stepNumber, + 'result' => $result, + 'message' => &$message, + ] + ); + + $this->app->getDispatcher()->dispatch('onAfterTourSaveUserState', $afterEvent); + + // Construct the response data + $data = [ + 'tourId' => $tourId, + 'stepId' => $stepNumber, + 'context' => $context, + 'state' => $actionState, + ]; + echo new JsonResponse($data, $message); + $this->app->close(); } } From a6cd4588432d69371499e087805afa2540d818bf Mon Sep 17 00:00:00 2001 From: Olivier Buisard Date: Mon, 16 Sep 2024 00:03:02 -0400 Subject: [PATCH 7/9] Added 2 error messages for the user state. --- administrator/language/en-GB/com_guidedtours.ini | 2 ++ 1 file changed, 2 insertions(+) diff --git a/administrator/language/en-GB/com_guidedtours.ini b/administrator/language/en-GB/com_guidedtours.ini index 627baef477610..4624056a5e5dd 100644 --- a/administrator/language/en-GB/com_guidedtours.ini +++ b/administrator/language/en-GB/com_guidedtours.ini @@ -94,7 +94,9 @@ COM_GUIDEDTOURS_TYPE_REDIRECT_URL_DESC="Enter the relative URL of the page you w COM_GUIDEDTOURS_TYPE_REDIRECT_URL_LABEL="Relative URL" COM_GUIDEDTOURS_URL_LABEL="Relative URL" COM_GUIDEDTOURS_URL_DESC="Enter the relative URL of the page from where you want to Start the tour, e.g administrator/index.php?option=com_guidedtours&view=tours for the tours' list page." +COM_GUIDEDTOURS_USERSTATE_BADTOURID="The Tour needs to have a positive id." COM_GUIDEDTOURS_USERSTATE_CONNECTEDONLY="Tour User state action is only for connected users." COM_GUIDEDTOURS_USERSTATE_STATENOTSAVED="Tour User state not saved for user %1$s tour %2$s." COM_GUIDEDTOURS_USERSTATE_STATESAVED="Tour User state saved for user %1$s tour %2$s." +COM_GUIDEDTOURS_USERSTATE_WRONGCONTEXT="The Tour User State context is incorrect." COM_GUIDEDTOURS_XML_DESCRIPTION="Component for managing Guided Tours functionality." From 9af535f71ea82e744d61863cfc1aa7194596c6f0 Mon Sep 17 00:00:00 2001 From: Olivier Buisard Date: Mon, 16 Sep 2024 00:15:27 -0400 Subject: [PATCH 8/9] Escaped in_array. --- .../com_guidedtours/src/Controller/AjaxController.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/components/com_guidedtours/src/Controller/AjaxController.php b/administrator/components/com_guidedtours/src/Controller/AjaxController.php index 851158e5878a5..2e6b4416f6318 100644 --- a/administrator/components/com_guidedtours/src/Controller/AjaxController.php +++ b/administrator/components/com_guidedtours/src/Controller/AjaxController.php @@ -46,7 +46,7 @@ public function fetchUserState() $this->app->close(); } - if (!in_array($context, ['tour.complete', 'tour.cancel', 'tour.skip'])) { + if (!\in_array($context, ['tour.complete', 'tour.cancel', 'tour.skip'])) { echo new JsonResponse(['success' => false, 'tourId' => $tourId], Text::_('COM_GUIDEDTOURS_USERSTATE_WRONGCONTEXT'), true); $this->app->close(); } From 8b919f5ee93087e2d7824f1e4d4af252c2362e85 Mon Sep 17 00:00:00 2001 From: Olivier Buisard Date: Mon, 16 Sep 2024 10:22:02 -0400 Subject: [PATCH 9/9] Consistency issue Co-authored-by: Brian Teeman --- administrator/language/en-GB/com_guidedtours.ini | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/administrator/language/en-GB/com_guidedtours.ini b/administrator/language/en-GB/com_guidedtours.ini index 4624056a5e5dd..33389dda469c9 100644 --- a/administrator/language/en-GB/com_guidedtours.ini +++ b/administrator/language/en-GB/com_guidedtours.ini @@ -98,5 +98,5 @@ COM_GUIDEDTOURS_USERSTATE_BADTOURID="The Tour needs to have a positive id." COM_GUIDEDTOURS_USERSTATE_CONNECTEDONLY="Tour User state action is only for connected users." COM_GUIDEDTOURS_USERSTATE_STATENOTSAVED="Tour User state not saved for user %1$s tour %2$s." COM_GUIDEDTOURS_USERSTATE_STATESAVED="Tour User state saved for user %1$s tour %2$s." -COM_GUIDEDTOURS_USERSTATE_WRONGCONTEXT="The Tour User State context is incorrect." +COM_GUIDEDTOURS_USERSTATE_WRONGCONTEXT="The Tour User state context is incorrect." COM_GUIDEDTOURS_XML_DESCRIPTION="Component for managing Guided Tours functionality."