<?php
/**
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*
* @package LnbSubscription
* @author Michael Lämmlein <michael.laemmlein@liebscher-bracht.com>
* @copyright ©2022 Liebscher & Bracht
* @license http://www.opensource.org/licenses/mit-license.php MIT-License
* @version 1.0.0
* @since 04.03.22
*/
declare(strict_types=1);
namespace Lnb\Shopware6\LnbSubscription\Subscriber\Subscription;
use Lnb\Shopware6\LnbSubscription\Entity\SubscriptionOrder\SubscriptionOrderEntity;
use Lnb\Shopware6\LnbSubscription\Event\SubscriptionCreatedEvent;
use Shopware\Core\Checkout\Cart\Price\Struct\CalculatedPrice;
use Shopware\Core\Checkout\Cart\Tax\Struct\CalculatedTaxCollection;
use Shopware\Core\Checkout\Cart\Tax\Struct\TaxRuleCollection;
use Shopware\Core\Checkout\Order\Aggregate\OrderLineItem\OrderLineItemEntity;
use Shopware\Core\Content\Product\ProductEntity;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\DataAbstractionLayer\EntityRepository;
use Shopware\Core\Framework\DataAbstractionLayer\Search\Criteria;
use Shopware\Core\Framework\Event\ShopwareEvent;
use Symfony\Component\DependencyInjection\Attribute\Target;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
class SubscriptionCreatedSubscriber implements EventSubscriberInterface
{
public function __construct(
#[Target('order_line_item.repository')] private readonly EntityRepository $orderLineItemRepository,
#[Target('order.repository')] private readonly EntityRepository $orderRepository,
#[Target('lnb_subscription_order.repository')] private readonly EntityRepository $subscriptionOrderRepository,
#[Target('product.repository')] private readonly EntityRepository $productRepository
) {
}
public static function getSubscribedEvents(): array
{
return [
SubscriptionCreatedEvent::class => [
['addSubscriptionOrderIdToOrderLineItem', 5],
['addSubscriptionOrderIdToOrder', 6],
['updatePriceIfZero', 10]
],
// SubscriptionCreatedFromRequestEvent::class => ['updatePriceIfZero']
];
}
public function addSubscriptionOrderIdToOrderLineItem(SubscriptionCreatedEvent $event): void
{
$criteria = new Criteria([$event->getOrderLineItemId()]);
/** @var OrderLineItemEntity $orderLineItem */
$orderLineItem = $this->orderLineItemRepository->search($criteria, $event->getContext())->first();
$customFields = $orderLineItem->getCustomFields();
$customFields['LnbSubscription']['lnbSubscriptionOrderId'] = $event->getSubscriptionId();
$this->orderLineItemRepository->update([[
'id' => $orderLineItem->getId(),
'customFields' => $customFields,
]], $event->getContext());
}
public function addSubscriptionOrderIdToOrder(SubscriptionCreatedEvent $event): void
{
$criteria = new Criteria([$event->getOrderLineItemId()]);
$criteria->addAssociation('order');
/** @var OrderLineItemEntity $orderLineItem */
$orderLineItem = $this->orderLineItemRepository->search($criteria, $event->getContext())->first();
$customFields = $orderLineItem->getOrder()->getCustomFields();
$customFields['LnbSubscription']['lnbSubscriptionOrderId'] = $event->getSubscriptionId();
// new field for Ids because lnbSubscriptionOrderId always gets overwritten by the last subscription id, and we want to catch all ids
if (!isset($customFields['LnbSubscription']['lnbSubscriptionOrderIds']) || !in_array($event->getSubscriptionId(), $customFields['LnbSubscription']['lnbSubscriptionOrderIds'])) {
$customFields['LnbSubscription']['lnbSubscriptionOrderIds'][] = $event->getSubscriptionId();
}
$this->orderRepository->upsert([[
'id' => $orderLineItem->getOrderId(),
'customFields' => $customFields,
'lnbSubscriptions' => [
[
'id' => $event->getSubscriptionId(),
]
],
]], $event->getContext());
}
public function updatePriceIfZero(ShopwareEvent $event): void
{
$subscriptionOrder = $this->getSubscriptionOrder($event->getSubscriptionId(), $event->getContext());
if (0 < $subscriptionOrder->getPrice()->getUnitPrice()) {
return;
}
$product = $this->getProduct($subscriptionOrder->getProductId(), $event->getContext());
$newPrice = $product->getCurrencyPrice($event->getContext()->getCurrencyId())->getNet();
$quantity = $subscriptionOrder->getQuantity();
$calculatedPrice = new CalculatedPrice(
$newPrice,
$newPrice * $quantity,
new CalculatedTaxCollection(),
new TaxRuleCollection(),
$quantity
);
$this->subscriptionOrderRepository->update([[
'id' => $event->getSubscriptionId(),
'price' => $calculatedPrice,
]], $event->getContext());
}
private function getSubscriptionOrder(string $subscriptionOrderId, Context $context): SubscriptionOrderEntity
{
$criteria = new Criteria([$subscriptionOrderId]);
$result = $this->subscriptionOrderRepository->search($criteria, $context);
$entity = $result->first();
if (!$entity) {
throw new \Exception('no subscription order found');
}
return $entity;
}
private function getProduct(string $productId, Context $context): ProductEntity
{
$criteria = new Criteria([$productId]);
$result = $this->productRepository->search($criteria, $context);
/** @var ?ProductEntity $entity */
$entity = $result->first();
if (!$entity) {
throw new \Exception('no product found');
}
return $entity;
}
}