Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions config/services.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ services:
Mollie\Subscription\Grid\Accessibility\SubscriptionCancelAccessibility:
class: Mollie\Subscription\Grid\Accessibility\SubscriptionCancelAccessibility

Mollie\Subscription\Provider\SubscriptionAvailabilityProvider:
class: Mollie\Subscription\Provider\SubscriptionAvailabilityProvider

carrier_options_provider:
class: Mollie\Subscription\Form\ChoiceProvider\CarrierOptionsProvider
public: true
Expand Down
45 changes: 33 additions & 12 deletions controllers/front/subscriptions.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
use Mollie\Logger\LoggerInterface;
use Mollie\Repository\MolCustomerRepositoryInterface;
use Mollie\Subscription\Presenter\RecurringOrdersPresenter;
use Mollie\Subscription\Provider\SubscriptionAvailabilityProvider;
use Mollie\Utility\ExceptionUtility;

/*
* 2007-2020 PrestaShop and Contributors
Expand Down Expand Up @@ -70,22 +72,41 @@ public function initContent()
Tools::redirect('index.php');
}

/** @var MolCustomerRepositoryInterface $molCustomerRepository */
$molCustomerRepository = $this->module->getService(MolCustomerRepositoryInterface::class);
try {
/** @var SubscriptionAvailabilityProvider $subscriptionAvailabilityProvider */
$subscriptionAvailabilityProvider = $this->module->getService(SubscriptionAvailabilityProvider::class);

/** @var RecurringOrdersPresenter $recurringOrdersPresenter */
$recurringOrdersPresenter = $this->module->getService(RecurringOrdersPresenter::class);
if (!$subscriptionAvailabilityProvider->isAvailableForCustomer($this->context->customer->email)) {
$logger->debug(sprintf('%s - Subscriptions not available for customer', self::FILE_NAME));
$this->prepareTemplate([]);

/** @var ?\MolCustomer $molCustomer */
$molCustomer = $molCustomerRepository->findOneBy([
'email' => $this->context->customer->email,
]);
return;
}

/** @var MolCustomerRepositoryInterface $molCustomerRepository */
$molCustomerRepository = $this->module->getService(MolCustomerRepositoryInterface::class);

/** @var RecurringOrdersPresenter $recurringOrdersPresenter */
$recurringOrdersPresenter = $this->module->getService(RecurringOrdersPresenter::class);

$this->prepareTemplate(
$molCustomer ? $recurringOrdersPresenter->present($molCustomer->customer_id) : []
);
/** @var ?\MolCustomer $molCustomer */
$molCustomer = $molCustomerRepository->findOneBy([
'email' => $this->context->customer->email,
]);

$logger->debug(sprintf('%s - Controller action ended', self::FILE_NAME));
$this->prepareTemplate(
$molCustomer ? $recurringOrdersPresenter->present($molCustomer->customer_id) : []
);

$logger->debug(sprintf('%s - Controller action ended', self::FILE_NAME));
} catch (\Throwable $exception) {
$logger->error(sprintf('%s - Error in subscriptions controller', self::FILE_NAME), [
'exceptions' => ExceptionUtility::getExceptions($exception),
]);

// Fail safely - show empty template if there's an error
$this->prepareTemplate([]);
}
}

public function setMedia()
Expand Down
37 changes: 29 additions & 8 deletions mollie.php
Original file line number Diff line number Diff line change
Expand Up @@ -1255,17 +1255,38 @@ public function hookActionCartUpdateQuantityBefore($params): void
*/
public function hookDisplayCustomerAccount()
{
$context = Context::getContext();
$id_customer = $context->customer->id;
try {
$context = Context::getContext();

$url = Context::getContext()->link->getModuleLink($this->name, 'subscriptions', [], true);
if (empty($context->customer->email)) {
return '';
}

$this->context->smarty->assign([
'front_controller' => $url,
'id_customer' => $id_customer,
]);
/** @var \Mollie\Subscription\Provider\SubscriptionAvailabilityProvider $subscriptionAvailabilityProvider */
$subscriptionAvailabilityProvider = $this->getService(\Mollie\Subscription\Provider\SubscriptionAvailabilityProvider::class);

return $this->display(__FILE__, 'views/templates/front/subscription/customerAccount.tpl');
if (!$subscriptionAvailabilityProvider->isAvailableForCustomer($context->customer->email)) {
return '';
}

$url = Context::getContext()->link->getModuleLink($this->name, 'subscriptions', [], true);

$this->context->smarty->assign([
'front_controller' => $url,
'id_customer' => $context->customer->id,
]);

return $this->display(__FILE__, 'views/templates/front/subscription/customerAccount.tpl');
} catch (\Throwable $exception) {
/** @var \Mollie\Logger\LoggerInterface $logger */
$logger = $this->getService(\Mollie\Logger\LoggerInterface::class);
$logger->error('Mollie - Error in hookDisplayCustomerAccount', [
'exceptions' => \Mollie\Utility\ExceptionUtility::getExceptions($exception),
]);

// Fail safely - don't show the tab if there's an error
return '';
}
}

