Skip to content

Commit

Permalink
Merge pull request #35 from matks/split-module-2
Browse files Browse the repository at this point in the history
Rewrite demoextendsymfonyform1 module without CQRS
  • Loading branch information
matks authored Feb 2, 2021
2 parents 8fd3d4f + 6a4fcaa commit 6d1f35f
Show file tree
Hide file tree
Showing 19 changed files with 172 additions and 585 deletions.
18 changes: 9 additions & 9 deletions demoextendsymfonyform1/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Demonstration of how to insert an inputs inside the Symfony form

Learn using identifiable object and grid hooks as well as combining CQRS pattern from module
Learn using identifiable object and grid hooks.

## About

Expand All @@ -12,21 +12,23 @@ This new field appears:
This modules demonstrates
- how to add this field, manage its content and its
properties using modern hooks in Symfony pages
- how to use custom [CQRS](https://devdocs.prestashop.com/1.7/development/architecture/domain/cqrs/) Commands and Queries to separate your domain from your application*
- how to use Translator inside modern Symfony module

*This part is only demonstrated as a possibility for your module, this is
not mandatory to be done this way.
### Details

### Supported PrestaShop versions
This module uses an ObjectModel entity to persist the data submitted by the user.
[Other modules](https://github.com/PrestaShop/example-modules/tree/master/demoextendsymfonyform2) demonstrate
how to use DoctrineORM.

### Supported PrestaShop versions

This module is compatible with and 1.7.6.0 and above versions.

### Requirements
### Requirements

1. Composer, see [Composer](https://getcomposer.org/) to learn more

### How to install
### How to install

1. Download or clone module into `modules` directory of your PrestaShop installation
2. Rename the directory to make sure that module directory is named `demoextendsymfonyform1`*
Expand All @@ -35,5 +37,3 @@ not mandatory to be done this way.
4. Install module from Back Office

*Because the name of the directory and the name of the main module file must match.


19 changes: 15 additions & 4 deletions demoextendsymfonyform1/composer.json
Original file line number Diff line number Diff line change
@@ -1,11 +1,22 @@
{
"name": "prestashop/democqrshooksusage",
"description": "Help developers to understand how to create module using new hooks and apply best practices when using CQRS",
"name": "prestashop/demoextendsymfonyform1",
"authors": [
{
"name": "Tomas Ilginis"
},
{
"name": "PrestaShop Core Team"
}
],
"description": "Help developers to understand how to create module using Symfony hooks",
"autoload": {
"psr-4": {
"DemoCQRSHooksUsage\\": "src/"
"PrestaShop\\Module\\DemoHowToExtendSymfonyForm\\": "src/"
}
},
"license": "MIT",
"type": "prestashop-module"
"type": "prestashop-module",
"config": {
"prepend-autoloader": false
}
}
6 changes: 3 additions & 3 deletions demoextendsymfonyform1/config/routes.yml
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# @see https://devdocs.prestashop.com/1.7/modules/concepts/controllers/admin-controllers/#how-to-map-an-action-of-your-controller-to-a-uri
ps_democqrshooksusage_toggle_is_allowed_for_review:
path: demo-cqrs-hook-usage/{customerId}/toggle-is-allowed-for-review
ps_demoextendsymfonyform_toggle_is_allowed_for_review:
path: ps_demoextendsymfonyform/{customerId}/toggle-is-allowed-for-review
methods: [POST]
defaults:
_controller: 'DemoCQRSHooksUsage\Controller\Admin\CustomerReviewController::toggleIsAllowedForReviewAction'
_controller: 'PrestaShop\Module\DemoHowToExtendSymfonyForm\Controller\Admin\CustomerReviewController::toggleIsAllowedForReviewAction'
requirements:
customerId: \d+
29 changes: 2 additions & 27 deletions demoextendsymfonyform1/config/services.yml
Original file line number Diff line number Diff line change
@@ -1,33 +1,8 @@
services:
_defaults:
public: true
# @see https://devdocs.prestashop.com/1.7/development/architecture/migration-guide/forms/cqrs-usage-in-forms/ for CQRS pattern usage examples.
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'
ps_demoextendsymfonyform.repository.reviewer:
class: 'PrestaShop\Module\DemoHowToExtendSymfonyForm\Repository\ReviewerRepository'
arguments:
- '@doctrine.dbal.default_connection'
- '%database_prefix%'
158 changes: 69 additions & 89 deletions demoextendsymfonyform1/demoextendsymfonyform1.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,11 @@
* It is also available through the world-wide-web at this URL: https://opensource.org/licenses/AFL-3.0
*/

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\Module\DemoHowToExtendSymfonyForm\Entity\Reviewer;
use PrestaShop\Module\DemoHowToExtendSymfonyForm\Exception\CannotCreateReviewerException;
use PrestaShop\Module\DemoHowToExtendSymfonyForm\Exception\CannotToggleAllowedToReviewStatusException;
use PrestaShop\PrestaShop\Core\Domain\Customer\Exception\CustomerException;
use PrestaShop\PrestaShop\Core\Grid\Column\Type\Common\ToggleColumn;
use PrestaShop\PrestaShop\Core\Grid\Definition\GridDefinitionInterface;
Expand All @@ -24,34 +21,32 @@
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;

/**
* Class DemoExtendSymfonyForm1 demonstrates the usage of CQRS pattern and hooks.
* Class DemoExtendSymfonyForm1 demonstrates the usage of Symfony hooks.
*/
class DemoExtendSymfonyForm1 extends Module
{
public function __construct()
{
$this->name = 'demoextendsymfonyform1';
$this->version = '1.0.0';
$this->author = 'Tomas Ilginis';
$this->version = '1.1.0';
$this->author = 'PrestaShop';
$this->need_instance = 0;

parent::__construct();

$this->displayName = $this->getTranslator()->trans(
'Demo Symfony Forms #1',
[],
'Modules.Democqrshooksusage.Admin'
'Modules.DemoHowToExtendSymfonyForm.Admin'
);

$this->description =
$this->getTranslator()->trans(
'Help developers to understand how to create module using new hooks and apply best practices when using CQRS',
'Help developers to understand how to create module using few Symfony hooks available in PrestaShop',
[],
'Modules.Democqrshooksusage.Admin'
'Modules.DemoHowToExtendSymfonyForm.Admin'
);

$this->ps_versions_compliancy = [
Expand Down Expand Up @@ -96,8 +91,7 @@ public function install()
$this->registerHook('actionCustomerFormBuilderModifier') &&
$this->registerHook('actionAfterCreateCustomerFormHandler') &&
$this->registerHook('actionAfterUpdateCustomerFormHandler') &&
$this->installTables()
;
$this->installTables();
}

public function uninstall()
Expand All @@ -123,19 +117,18 @@ public function hookActionCustomerGridDefinitionModifier(array $params)
->addAfter(
'optin',
(new ToggleColumn('is_allowed_for_review'))
->setName($translator->trans('Allowed for review', [], 'Modules.Democqrshooksusage.Admin'))
->setName($translator->trans('Allowed for review', [], 'Modules.DemoHowToExtendSymfonyForm.Admin'))
->setOptions([
'field' => 'is_allowed_for_review',
'primary_field' => 'id_customer',
'route' => 'ps_democqrshooksusage_toggle_is_allowed_for_review',
'route' => 'ps_demoextendsymfonyform_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')
->setAssociatedColumn('is_allowed_for_review')
);
}

Expand All @@ -158,7 +151,7 @@ public function hookActionCustomerGridQueryBuilderModifier(array $params)

$searchQueryBuilder->leftJoin(
'c',
'`' . pSQL(_DB_PREFIX_) . 'democqrshooksusage_reviewer`',
'`' . pSQL(_DB_PREFIX_) . 'demoextendsymfonyform_reviewer`',
'dcur',
'dcur.`id_customer` = c.`id_customer`'
);
Expand Down Expand Up @@ -189,28 +182,16 @@ public function hookActionCustomerFormBuilderModifier(array $params)
/** @var FormBuilderInterface $formBuilder */
$formBuilder = $params['form_builder'];
$formBuilder->add('is_allowed_for_review', SwitchType::class, [
'label' => $this->getTranslator()->trans('Allow reviews', [], 'Modules.Democqrshooksusage.Admin'),
'label' => $this->getTranslator()->trans('Allow reviews', [], 'Modules.DemoHowToExtendSymfonyForm.Admin'),
'required' => false,
]);

/**
* @var CommandBusInterface
*/
$queryBus = $this->get('prestashop.core.query_bus');

/**
* This part demonstrates the usage of CQRS pattern query to perform read operation from Reviewer entity.
*
* @see https://devdocs.prestashop.com/1.7/development/architecture/cqrs/ for more detailed information.
*
* As this is our recommended approach of reading the data but we not force to use this pattern in modules -
* you can use directly an entity here or wrap it in custom service class.
*
* @var ReviewerSettingsForForm
*/
$reviewerSettings = $queryBus->handle(new GetReviewerSettingsForForm($params['id']));

$params['data']['is_allowed_for_review'] = $reviewerSettings->isAllowedForReview();
$result = false;
if (null !== $params['id']) {
$result = $this->get('ps_demoextendsymfonyform.repository.reviewer')->getIsAllowedToReviewStatus((int) $params['id']);
}

$params['data']['is_allowed_for_review'] = $result;

$formBuilder->setData($params['data']);
}
Expand Down Expand Up @@ -251,23 +232,24 @@ private function updateCustomerReviewStatus(array $params)
$customerFormData = $params['form_data'];
$isAllowedForReview = (bool) $customerFormData['is_allowed_for_review'];

/** @var CommandBusInterface $commandBus */
$commandBus = $this->get('prestashop.core.command_bus');
$reviewerId = $this->get('ps_demoextendsymfonyform.repository.reviewer')->findIdByCustomer($customerId);

$reviewer = new Reviewer($reviewerId);
if (0 >= $reviewer->id) {
$reviewer = $this->createReviewer($customerId);
}
$reviewer->is_allowed_for_review = $isAllowedForReview;

try {
/*
* This part demonstrates the usage of CQRS pattern command to perform write operation for Reviewer entity.
* @see https://devdocs.prestashop.com/1.7/development/architecture/cqrs/ for more detailed information.
*
* As this is our recommended approach of writing the data but we not force to use this pattern in modules -
* you can use directly an entity here or wrap it in custom service class.
*/
$commandBus->handle(new UpdateIsAllowedToReviewCommand(
$customerId,
$isAllowedForReview
));
} catch (ReviewerException $exception) {
$this->handleException($exception);
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'
);
}
}

Expand All @@ -279,7 +261,7 @@ private function updateCustomerReviewStatus(array $params)
private function installTables()
{
$sql = '
CREATE TABLE IF NOT EXISTS `' . pSQL(_DB_PREFIX_) . 'democqrshooksusage_reviewer` (
CREATE TABLE IF NOT EXISTS `' . pSQL(_DB_PREFIX_) . 'demoextendsymfonyform_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,
Expand All @@ -297,48 +279,46 @@ private function installTables()
*/
private function uninstallTables()
{
$sql = 'DROP TABLE IF EXISTS `' . pSQL(_DB_PREFIX_) . 'democqrshooksusage_reviewer`';
$sql = 'DROP TABLE IF EXISTS `' . pSQL(_DB_PREFIX_) . 'demoextendsymfonyform_reviewer`';

return Db::getInstance()->execute($sql);
}

/**
* Handles exceptions and displays message in more user friendly form.
* Creates a reviewer.
*
* @param ReviewerException $exception
* @param int $customerId
*
* @throws \PrestaShop\PrestaShop\Core\Module\Exception\ModuleErrorException
* @return Reviewer
*
* @throws CannotCreateReviewerException
*/
private function handleException(ReviewerException $exception)
protected function createReviewer(int $customerId)
{
$exceptionDictionary = [
CannotCreateReviewerException::class => $this->getTranslator()->trans(
'Failed to create a record for customer',
[],
'Modules.Democqrshooksusage.Admin'
),
CannotToggleAllowedToReviewStatusException::class => $this->getTranslator()->trans(
'Failed to toggle is allowed to review status',
[],
'Modules.Democqrshooksusage.Admin'
),
];

$exceptionType = get_class($exception);

if (isset($exceptionDictionary[$exceptionType])) {
$message = $exceptionDictionary[$exceptionType];
} else {
$message = $this->getTranslator()->trans(
'An unexpected error occurred. [%type% code %code%]',
[
'%type%' => $exceptionType,
'%code%' => $exception->getCode(),
],
'Admin.Notifications.Error'
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
);
}

throw new \PrestaShop\PrestaShop\Core\Module\Exception\ModuleErrorException($message);
return $reviewer;
}
}
Loading

0 comments on commit 6d1f35f

Please sign in to comment.