<?php declare(strict_types=1);
namespace Acris\Stock;
use Doctrine\DBAL\Connection;
use Shopware\Core\Checkout\Cart\LineItem\LineItem;
use Shopware\Core\Checkout\Order\OrderStates;
use Shopware\Core\Framework\Context;
use Shopware\Core\Framework\Plugin;
use Shopware\Core\Framework\Plugin\Context\ActivateContext;
use Shopware\Core\Framework\Plugin\Context\DeactivateContext;
use Shopware\Core\Framework\Plugin\KernelPluginLoader\KernelPluginLoader;
use Shopware\Core\Framework\Plugin\KernelPluginLoader\StaticKernelPluginLoader;
use Shopware\Core\Framework\Uuid\Uuid;
use Symfony\Component\HttpKernel\Kernel;
class AcrisStockCS extends Plugin
{
public function activate(ActivateContext $activateContext): void
{
$this->putClassesToContainer();
$products = $this->getAffectedProductIds($activateContext->getContext());
$stockUpdater = $this->container->get('Acris\Stock\Core\Content\Product\DataAbstractionLayer\StockUpdater');
$stockUpdater->decreaseStockOnActivation($products, $activateContext->getContext());
}
public function deactivate(DeactivateContext $deactivateContext): void
{
$products = $this->getAffectedProductIds($deactivateContext->getContext());
$stockUpdater = $this->container->get('Acris\Stock\Core\Content\Product\DataAbstractionLayer\StockUpdater');
$stockUpdater->increaseStockOnDeactivation($products, $deactivateContext->getContext());
}
private function getAffectedProductIds(Context $context): array {
$connection = $this->container->get(Connection::class);
$sql = '
SELECT LOWER(HEX(order_line_item.product_id)) as referenced_id, order_line_item.quantity as quantity
FROM order_line_item
INNER JOIN `order`
ON `order`.id = order_line_item.order_id
AND `order`.version_id = order_line_item.order_version_id
INNER JOIN state_machine_state
ON state_machine_state.id = `order`.state_id
AND (state_machine_state.technical_name = :progress_state)
WHERE order_line_item.type = :type
AND order_line_item.version_id = :version
AND order_line_item.product_id IS NOT NULL
GROUP BY referenced_id;
';
$rows = $connection->fetchAllAssociative(
$sql,
[
'type' => LineItem::PRODUCT_LINE_ITEM_TYPE,
'version' => Uuid::fromHexToBytes($context->getVersionId()),
'progress_state' => OrderStates::STATE_IN_PROGRESS
]
);
return $rows;
}
private function putClassesToContainer(): void
{
/** @var Kernel $kernel */
$kernel = $this->container->get('kernel');
/** @var KernelPluginLoader $pluginLoader */
$pluginLoader = $this->container->get(KernelPluginLoader::class);
//get all plugins and mark the current plugin as active, so that its classes get added to the container
$plugins = $pluginLoader->getPluginInfos();
foreach ($plugins as $i => $pluginData) {
if ($pluginData['name'] === $this->getName()) {
$plugins[$i]['active'] = 1;
}
}
//load all plugins
$tmpStaticPluginLoader = new StaticKernelPluginLoader(
$pluginLoader->getClassLoader(),
$kernel->getContainer()->getParameter('kernel.plugin_dir'),
$plugins
);
//reboot kernel to apply the changes to the container
$kernel->reboot(null, $tmpStaticPluginLoader);
//handle an exception, when calling getContainer on a not booted kernel
/** @var \Symfony\Component\DependencyInjection\ContainerInterface|null $newContainer */
$newContainer = $kernel->getContainer();
if (!$newContainer) {
throw new \RuntimeException('Failed to reboot the kernel');
}
$this->container = $newContainer;
}
}