/**
Expand Down
122 changes: 122 additions & 0 deletions subscription/Provider/SubscriptionAvailabilityProvider.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
<?php
/**
* Mollie https://www.mollie.nl
*
* @author Mollie B.V. <info@mollie.nl>
* @copyright Mollie B.V.
* @license https://github.com/mollie/PrestaShop/blob/master/LICENSE.md
*
* @see https://github.com/mollie/PrestaShop
* @codingStandardsIgnoreStart
*/

namespace Mollie\Subscription\Provider;

use Mollie\Adapter\ConfigurationAdapter;
use Mollie\Config\Config;
use Mollie\Logger\LoggerInterface;
use Mollie\Repository\MolCustomerRepositoryInterface;
use Mollie\Subscription\Repository\RecurringOrderRepositoryInterface;
use Mollie\Utility\ExceptionUtility;

if (!defined('_PS_VERSION_')) {
exit;
}

class SubscriptionAvailabilityProvider
{
const FILE_NAME = 'SubscriptionAvailabilityProvider';

/** @var ConfigurationAdapter */
private $configuration;
/** @var MolCustomerRepositoryInterface */
private $molCustomerRepository;
/** @var RecurringOrderRepositoryInterface */
private $recurringOrderRepository;
/** @var LoggerInterface */
private $logger;

public function __construct(
ConfigurationAdapter $configuration,
MolCustomerRepositoryInterface $molCustomerRepository,
RecurringOrderRepositoryInterface $recurringOrderRepository,
LoggerInterface $logger
) {
$this->configuration = $configuration;
$this->molCustomerRepository = $molCustomerRepository;
$this->recurringOrderRepository = $recurringOrderRepository;
$this->logger = $logger;
}

/**
* Check if subscription functionality should be available for a customer
*
* @param string $customerEmail
*
* @return bool Returns true if subscriptions are enabled OR customer has existing subscription orders
* Returns false on any error to fail safely
*/
public function isAvailableForCustomer(string $customerEmail): bool
{
try {
// Validate input
if (empty($customerEmail)) {
return false;
}

$isSubscriptionEnabled = (bool) $this->configuration->get(Config::MOLLIE_SUBSCRIPTION_ENABLED);

// If subscriptions are enabled, always show
if ($isSubscriptionEnabled) {
return true;
}

// If subscriptions are disabled, check if customer has existing subscription orders
return $this->hasExistingSubscriptionOrders($customerEmail);
} catch (\Throwable $exception) {
$this->logger->error(sprintf('%s - Error checking subscription availability', self::FILE_NAME), [
'customer_email' => $customerEmail,
'exceptions' => ExceptionUtility::getExceptions($exception),
]);

// Fail safely - don't show subscription tab if there's an error
return false;
}
}

/**
* Check if customer has existing subscription orders
*
* @param string $customerEmail
*
* @return bool
*
* @throws \PrestaShopException
*/
private function hasExistingSubscriptionOrders(string $customerEmail): bool
{
try {
$molCustomer = $this->molCustomerRepository->findOneBy([
'email' => $customerEmail,
]);

if (!$molCustomer) {
return false;
}

$recurringOrders = $this->recurringOrderRepository->findBy([

Check failure on line 107 in subscription/Provider/SubscriptionAvailabilityProvider.php

View workflow job for this annotation

GitHub Actions / PHPStan (1.7.7.0)

Call to an undefined method Mollie\Subscription\Repository\RecurringOrderRepositoryInterface::findBy().

Check failure on line 107 in subscription/Provider/SubscriptionAvailabilityProvider.php

View workflow job for this annotation

GitHub Actions / PHPStan (1.7.6.8)

Call to an undefined method Mollie\Subscription\Repository\RecurringOrderRepositoryInterface::findBy().
'mol_customer_id' => $molCustomer->customer_id,

Check failure on line 108 in subscription/Provider/SubscriptionAvailabilityProvider.php

View workflow job for this annotation

GitHub Actions / PHPStan (1.7.7.0)

Access to an undefined property ObjectModel::$customer_id.

Check failure on line 108 in subscription/Provider/SubscriptionAvailabilityProvider.php

View workflow job for this annotation

GitHub Actions / PHPStan (1.7.6.8)

Access to an undefined property ObjectModel::$customer_id.
]);

return !empty($recurringOrders);
} catch (\Throwable $exception) {
// Log and re-throw to be caught by parent method
$this->logger->error(sprintf('%s - Error checking existing subscription orders', self::FILE_NAME), [
'customer_email' => $customerEmail,
'exceptions' => ExceptionUtility::getExceptions($exception),
]);

throw $exception;
}
}
}
Loading