<?php declare(strict_types=1);
namespace Virgin\PaymentPlugin;
use Doctrine\DBAL\Connection;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepositoryInterface;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsAnyFilter;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Filter\EqualsFilter;
use Shopware\Core\Framework\Plugin;
use Shopware\Core\Framework\Plugin\Context\ActivateContext;
use Shopware\Core\Framework\Plugin\Context\DeactivateContext;
use Shopware\Core\Framework\Plugin\Context\InstallContext;
use Shopware\Core\Framework\Plugin\Context\UninstallContext;
use Shopware\Core\Framework\Plugin\Context\UpdateContext;
use Shopware\Core\Framework\Plugin\Util\PluginIdProvider;
use Shopware\Core\System\CustomField\CustomFieldTypes;
use Virgin\PaymentPlugin\Service\ClubPaymentHandler;
use Virgin\PaymentPlugin\Service\DirectDebitPaymentHandler;
use Virgin\PaymentPlugin\Service\NewPaymentAgreementHandler;
use Virgin\PaymentPlugin\Service\NexiExternalLinkPaymentHandler;
use Virgin\PaymentPlugin\Service\NexiPaymentHandler;
use Virgin\PaymentPlugin\Service\SuperPromoPaymentHandler;
/**
* Class PaymentPlugin
* @package Virgin\PaymentPlugin
*/
class PaymentPlugin extends Plugin
{
const CLUB_PAYMENT_TYPE = 1;
const DIRECT_DEBIT_PAYMENT_TYPE = 2;
const NEXY_PAYMENT_TYPE = 3;
const SUPER_PROMO_PAYMENT_TYPE = 4;
const NEXY_PAYMENT_TYPE_EXTERNAL = 5;
const NEW_PAYMENT_AGREEMENT_TYPE = 6;
public function install(InstallContext $context): void
{
$paymentFields =
[
[
'name' => 'payment_type',
'type' => CustomFieldTypes::INT,
'config' => [
'componentName' => 'sw-field',
'type' => 'number',
'numbertype'=> 'int',
'customFieldType' => "number",
'customFieldPosition' => 1,
'label' => [
'en-GB' => 'payment type identifier',
],
],
],
];
$this->addPaymentCustomFields($paymentFields);
$this->addPaymentMethod($context->getContext());
}
public function uninstall(UninstallContext $context): void
{
// Only set the payment method to inactive when uninstalling. Removing the payment method would
// cause data consistency issues, since the payment method might have been used in several orders
$this->setPaymentMethodIsActive(false, $context->getContext());
}
public function activate(ActivateContext $context): void
{
$this->setPaymentMethodIsActive(true, $context->getContext());
parent::activate($context);
}
public function deactivate(DeactivateContext $context): void
{
$this->setPaymentMethodIsActive(false, $context->getContext());
parent::deactivate($context);
}
public function update(UpdateContext $context): void
{
$orderFields = [
[
'name' => 'payment_agreement_reference',
'type' => CustomFieldTypes::TEXT,
'config' => [
'componentName' => 'sw-field',
'type' => 'text',
'customFieldType' => 'text',
'customFieldPosition' => 1,
'label' => [
'en-GB' => 'Payment Agreement Reference',
],
],
]
];
$this->addOrderCustomFields($orderFields, 'payment_option', 'Payment option');
$paymentMethodExists = $this->getPaymentMethods();
/** @var PluginIdProvider $pluginIdProvider */
$pluginIdProvider = $this->container->get(PluginIdProvider::class);
$pluginId = $pluginIdProvider->getPluginIdByBaseClass(get_class($this), $context->getContext());
$connection = $this->container->get(Connection::class);
$builder = $connection->createQueryBuilder();
$salesChannelsId = $builder->select(['LOWER(HEX(sct.sales_channel_id ))'])
->from('sales_channel_translation sct')
->where('sct.name = :name')
->setParameter('name', "Virgin Active")
->execute()
->fetch(\PDO::FETCH_COLUMN);
$newPaymentMethods = [
[
// payment handler will be selected by the identifier
'handlerIdentifier' => NewPaymentAgreementHandler::class,
'name' => 'Accordo di pagamento precedente',
'description' => 'Accordo di pagamento',
'pluginId' => $pluginId,
'salesChannels' => [
['id' => strtolower($salesChannelsId)]
],
'active'=>true,
'customFields' => [
'payment_type' => self::NEW_PAYMENT_AGREEMENT_TYPE
],
]
];
/** @var EntityRepositoryInterface $paymentRepository */
$paymentRepository = $this->container->get('payment_method.repository');
foreach ($newPaymentMethods as $newPaymentMethod){
if ($paymentMethodExists) {
if (in_array($newPaymentMethod['handlerIdentifier'], $paymentMethodExists)){
continue;
}
else{
$paymentRepository->create([$newPaymentMethod], $context->getContext());
}
}else{
$paymentRepository->create([$newPaymentMethod], $context->getContext());
}
}
}
private function addPaymentMethod(Context $context): void
{
$paymentMethodExists = $this->getPaymentMethods();
/** @var PluginIdProvider $pluginIdProvider */
$pluginIdProvider = $this->container->get(PluginIdProvider::class);
$pluginId = $pluginIdProvider->getPluginIdByBaseClass(get_class($this), $context);
$connection = $this->container->get(Connection::class);
$builder = $connection->createQueryBuilder();
$salesChannelsId = $builder->select(['LOWER(HEX(sct.sales_channel_id ))'])
->from('sales_channel_translation sct')
->where('sct.name = :name')
->setParameter('name', "Virgin Active")
->execute()
->fetch(\PDO::FETCH_COLUMN);
$newPaymentMethods = [
[
// payment handler will be selected by the identifier
'handlerIdentifier' => ClubPaymentHandler::class,
'name' => 'Pagamento al club',
'description' => 'Pay at the club',
'pluginId' => $pluginId,
'salesChannels' => [
['id' => strtolower($salesChannelsId)]
],
'active'=>true,
'customFields' => [
'payment_type' => self::CLUB_PAYMENT_TYPE
],
],
[
// payment handler will be selected by the identifier
'handlerIdentifier' => DirectDebitPaymentHandler::class,
'name' => 'Addebito diretto',
'description' => 'Direct debit',
'pluginId' => $pluginId,
'salesChannels' => [
['id' => strtolower($salesChannelsId)]
],
'active'=>true,
'customFields' => [
'payment_type' => self::DIRECT_DEBIT_PAYMENT_TYPE
],
],
[
// payment handler will be selected by the identifier
'handlerIdentifier' => NexiPaymentHandler::class,
'name' => 'Pagamento Nexi',
'description' => 'Nexi payment',
'pluginId' => $pluginId,
'salesChannels' => [
['id' => strtolower($salesChannelsId)]
],
'active'=>true,
'customFields' => [
'payment_type' => self::NEXY_PAYMENT_TYPE
],
],
[
// payment handler will be selected by the identifier
'handlerIdentifier' => SuperPromoPaymentHandler::class,
'name' => 'Super promo pagamento',
'description' => 'Super promo payment',
'pluginId' => $pluginId,
'salesChannels' => [
['id' => strtolower($salesChannelsId)]
],
'active'=>false,
'customFields' => [
'payment_type' => self::SUPER_PROMO_PAYMENT_TYPE
],
],
[
// payment handler will be selected by the identifier
'handlerIdentifier' => NexiExternalLinkPaymentHandler::class,
'name' => 'Pagamento Nexi Link',
'description' => 'Pagamento nexi tramite link',
'pluginId' => $pluginId,
'salesChannels' => [
['id' => strtolower($salesChannelsId)]
],
'active'=>true,
'customFields' => [
'payment_type' => self::NEXY_PAYMENT_TYPE_EXTERNAL
],
]
];
/** @var EntityRepositoryInterface $paymentRepository */
$paymentRepository = $this->container->get('payment_method.repository');
foreach ($newPaymentMethods as $newPaymentMethod){
if ($paymentMethodExists) {
if (in_array($newPaymentMethod['handlerIdentifier'], $paymentMethodExists)){
continue;
}
else{
$paymentRepository->create([$newPaymentMethod], $context);
}
}else{
$paymentRepository->create([$newPaymentMethod], $context);
}
}
}
private function setPaymentMethodIsActive(bool $active, Context $context): void
{
/** @var EntityRepositoryInterface $paymentRepository */
$paymentRepository = $this->container->get('payment_method.repository');
$paymentMethods = $this->getPaymentMethods();
// Payment does not even exist, so nothing to (de-)activate here
if (!$paymentMethods) {
return;
}
foreach ($paymentMethods as $paymentMethod){
$paymentCriteria = (new Criteria())->addFilter(new EqualsFilter('handlerIdentifier', $paymentMethod));
$paymentId = $paymentRepository->searchIds($paymentCriteria, Context::createDefaultContext());
$paymentMethod = [
'id' => $paymentId->getIds()[0],
'active' => $active,
];
$paymentRepository->update([$paymentMethod], $context);
}
}
private function getPaymentMethods(): ?array
{
/** @var EntityRepositoryInterface $paymentRepository */
$paymentRepository = $this->container->get('payment_method.repository');
// Fetch ID for update
$paymentCriteria = (new Criteria())->addFilter(new EqualsAnyFilter('handlerIdentifier', [ClubPaymentHandler::class, NexiPaymentHandler::class, DirectDebitPaymentHandler::class, SuperPromoPaymentHandler::class, NexiExternalLinkPaymentHandler::class]));
$payments = $paymentRepository->search($paymentCriteria, Context::createDefaultContext())->getElements();
if (empty($payments)) {
return null;
}
$paymentIdentifiers = [];
foreach ($payments as $payment){
array_push($paymentIdentifiers, $payment->getHandlerIdentifier());
}
return $paymentIdentifiers;
}
private function addPaymentCustomFields($paymentFields)
{
/** @var $customFieldSetRepository */
$customFieldSetRepository = $this->container->get('custom_field_set.repository');
$customFieldRepository = $this->container->get('custom_field.repository');
$context = Context::createDefaultContext();
foreach ($paymentFields as $paymentField) {
$criteria = new Criteria();
$criteria->addFilter(
new EqualsFilter('custom_field.name', $paymentField['name'])
);
$fieldId = $customFieldRepository->searchIds($criteria, $context)->firstId();
if ($fieldId == null) {
$createCustomFields[] = $paymentField;
}
}
if (!empty($createCustomFields)) {
$customFieldSetRepository->create([
[
'name' => 'payment_type',
'customFields' => $createCustomFields,
'config' => [
'label' => [
'en-GB' => 'Payment type',
],
],
'relations' => [
['entityName' => 'payment_method'],
],
],
], $context);
}
}
private function addOrderCustomFields($newOrderCustomFields, $setName, $label)
{
/** @var EntityRepositoryInterface $customFieldSetRepository */
$customFieldSetRepository = $this->container->get('custom_field_set.repository');
$customFieldRepository = $this->container->get('custom_field.repository');
$context = Context::createDefaultContext();
foreach ($newOrderCustomFields as $newOrderCustomField) {
$criteria = new Criteria();
$criteria->addFilter(
new EqualsFilter('custom_field.name', $newOrderCustomField['name'])
);
$fieldId = $customFieldRepository->searchIds($criteria, $context)->firstId();
if ($fieldId == null) {
$createCustomFields[] = $newOrderCustomField;
}
}
$criteria = new Criteria();
$criteria->addFilter(
new EqualsFilter('name', $setName)
);
$customFieldSetId = $customFieldSetRepository->searchIds($criteria, $context)->firstId();
if (!empty($createCustomFields)) {
if (null == $customFieldSetId) {
$customFieldSetRepository->create([
[
'name' => $setName,
'customFields' => $createCustomFields,
'config' => [
'label' => [
'en-GB' => $label,
],
],
'relations' => [
['entityName' => 'order'],
],
],
], $context);
} else {
$customFieldSetRepository->update(
[
[
'id' => $customFieldSetId,
'customFields' => $createCustomFields
]
], $context);
}
}
}
}