diff --git a/.php_cs.dist b/.php-cs-fixer.dist.php similarity index 100% rename from .php_cs.dist rename to .php-cs-fixer.dist.php diff --git a/Makefile b/Makefile index b535084b3..7c3ace459 100755 --- a/Makefile +++ b/Makefile @@ -86,3 +86,13 @@ upgrading-module-test-$(VERSION): npm-package-install: cd views/assets && npm i && npm run build + +prepare-zip: + composer install --no-dev --optimize-autoloader --classmap-authoritative + composer dump-autoload --no-dev --optimize --classmap-authoritative + cp .github/.htaccess vendor/.htaccess + rm -rf .git .docker .editorconfig .github tests .php-cs-fixer.php Makefile cypress .docker cypress.config.js cypress.env.json docker-compose*.yml .gitignore bin codeception.yml package-lock.json package.json .php_cs.dist .php-cs-fixer.dist + + + + diff --git a/changelog.md b/changelog.md index b4396ccb2..2d0a3e828 100644 --- a/changelog.md +++ b/changelog.md @@ -2,6 +2,16 @@ # Changelog # +## Changes in release 6.2.0 ## ++ New payment methods: Bancomat and Alma ++ Apple certificate update ++ Conflicting services fix ++ Bootstrap 5 compatibility improved ++ Maximum fee field ++ Multi carrier for subscription orders added ++ Design improvements in BO ++ Improved subscription creation logic + ## Changes in release 6.1.1 ## + Updated translations for Dutch, German, English and French languages + Added credit card translations for Italian and Spanish languages diff --git a/composer.json b/composer.json index d86cafc06..ab171d36f 100644 --- a/composer.json +++ b/composer.json @@ -21,6 +21,7 @@ }, "require-dev": { "roave/security-advisories": "dev-latest", + "invertus/prestashop-models": "^1.0", "prestashop/php-dev-tools": "*", "phpunit/phpunit": "~5.7" }, @@ -32,7 +33,8 @@ "autoload": { "psr-4": { "Mollie\\": "src/", - "Mollie\\Subscription\\": "subscription/" + "Mollie\\Subscription\\": "subscription/", + "Mollie\\Shared\\": "shared/" }, "classmap": [ "mollie.php", diff --git a/controllers/front/ajax.php b/controllers/front/ajax.php index 1df5a79fd..5e222be7d 100644 --- a/controllers/front/ajax.php +++ b/controllers/front/ajax.php @@ -13,10 +13,12 @@ use Mollie\Adapter\ConfigurationAdapter; use Mollie\Adapter\ToolsAdapter; use Mollie\Controller\AbstractMollieController; +use Mollie\Errors\Http\HttpStatusCode; use Mollie\Exception\FailedToProvidePaymentFeeException; +use Mollie\Infrastructure\Response\JsonResponse; use Mollie\Provider\PaymentFeeProviderInterface; -use Mollie\Repository\CurrencyRepositoryInterface; -use Mollie\Subscription\Exception\SubscriptionProductValidationException; +use Mollie\Shared\Core\Shared\Repository\CurrencyRepositoryInterface; +use Mollie\Subscription\Exception\ExceptionCode; use Mollie\Subscription\Validator\CanProductBeAddedToCartValidator; use Mollie\Utility\NumberUtility; @@ -185,30 +187,35 @@ private function displayCheckoutError(): void private function validateProduct(): void { - /** @var CanProductBeAddedToCartValidator $cartValidation */ - $cartValidation = $this->module->getService(CanProductBeAddedToCartValidator::class); + /** @var CanProductBeAddedToCartValidator $canProductBeAddedToCartValidator */ + $canProductBeAddedToCartValidator = $this->module->getService(CanProductBeAddedToCartValidator::class); $product = Tools::getValue('product'); - $productCanBeAdded = true; - $message = ''; - try { - $cartValidation->validate((int) $product['id_product_attribute']); - } catch (SubscriptionProductValidationException $e) { - $productCanBeAdded = false; - $message = $this->module->l('Please note: Only one subscription product can be added to the cart at a time.', self::FILE_NAME); + $canProductBeAddedToCartValidator->validate((int) ($product['id_product_attribute'] ?? 0)); + } catch (\Throwable $exception) { + if ($exception->getCode() === ExceptionCode::CART_ALREADY_HAS_SUBSCRIPTION_PRODUCT) { + $this->ajaxResponse(JsonResponse::error( + $this->module->l('Please note: Only one subscription product can be added to the cart at a time.', self::FILE_NAME), + HttpStatusCode::HTTP_BAD_REQUEST + )); + } + + if ($exception->getCode() === ExceptionCode::CART_INVALID_SUBSCRIPTION_SETTINGS) { + $this->ajaxResponse(JsonResponse::error( + $this->module->l('Subscription service is disabled. Please change the attribute to Subscription: none.', self::FILE_NAME), + HttpStatusCode::HTTP_BAD_REQUEST + )); + } + + $this->ajaxResponse(JsonResponse::error( + $this->module->l('Unknown error. Try again or change the attribute to Subscription: none.', self::FILE_NAME), + HttpStatusCode::HTTP_BAD_REQUEST + )); } - $this->ajaxRender( - json_encode( - [ - 'success' => true, - 'isValid' => $productCanBeAdded, - 'message' => $message, - ] - ) - ); + $this->ajaxResponse(JsonResponse::success([])); } private function returnDefaultOrderSummaryBlock(Cart $cart, array $errorData = [], array $presentedCart = null): void diff --git a/controllers/front/recurringOrderDetail.php b/controllers/front/recurringOrderDetail.php index 41fcb8dbf..610f28a17 100644 --- a/controllers/front/recurringOrderDetail.php +++ b/controllers/front/recurringOrderDetail.php @@ -56,13 +56,28 @@ public function initContent() $recurringOrderId = (int) Tools::getValue('id_mol_recurring_order'); $recurringOrderId = Validate::isUnsignedId($recurringOrderId) ? $recurringOrderId : false; + $failureRedirectUrl = Context::getContext()->link->getModuleLink($this->module->name, 'subscriptions', [], true); + /** @var RecurringOrderRepositoryInterface $recurringOrderRepository */ $recurringOrderRepository = $this->module->getService(RecurringOrderRepositoryInterface::class); - $recurringOrder = $recurringOrderRepository->findOneBy(['id_mol_recurring_order' => $recurringOrderId]); + try { + /** @var \MolRecurringOrder $recurringOrder */ + $recurringOrder = $recurringOrderRepository->findOrFail([ + 'id_mol_recurring_order' => $recurringOrderId, + ]); + } catch (\Throwable $exception) { + // TODO add notification about data retrieve failure + + Tools::redirect($failureRedirectUrl); + + return; + } + + if ((int) $recurringOrder->id_customer !== (int) $this->context->customer->id) { + Tools::redirect($failureRedirectUrl); - if (!Validate::isLoadedObject($recurringOrder) || (int) $recurringOrder->id_customer !== (int) $this->context->customer->id) { - Tools::redirect(Context::getContext()->link->getModuleLink($this->module->name, 'subscriptions', [], true)); + return; } /** @var PrestaLoggerInterface $logger */ @@ -82,10 +97,13 @@ public function initContent() 'Exception code' => $exception->getCode(), ]); - Tools::redirect(Context::getContext()->link->getModuleLink($this->module->name, 'subscriptions', [], true)); + Tools::redirect($failureRedirectUrl); + + return; } parent::initContent(); + $this->context->controller->addCSS($this->module->getPathUri() . 'views/css/front/subscription/customer_order_detail.css'); $this->setTemplate('module:mollie/views/templates/front/subscription/customerRecurringOrderDetail.tpl'); } diff --git a/controllers/front/subscriptions.php b/controllers/front/subscriptions.php index 3776aa0fe..3ad31e3fc 100644 --- a/controllers/front/subscriptions.php +++ b/controllers/front/subscriptions.php @@ -10,7 +10,7 @@ * @codingStandardsIgnoreStart */ -use Mollie\Repository\MolCustomerRepository; +use Mollie\Repository\MolCustomerRepositoryInterface; use Mollie\Subscription\Presenter\RecurringOrdersPresenter; /* @@ -52,40 +52,29 @@ class mollieSubscriptionsModuleFrontController extends ModuleFrontController */ public $display_column_left; - /** - * @throws PrestaShopException - */ public function initContent() { $this->display_column_right = false; $this->display_column_left = false; - $context = Context::getContext(); - if (empty($context->customer->id)) { + + if (empty($this->context->customer->id)) { Tools::redirect('index.php'); } - /** @var MolCustomerRepository $molCustomerRepository */ - $molCustomerRepository = $this->module->getService(MolCustomerRepository::class); + /** @var MolCustomerRepositoryInterface $molCustomerRepository */ + $molCustomerRepository = $this->module->getService(MolCustomerRepositoryInterface::class); /** @var RecurringOrdersPresenter $recurringOrdersPresenter */ $recurringOrdersPresenter = $this->module->getService(RecurringOrdersPresenter::class); - $molCustomer = $molCustomerRepository->findOneBy(['email' => $context->customer->email]); - - $recurringOrdersPresentData = []; - if ($molCustomer) { - $recurringOrdersPresentData = $recurringOrdersPresenter->present($molCustomer->customer_id); - } - - parent::initContent(); - - $this->context->smarty->assign([ - 'recurringOrdersData' => $recurringOrdersPresentData, + /** @var ?\MolCustomer $molCustomer */ + $molCustomer = $molCustomerRepository->findOneBy([ + 'email' => $this->context->customer->email, ]); - $this->context->smarty->tpl_vars['page']->value['body_classes']['page-customer-account'] = true; - - $this->setTemplate('module:mollie/views/templates/front/subscription/customerSubscriptionsData.tpl'); + $this->prepareTemplate( + $molCustomer ? $recurringOrdersPresenter->present($molCustomer->customer_id) : [] + ); } public function setMedia() @@ -97,4 +86,17 @@ public function setMedia() $this->context->controller->addJS($js_path . 'front.js'); $this->context->controller->addCSS($css_path . 'customerPersonalData.css'); } + + private function prepareTemplate(array $recurringOrdersPresentData = []): void + { + parent::initContent(); + + $this->context->smarty->assign([ + 'recurringOrdersData' => $recurringOrdersPresentData, + ]); + + $this->context->smarty->tpl_vars['page']->value['body_classes']['page-customer-account'] = true; + + $this->setTemplate('module:mollie/views/templates/front/subscription/customerSubscriptionsData.tpl'); + } } diff --git a/mails/en/mollie_subscription_cancel.html b/mails/en/mollie_subscription_cancel.html index 73517e93e..0922507b0 100644 --- a/mails/en/mollie_subscription_cancel.html +++ b/mails/en/mollie_subscription_cancel.html @@ -576,7 +576,7 @@ > -