From e085fcef863686e6b65b82fc044d143610afc420 Mon Sep 17 00:00:00 2001 From: Mathieu Ferment Date: Mon, 20 May 2019 17:37:27 +0200 Subject: [PATCH] Revert "Remove everything for fake" This reverts commit e58816d410356e264e70d0758f1bfadee7ce1fc7. --- README.md | 3 + composer.json | 11 + config/routes.yml | 7 + config/services.yml | 33 ++ ps_democqrshooksusage.php | 337 ++++++++++++++++++ .../Admin/CustomerReviewController.php | 87 +++++ .../ToggleIsAllowedToReviewCommand.php | 59 +++ .../UpdateIsAllowedToReviewCommand.php | 74 ++++ .../AbstractReviewerHandler.php | 74 ++++ .../ToggleIsAllowedToReviewHandler.php | 86 +++++ .../UpdateIsAllowedToReviewHandler.php | 77 ++++ .../CannotCreateReviewerException.php | 32 ++ ...otToggleAllowedToReviewStatusException.php | 31 ++ .../Reviewer/Exception/ReviewerException.php | 33 ++ .../Query/GetReviewerSettingsForForm.php | 56 +++ .../GetReviewerSettingsForFormHandler.php | 63 ++++ .../QueryResult/ReviewerSettingsForForm.php | 54 +++ src/Entity/Reviewer.php | 51 +++ src/Repository/ReviewerRepository.php | 97 +++++ 19 files changed, 1265 insertions(+) create mode 100755 README.md create mode 100755 composer.json create mode 100755 config/routes.yml create mode 100755 config/services.yml create mode 100755 ps_democqrshooksusage.php create mode 100755 src/Controller/Admin/CustomerReviewController.php create mode 100755 src/Domain/Reviewer/Command/ToggleIsAllowedToReviewCommand.php create mode 100644 src/Domain/Reviewer/Command/UpdateIsAllowedToReviewCommand.php create mode 100644 src/Domain/Reviewer/CommandHandler/AbstractReviewerHandler.php create mode 100755 src/Domain/Reviewer/CommandHandler/ToggleIsAllowedToReviewHandler.php create mode 100644 src/Domain/Reviewer/CommandHandler/UpdateIsAllowedToReviewHandler.php create mode 100644 src/Domain/Reviewer/Exception/CannotCreateReviewerException.php create mode 100644 src/Domain/Reviewer/Exception/CannotToggleAllowedToReviewStatusException.php create mode 100644 src/Domain/Reviewer/Exception/ReviewerException.php create mode 100644 src/Domain/Reviewer/Query/GetReviewerSettingsForForm.php create mode 100644 src/Domain/Reviewer/QueryHandler/GetReviewerSettingsForFormHandler.php create mode 100644 src/Domain/Reviewer/QueryResult/ReviewerSettingsForForm.php create mode 100755 src/Entity/Reviewer.php create mode 100644 src/Repository/ReviewerRepository.php diff --git a/README.md b/README.md new file mode 100755 index 0000000..c0d0665 --- /dev/null +++ b/README.md @@ -0,0 +1,3 @@ +# demo CQRS and hooks usage module + +# WORK IN PROGRESS diff --git a/composer.json b/composer.json new file mode 100755 index 0000000..8c8434c --- /dev/null +++ b/composer.json @@ -0,0 +1,11 @@ +{ + "name": "prestashop/democqrshooksusage", + "description": "Help developers to understand how to create module using new hooks and apply best practices when using CQRS", + "autoload": { + "psr-4": { + "DemoCQRSHooksUsage\\": "src/" + } + }, + "license": "MIT", + "type": "prestashop-module" +} diff --git a/config/routes.yml b/config/routes.yml new file mode 100755 index 0000000..dbe1232 --- /dev/null +++ b/config/routes.yml @@ -0,0 +1,7 @@ +ps_democqrshooksusage_toggle_is_allowed_for_review: + path: demo-cqrs-hook-usage/{customerId}/toggle-is-allowed-for-review + methods: [POST] + defaults: + _controller: 'DemoCQRSHooksUsage\Controller\Admin\CustomerReviewController::toggleIsAllowedForReviewAction' + requirements: + customerId: \d+ diff --git a/config/services.yml b/config/services.yml new file mode 100755 index 0000000..5df4c79 --- /dev/null +++ b/config/services.yml @@ -0,0 +1,33 @@ +services: + _defaults: + public: true + + democqrshooksusage.domain.reviewer.command_handler.toggle_is_allowed_to_review_handler: + class: 'DemoCQRSHooksUsage\Domain\Reviewer\CommandHandler\ToggleIsAllowedToReviewHandler' + arguments: + - '@democqrshooksusage.repository.reviewer' + tags: + - name: tactician.handler + command: 'DemoCQRSHooksUsage\Domain\Reviewer\Command\ToggleIsAllowedToReviewCommand' + + democqrshooksusage.domain.reviewer.query_handler.get_reviewer_settings_for_form_handler: + class: 'DemoCQRSHooksUsage\Domain\Reviewer\QueryHandler\GetReviewerSettingsForFormHandler' + arguments: + - '@democqrshooksusage.repository.reviewer' + tags: + - name: tactician.handler + command: 'DemoCQRSHooksUsage\Domain\Reviewer\Query\GetReviewerSettingsForForm' + + democqrshooksusage.domain.reviewer.command_handler.update_is_allowed_to_review_handler: + class: 'DemoCQRSHooksUsage\Domain\Reviewer\CommandHandler\UpdateIsAllowedToReviewHandler' + arguments: + - '@democqrshooksusage.repository.reviewer' + tags: + - name: tactician.handler + command: 'DemoCQRSHooksUsage\Domain\Reviewer\Command\UpdateIsAllowedToReviewCommand' + + democqrshooksusage.repository.reviewer: + class: 'DemoCQRSHooksUsage\Repository\ReviewerRepository' + arguments: + - '@doctrine.dbal.default_connection' + - '%database_prefix%' diff --git a/ps_democqrshooksusage.php b/ps_democqrshooksusage.php new file mode 100755 index 0000000..4f7a4ec --- /dev/null +++ b/ps_democqrshooksusage.php @@ -0,0 +1,337 @@ + + * @copyright 2007-2019 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +use DemoCQRSHooksUsage\Domain\Reviewer\Command\UpdateIsAllowedToReviewCommand; +use DemoCQRSHooksUsage\Domain\Reviewer\Exception\CannotCreateReviewerException; +use DemoCQRSHooksUsage\Domain\Reviewer\Exception\CannotToggleAllowedToReviewStatusException; +use DemoCQRSHooksUsage\Domain\Reviewer\Exception\ReviewerException; +use DemoCQRSHooksUsage\Domain\Reviewer\Query\GetReviewerSettingsForForm; +use DemoCQRSHooksUsage\Domain\Reviewer\QueryResult\ReviewerSettingsForForm; +use Doctrine\DBAL\Query\QueryBuilder; +use PrestaShop\PrestaShop\Core\CommandBus\CommandBusInterface; +use PrestaShop\PrestaShop\Core\Domain\Customer\Exception\CustomerException; +use PrestaShop\PrestaShop\Core\Grid\Column\Type\Common\ToggleColumn; +use PrestaShop\PrestaShop\Core\Grid\Definition\GridDefinitionInterface; +use PrestaShop\PrestaShop\Core\Grid\Filter\Filter; +use PrestaShop\PrestaShop\Core\Search\Filters\CustomerFilters; +use PrestaShopBundle\Form\Admin\Type\SwitchType; +use PrestaShopBundle\Form\Admin\Type\YesAndNoChoiceType; +use Symfony\Component\Form\FormBuilderInterface; +use Symfony\Component\HttpFoundation\Request; +use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface; + +//todo: demonstrate how include custom js extensions for existing grids maybe?. +//todo: not a single translation works for this module +/** + * Class Ps_DemoCQRSHooksUsage demonstrates the usage of CQRS and hooks. + */ +class Ps_DemoCQRSHooksUsage extends Module +{ + public function __construct() + { + $this->name = 'ps_democqrshooksusage'; + $this->version = '1.0.0'; + $this->author = 'Tomas Ilginis'; + $this->need_instance = 0; + + parent::__construct(); + + $this->displayName = $this->getTranslator()->trans( + 'Demo for CQRS and hooks usage', + [], + 'Modules.Ps_DemoCQRSHooksUsage' + ); + + $this->description = + $this->getTranslator()->trans( + 'Help developers to understand how to create module using new hooks and apply best practices when using CQRS', + [], + 'Modules.Ps_DemoCQRSHooksUsage' + ); + + $this->ps_versions_compliancy = [ + 'min' => '1.7.6.0', + 'max' => _PS_VERSION_, + ]; + } + + /** + * Install module and register hooks to allow grid modification. + * + * @return bool + */ + public function install() + { + return parent::install() && + // Register hook to allow Customer grid definition modifications. + // Each grid's definition modification hook has it's own name. Hook name is built using + // this structure: "action{grid_id}GridDefinitionModifier", in this case "grid_id" is "customer" + // this means we will be modifying "Sell > Customers" page grid. + // You can check any definition factory service in PrestaShop\PrestaShop\Core\Grid\Definition\Factory + // to see available grid ids. Grid id is returned by `getId()` method. + $this->registerHook('actionCustomerGridDefinitionModifier') && + // Register hook to allow Customer grid query modifications which allows to add any sql condition. + $this->registerHook('actionCustomerGridQueryBuilderModifier') && + // Register hook to allow overriding customer form + // this structure: "action{block_prefix}FormBuilderModifier", in this case "block_prefix" is "customer" + // {block_prefix} is either retrieved automatically by its type. E.g "ManufacturerType" will be "manufacturer" + // or it can be modified in form type by overriding "getBlockPrefix" function + $this->registerHook('actioncustomerFormBuilderModifier') && + $this->registerHook('actionAfterCreatecustomerFormHandler') && + $this->registerHook('actionAfterUpdatecustomerFormHandler') && + $this->installTables() + ; + } + + public function uninstall() + { + return parent::uninstall() && $this->uninstallTables(); + } + + /** + * Hook allows to modify Customers grid definition. + * This hook is a right place to add/remove columns or actions (bulk, grid). + * + * @param array $params + */ + public function hookActionCustomerGridDefinitionModifier(array $params) + { + /** @var GridDefinitionInterface $definition */ + $definition = $params['definition']; + + $translator = $this->getTranslator(); + + $definition + ->getColumns() + ->addAfter( + 'optin', + (new ToggleColumn('is_allowed_for_review')) + ->setName($translator->trans('Allowed for review', [], 'Modules.Ps_DemoCQRSHooksUsage')) + ->setOptions([ + 'field' => 'is_allowed_for_review', + 'primary_field' => 'id_customer', + 'route' => 'ps_democqrshooksusage_toggle_is_allowed_for_review', + 'route_param_name' => 'customerId', + ]) + ) + ; + + $definition->getFilters()->add( + (new Filter('is_allowed_for_review', YesAndNoChoiceType::class)) + ->setAssociatedColumn('is_allowed_for_review') + ); + } + + /** + * Hook allows to modify Customers query builder and add custom sql statements. + * + * @param array $params + */ + public function hookActionCustomerGridQueryBuilderModifier(array $params) + { + /** @var QueryBuilder $searchQueryBuilder */ + $searchQueryBuilder = $params['search_query_builder']; + + /** @var CustomerFilters $searchCriteria */ + $searchCriteria = $params['search_criteria']; + + $searchQueryBuilder->addSelect( + 'IF(dcur.`is_allowed_for_review` IS NULL,0,dcur.`is_allowed_for_review`) AS `is_allowed_for_review`' + ); + + $searchQueryBuilder->leftJoin( + 'c', + '`' . pSQL(_DB_PREFIX_) . 'democqrshooksusage_reviewer`', + 'dcur', + 'dcur.`id_customer` = c.`id_customer`' + ); + + if ('is_allowed_for_review' === $searchCriteria->getOrderBy()) { + $searchQueryBuilder->orderBy('dcur.`is_allowed_for_review`', $searchCriteria->getOrderWay()); + } + + foreach ($searchCriteria->getFilters() as $filterName => $filterValue) { + if ('is_allowed_for_review' === $filterName) { + $searchQueryBuilder->andWhere('dcur.`is_allowed_for_review` = :is_allowed_for_review'); + $searchQueryBuilder->setParameter('is_allowed_for_review', $filterValue); + + if (!$filterValue) { + $searchQueryBuilder->orWhere('dcur.`is_allowed_for_review` IS NULL'); + } + } + } + } + + /** + * Hook allows to modify Customers form and add aditional form fields as well as modify or add new data to the forms. + * + * @param array $params + */ + public function hookactioncustomerFormBuilderModifier(array $params) + { + /** @var FormBuilderInterface $formBuilder */ + $formBuilder = $params['form_builder']; + $formBuilder->add('is_allowed_for_review', SwitchType::class); + + /** @var CommandBusInterface $queryBus */ + $queryBus = $this->get('prestashop.core.query_bus'); + + /** @var ReviewerSettingsForForm $reviewerSettings */ + $reviewerSettings = $queryBus->handle(new GetReviewerSettingsForForm($params['id'])); + + $params['data']['is_allowed_for_review'] = $reviewerSettings->isAllowedForReview(); + + $formBuilder->setData($params['data']); + } + + /** + * Hook allows to modify Customers form and add aditional form fields as well as modify or add new data to the forms. + * + * @param array $params + * + * @throws CustomerException + */ + public function hookactionAfterUpdatecustomerFormHandler(array $params) + { + $this->updateCustomerReviewStatus($params); + } + + /** + * Hook allows to modify Customers form and add aditional form fields as well as modify or add new data to the forms. + * + * @param array $params + * + * @throws CustomerException + */ + public function hookactionAfterCreatecustomerFormHandler(array $params) + { + $this->updateCustomerReviewStatus($params); + } + + /** + * @param array $params + * + * @throws CustomerException + */ + private function updateCustomerReviewStatus(array $params) + { + //todo: a better would be to grab the data from array? + + $customerId = $params['id']; + /** @var Request $request */ + $request = $params['request']; + /** @var array $customerFormData */ + $customerFormData = $request->get('customer'); + $isAllowedForReview = (bool) $customerFormData['is_allowed_for_review']; + + /** @var CommandBusInterface $commandBus */ + $commandBus = $this->get('prestashop.core.command_bus'); + + try { + $commandBus->handle(new UpdateIsAllowedToReviewCommand( + $customerId, + $isAllowedForReview + )); + } catch (ReviewerException $exception) { + $this->handleException($exception); + } + } + + /** + * Installs sample tables required for demonstration. + * + * @return bool + */ + private function installTables() + { + $sql = ' + CREATE TABLE IF NOT EXISTS `' . pSQL(_DB_PREFIX_) . 'democqrshooksusage_reviewer` ( + `id_reviewer` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, + `id_customer` INT(10) UNSIGNED NOT NULL, + `is_allowed_for_review` TINYINT(1) NOT NULL, + PRIMARY KEY (`id_reviewer`) + ) ENGINE=' . pSQL(_MYSQL_ENGINE_) . ' COLLATE=utf8_unicode_ci; + '; + + return Db::getInstance()->execute($sql); + } + + /** + * Uninstalls sample tables required for demonstration. + * + * @return bool + */ + private function uninstallTables() + { + $sql = 'DROP TABLE IF EXISTS `' . pSQL(_DB_PREFIX_) . 'democqrshooksusage_reviewer`'; + + return Db::getInstance()->execute($sql); + } + + /** + * Handles exceptions and displays message in more user friendly form. + * + * @param ReviewerException $exception + */ + private function handleException(ReviewerException $exception) + { + $exceptionDictionary = [ + CannotCreateReviewerException::class => $this->getTranslator()->trans( + 'Failed to create a record for customer', + [], + 'Modules.Ps_DemoCQRSHooksUsage' + ), + CannotToggleAllowedToReviewStatusException::class => $this->getTranslator()->trans( + 'Failed to toggle is allowed to review status', + [], + 'Modules.Ps_DemoCQRSHooksUsage' + ), + ]; + + $exceptionType = get_class($exception); + + /** @var FlashBagInterface $flashBag */ + $flashBag = $this->get('session')->getFlashBag(); + + + if (isset($exceptionDictionary[$exceptionType])) { + $flashBag->add('error', $exceptionDictionary[$exceptionType]); + + return; + } + + $fallbackMessage = $this->getTranslator()->trans( + 'An unexpected error occurred. [%type% code %code%]', + [ + '%type%' => $exceptionType, + '%code%' => $exception->getCode(), + ], + 'Admin.Notifications.Error' + ); + + $flashBag->add('error', $fallbackMessage); + } +} diff --git a/src/Controller/Admin/CustomerReviewController.php b/src/Controller/Admin/CustomerReviewController.php new file mode 100755 index 0000000..81d5483 --- /dev/null +++ b/src/Controller/Admin/CustomerReviewController.php @@ -0,0 +1,87 @@ + + * @copyright 2007-2019 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace DemoCQRSHooksUsage\Controller\Admin; + +use DemoCQRSHooksUsage\Domain\Reviewer\Command\ToggleIsAllowedToReviewCommand; +use DemoCQRSHooksUsage\Domain\Reviewer\Exception\CannotCreateReviewerException; +use DemoCQRSHooksUsage\Domain\Reviewer\Exception\CannotToggleAllowedToReviewStatusException; +use DemoCQRSHooksUsage\Domain\Reviewer\Exception\ReviewerException; +use PrestaShop\PrestaShop\Core\Domain\Customer\Exception\CustomerException; +use PrestaShopBundle\Controller\Admin\FrameworkBundleAdminController; +use Symfony\Component\HttpFoundation\RedirectResponse; + +/** + * This controller holds all custom actions which are added by extending "Sell > Customers" page. + */ +class CustomerReviewController extends FrameworkBundleAdminController +{ + /** + * Catches the toggle action of customer review. + * + * @param int $customerId + * + * @return RedirectResponse + */ + public function toggleIsAllowedForReviewAction($customerId) + { + try { + $this->getCommandBus()->handle(new ToggleIsAllowedToReviewCommand((int)$customerId)); + + $this->addFlash('success', $this->trans('Successful update.', 'Admin.Notifications.Success')); + } catch (CustomerException $e) { + $this->addFlash('error', $this->getErrorMessageForException($e, $this->getErrorMessageMapping())); + } catch (ReviewerException $e) { + $this->addFlash('error', $this->getErrorMessageForException($e, $this->getErrorMessageMapping())); + } + + return $this->redirectToRoute('admin_customers_index'); + } + + /** + * Gets error message mappings which are later used to display friendly user error message instead of the + * exception message. + * + * @return array + */ + private function getErrorMessageMapping() + { + return [ + CustomerException::class => $this->trans( + 'Something bad happened when trying to get customer id', + 'Modules.Ps_DemoCQRSHooksUsage' + ), + CannotCreateReviewerException::class => $this->trans( + 'Failed to create reviewer', + 'Modules.Ps_DemoCQRSHooksUsage' + ), + CannotToggleAllowedToReviewStatusException::class => $this->trans( + 'An error occurred while updating the status.', + 'Admin.Notifications.Error' + ) + ]; + } +} diff --git a/src/Domain/Reviewer/Command/ToggleIsAllowedToReviewCommand.php b/src/Domain/Reviewer/Command/ToggleIsAllowedToReviewCommand.php new file mode 100755 index 0000000..1491dc8 --- /dev/null +++ b/src/Domain/Reviewer/Command/ToggleIsAllowedToReviewCommand.php @@ -0,0 +1,59 @@ + + * @copyright 2007-2019 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace DemoCQRSHooksUsage\Domain\Reviewer\Command; + +use PrestaShop\PrestaShop\Core\Domain\Customer\Exception\CustomerException; +use PrestaShop\PrestaShop\Core\Domain\Customer\ValueObject\CustomerId; + +/** + * Used for toggling the customer if is allowed to make a review. + */ +class ToggleIsAllowedToReviewCommand +{ + /** + * @var CustomerId + */ + private $customerId; + + /** + * @param int $customerId + * + * @throws CustomerException + */ + public function __construct($customerId) + { + $this->customerId = new CustomerId($customerId); + } + + /** + * @return CustomerId + */ + public function getCustomerId() + { + return $this->customerId; + } +} diff --git a/src/Domain/Reviewer/Command/UpdateIsAllowedToReviewCommand.php b/src/Domain/Reviewer/Command/UpdateIsAllowedToReviewCommand.php new file mode 100644 index 0000000..3519393 --- /dev/null +++ b/src/Domain/Reviewer/Command/UpdateIsAllowedToReviewCommand.php @@ -0,0 +1,74 @@ + + * @copyright 2007-2019 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace DemoCQRSHooksUsage\Domain\Reviewer\Command; + +use PrestaShop\PrestaShop\Core\Domain\Customer\Exception\CustomerException; +use PrestaShop\PrestaShop\Core\Domain\Customer\ValueObject\CustomerId; + +/** + * used to update customers review status. + */ +class UpdateIsAllowedToReviewCommand +{ + /** + * @var CustomerId + */ + private $customerId; + + /** + * @var bool + */ + private $isAllowedToReview; + + /** + * @param int $customerId + * @param bool $isAllowedToReview + * + * @throws CustomerException + */ + public function __construct($customerId, $isAllowedToReview) + { + $this->customerId = new CustomerId($customerId); + $this->isAllowedToReview = $isAllowedToReview; + } + + /** + * @return CustomerId + */ + public function getCustomerId() + { + return $this->customerId; + } + + /** + * @return bool + */ + public function isAllowedToReview() + { + return $this->isAllowedToReview; + } +} diff --git a/src/Domain/Reviewer/CommandHandler/AbstractReviewerHandler.php b/src/Domain/Reviewer/CommandHandler/AbstractReviewerHandler.php new file mode 100644 index 0000000..e00e9ea --- /dev/null +++ b/src/Domain/Reviewer/CommandHandler/AbstractReviewerHandler.php @@ -0,0 +1,74 @@ + + * @copyright 2007-2019 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace DemoCQRSHooksUsage\Domain\Reviewer\CommandHandler; + +use DemoCQRSHooksUsage\Domain\Reviewer\Exception\CannotCreateReviewerException; +use DemoCQRSHooksUsage\Entity\Reviewer; + +/** + * Holds the abstraction for common actions for reviewer commands. + */ +class AbstractReviewerHandler +{ + /** + * Creates a reviewer. + * + * @param $customerId + * + * @return Reviewer + * + * @throws CannotCreateReviewerException + */ + protected function createReviewer($customerId) + { + try { + $reviewer = new Reviewer(); + $reviewer->id_customer = $customerId; + $reviewer->is_allowed_for_review = 0; + + if (false === $reviewer->save()) { + throw new CannotCreateReviewerException( + sprintf( + 'An error occurred when creating reviewer with customer id "%s"', + $customerId + ) + ); + } + } catch (PrestaShopException $exception) { + throw new CannotCreateReviewerException( + sprintf( + 'An unexpected error occurred when creating reviewer with customer id "%s"', + $customerId + ), + 0, + $exception + ); + } + + return $reviewer; + } +} diff --git a/src/Domain/Reviewer/CommandHandler/ToggleIsAllowedToReviewHandler.php b/src/Domain/Reviewer/CommandHandler/ToggleIsAllowedToReviewHandler.php new file mode 100755 index 0000000..368c0f2 --- /dev/null +++ b/src/Domain/Reviewer/CommandHandler/ToggleIsAllowedToReviewHandler.php @@ -0,0 +1,86 @@ + + * @copyright 2007-2019 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace DemoCQRSHooksUsage\Domain\Reviewer\CommandHandler; + +use DemoCQRSHooksUsage\Domain\Reviewer\Command\ToggleIsAllowedToReviewCommand; +use DemoCQRSHooksUsage\Domain\Reviewer\Exception\CannotCreateReviewerException; +use DemoCQRSHooksUsage\Domain\Reviewer\Exception\CannotToggleAllowedToReviewStatusException; +use DemoCQRSHooksUsage\Entity\Reviewer; +use DemoCQRSHooksUsage\Repository\ReviewerRepository; +use Doctrine\DBAL\Connection; +use PDO; +use PrestaShopException; + +/** + * Used for toggling the customer if is allowed to make a review. + */ +class ToggleIsAllowedToReviewHandler extends AbstractReviewerHandler +{ + /** + * @var ReviewerRepository + */ + private $reviewerRepository; + + /** + * @param ReviewerRepository $reviewerRepository + */ + public function __construct(ReviewerRepository $reviewerRepository) + { + $this->reviewerRepository = $reviewerRepository; + } + + /** + * @param ToggleIsAllowedToReviewCommand $command + * + * @throws CannotCreateReviewerException + * @throws CannotToggleAllowedToReviewStatusException + */ + public function handle(ToggleIsAllowedToReviewCommand $command) + { + $reviewerId = $this->reviewerRepository->findIdByCustomer($command->getCustomerId()->getValue()); + + $reviewer = new Reviewer($reviewerId); + + if (0 >= $reviewer->id) { + $reviewer = $this->createReviewer($command->getCustomerId()->getValue()); + } + + $reviewer->is_allowed_for_review = (bool) !$reviewer->is_allowed_for_review; + + try { + if (false === $reviewer->update()) { + throw new CannotToggleAllowedToReviewStatusException( + sprintf('Failed to change status for reviewer with id "%s"', $reviewer->id) + ); + } + } catch (PrestaShopException $exception) { + throw new CannotToggleAllowedToReviewStatusException( + 'An unexpected error occurred when updating reviewer status' + ); + } + } +} diff --git a/src/Domain/Reviewer/CommandHandler/UpdateIsAllowedToReviewHandler.php b/src/Domain/Reviewer/CommandHandler/UpdateIsAllowedToReviewHandler.php new file mode 100644 index 0000000..1a5b2c1 --- /dev/null +++ b/src/Domain/Reviewer/CommandHandler/UpdateIsAllowedToReviewHandler.php @@ -0,0 +1,77 @@ + + * @copyright 2007-2019 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace DemoCQRSHooksUsage\Domain\Reviewer\CommandHandler; + +use DemoCQRSHooksUsage\Domain\Reviewer\Command\UpdateIsAllowedToReviewCommand; +use DemoCQRSHooksUsage\Domain\Reviewer\Exception\CannotToggleAllowedToReviewStatusException; +use DemoCQRSHooksUsage\Entity\Reviewer; +use DemoCQRSHooksUsage\Repository\ReviewerRepository; +use PrestaShopException; + +/** + * used to update customers review status. + */ +class UpdateIsAllowedToReviewHandler extends AbstractReviewerHandler +{ + /** + * @var ReviewerRepository + */ + private $reviewerRepository; + + /** + * @param ReviewerRepository $reviewerRepository + */ + public function __construct(ReviewerRepository $reviewerRepository) + { + $this->reviewerRepository = $reviewerRepository; + } + + public function handle(UpdateIsAllowedToReviewCommand $command) + { + $reviewerId = $this->reviewerRepository->findIdByCustomer($command->getCustomerId()->getValue()); + + $reviewer = new Reviewer($reviewerId); + + if (0 >= $reviewer->id) { + $reviewer = $this->createReviewer($command->getCustomerId()->getValue()); + } + + $reviewer->is_allowed_for_review = $command->isAllowedToReview(); + + try { + if (false === $reviewer->update()) { + throw new CannotToggleAllowedToReviewStatusException( + sprintf('Failed to change status for reviewer with id "%s"', $reviewer->id) + ); + } + } catch (PrestaShopException $exception) { + throw new CannotToggleAllowedToReviewStatusException( + 'An unexpected error occurred when updating reviewer status' + ); + } + } +} diff --git a/src/Domain/Reviewer/Exception/CannotCreateReviewerException.php b/src/Domain/Reviewer/Exception/CannotCreateReviewerException.php new file mode 100644 index 0000000..0449545 --- /dev/null +++ b/src/Domain/Reviewer/Exception/CannotCreateReviewerException.php @@ -0,0 +1,32 @@ + + * @copyright 2007-2019 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace DemoCQRSHooksUsage\Domain\Reviewer\Exception; + +class CannotCreateReviewerException extends ReviewerException +{ + +} diff --git a/src/Domain/Reviewer/Exception/CannotToggleAllowedToReviewStatusException.php b/src/Domain/Reviewer/Exception/CannotToggleAllowedToReviewStatusException.php new file mode 100644 index 0000000..e98322e --- /dev/null +++ b/src/Domain/Reviewer/Exception/CannotToggleAllowedToReviewStatusException.php @@ -0,0 +1,31 @@ + + * @copyright 2007-2019 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace DemoCQRSHooksUsage\Domain\Reviewer\Exception; + +class CannotToggleAllowedToReviewStatusException extends ReviewerException +{ +} diff --git a/src/Domain/Reviewer/Exception/ReviewerException.php b/src/Domain/Reviewer/Exception/ReviewerException.php new file mode 100644 index 0000000..abbb49d --- /dev/null +++ b/src/Domain/Reviewer/Exception/ReviewerException.php @@ -0,0 +1,33 @@ + + * @copyright 2007-2019 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace DemoCQRSHooksUsage\Domain\Reviewer\Exception; + +use PrestaShop\PrestaShop\Core\Domain\Exception\DomainException; + +class ReviewerException extends DomainException +{ +} diff --git a/src/Domain/Reviewer/Query/GetReviewerSettingsForForm.php b/src/Domain/Reviewer/Query/GetReviewerSettingsForForm.php new file mode 100644 index 0000000..5441b1f --- /dev/null +++ b/src/Domain/Reviewer/Query/GetReviewerSettingsForForm.php @@ -0,0 +1,56 @@ + + * @copyright 2007-2019 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace DemoCQRSHooksUsage\Domain\Reviewer\Query; + +use PrestaShop\PrestaShop\Core\Domain\Customer\ValueObject\CustomerId; + +/** + * Gets reviewer settings data ready for form display. + */ +class GetReviewerSettingsForForm +{ + /** + * @var CustomerId|null + */ + private $customerId; + + /** + * @param int|null $customerId + */ + public function __construct($customerId) + { + $this->customerId = null !== $customerId ? new CustomerId((int) $customerId) : null; + } + + /** + * @return CustomerId|null + */ + public function getCustomerId() + { + return $this->customerId; + } +} diff --git a/src/Domain/Reviewer/QueryHandler/GetReviewerSettingsForFormHandler.php b/src/Domain/Reviewer/QueryHandler/GetReviewerSettingsForFormHandler.php new file mode 100644 index 0000000..f003d90 --- /dev/null +++ b/src/Domain/Reviewer/QueryHandler/GetReviewerSettingsForFormHandler.php @@ -0,0 +1,63 @@ + + * @copyright 2007-2019 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace DemoCQRSHooksUsage\Domain\Reviewer\QueryHandler; + +use DemoCQRSHooksUsage\Domain\Reviewer\Query\GetReviewerSettingsForForm; +use DemoCQRSHooksUsage\Domain\Reviewer\QueryResult\ReviewerSettingsForForm; +use DemoCQRSHooksUsage\Repository\ReviewerRepository; + +/** + * Gets reviewer settings data ready for form display. + */ +class GetReviewerSettingsForFormHandler +{ + + /** + * @var ReviewerRepository + */ + private $reviewerRepository; + + /** + * @param ReviewerRepository $reviewerRepository + */ + public function __construct(ReviewerRepository $reviewerRepository) + { + + $this->reviewerRepository = $reviewerRepository; + } + + public function handle(GetReviewerSettingsForForm $query) + { + if (null === $query->getCustomerId()) { + return new ReviewerSettingsForForm(false); + } + + return new ReviewerSettingsForForm( + $this->reviewerRepository->getIsAllowedToReviewStatus($query->getCustomerId()->getValue()) + ); + } +} diff --git a/src/Domain/Reviewer/QueryResult/ReviewerSettingsForForm.php b/src/Domain/Reviewer/QueryResult/ReviewerSettingsForForm.php new file mode 100644 index 0000000..852b16f --- /dev/null +++ b/src/Domain/Reviewer/QueryResult/ReviewerSettingsForForm.php @@ -0,0 +1,54 @@ + + * @copyright 2007-2019 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace DemoCQRSHooksUsage\Domain\Reviewer\QueryResult; + +/** + * Holds data used in modified customers form. + */ +class ReviewerSettingsForForm +{ + /** + * @var bool + */ + private $isAllowedForReview; + + /** + * @param bool $isAllowedForReview + */ + public function __construct($isAllowedForReview) + { + $this->isAllowedForReview = $isAllowedForReview; + } + + /** + * @return bool + */ + public function isAllowedForReview() + { + return $this->isAllowedForReview; + } +} diff --git a/src/Entity/Reviewer.php b/src/Entity/Reviewer.php new file mode 100755 index 0000000..8fac85c --- /dev/null +++ b/src/Entity/Reviewer.php @@ -0,0 +1,51 @@ + + * @copyright 2007-2019 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace DemoCQRSHooksUsage\Entity; + +use PrestaShop\PrestaShop\Adapter\Entity\ObjectModel; + +class Reviewer extends ObjectModel +{ + /** + * @var int + */ + public $id_customer; + + /** + * @var int + */ + public $is_allowed_for_review; + + public static $definition = [ + 'table' => 'democqrshooksusage_reviewer', + 'primary' => 'id_reviewer', + 'fields' => [ + 'id_customer' => ['type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'], + 'is_allowed_for_review' => ['type' => self::TYPE_BOOL, 'validate' => 'isBool'], + ] + ]; +} diff --git a/src/Repository/ReviewerRepository.php b/src/Repository/ReviewerRepository.php new file mode 100644 index 0000000..3d0f184 --- /dev/null +++ b/src/Repository/ReviewerRepository.php @@ -0,0 +1,97 @@ + + * @copyright 2007-2019 PrestaShop SA and Contributors + * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) + * International Registered Trademark & Property of PrestaShop SA + */ + +namespace DemoCQRSHooksUsage\Repository; + +use Doctrine\DBAL\Connection; +use PDO; + +class ReviewerRepository +{ + /** + * @var Connection + */ + private $connection; + + /** + * @var string + */ + private $dbPrefix; + + /** + * @param Connection $connection + * @param string $dbPrefix + */ + public function __construct(Connection $connection, $dbPrefix) + { + $this->connection = $connection; + $this->dbPrefix = $dbPrefix; + } + + /** + * Finds customer id if such exists. + * + * @param int $customerId + * + * @return int + */ + public function findIdByCustomer($customerId) + { + $queryBuilder = $this->connection->createQueryBuilder(); + + $queryBuilder + ->select('`id_reviewer`') + ->from($this->dbPrefix . 'democqrshooksusage_reviewer') + ->where('`id_customer` = :customer_id') + ; + + $queryBuilder->setParameter('customer_id', $customerId); + + return (int) $queryBuilder->execute()->fetch(PDO::FETCH_COLUMN); + } + + /** + * Gets allowed to review status by customer. + * + * @param int $customerId + * + * @return bool + */ + public function getIsAllowedToReviewStatus($customerId) + { + $queryBuilder = $this->connection->createQueryBuilder(); + + $queryBuilder + ->select('`is_allowed_for_review`') + ->from($this->dbPrefix . 'democqrshooksusage_reviewer') + ->where('`id_customer` = :customer_id') + ; + + $queryBuilder->setParameter('customer_id', $customerId); + + return (bool) $queryBuilder->execute()->fetch(PDO::FETCH_COLUMN); + } +}