274 lines
7.2 KiB
PHP
274 lines
7.2 KiB
PHP
<?php
|
|
|
|
namespace KupShop\KupShopBundle\Context;
|
|
|
|
use KupShop\KupShopBundle\Exception\InvalidArgumentException;
|
|
use KupShop\KupShopBundle\Util\Contexts;
|
|
use KupShop\PricelistBundle\Context\PricelistContext;
|
|
use KupShop\SellerBundle\Context\SellerContext;
|
|
|
|
class ContextManager
|
|
{
|
|
public const CLEAR_CACHE = null;
|
|
public const FORCE_EMPTY = 'FORCE_EMPTY';
|
|
|
|
public function __construct()
|
|
{
|
|
}
|
|
|
|
/**
|
|
* @template T
|
|
*
|
|
* @param callable(): T $callback
|
|
*
|
|
* @return T
|
|
*
|
|
* @throws InvalidArgumentException
|
|
*/
|
|
public function activateSite(int $siteId, callable $callback): mixed
|
|
{
|
|
return $this->activateContexts($this->getActivateSiteContexts($siteId), $callback);
|
|
}
|
|
|
|
/**
|
|
* @template T
|
|
*
|
|
* @param callable(): T $callback
|
|
*
|
|
* @return T
|
|
*
|
|
* @throws InvalidArgumentException
|
|
*/
|
|
public function activateOrder(\OrderBase $order, callable $callback)
|
|
{
|
|
return $this->activateContexts($this->getActivateOrderContexts($order), $callback);
|
|
}
|
|
|
|
/**
|
|
* @template T
|
|
*
|
|
* @param callable(): T $callback
|
|
*
|
|
* @return T
|
|
*
|
|
* @throws InvalidArgumentException
|
|
*/
|
|
public function activateUser(\User $user, callable $callback): mixed
|
|
{
|
|
return $this->activateContexts($this->getActivateUserContexts($user), $callback);
|
|
}
|
|
|
|
/**
|
|
* @template T
|
|
*
|
|
* @param callable(): T $callback
|
|
*
|
|
* @return T
|
|
*
|
|
* @throws InvalidArgumentException
|
|
*/
|
|
public function deactivateUser(callable $callback): mixed
|
|
{
|
|
return $this->activateContexts($this->getDeactivateUserContexts(), $callback);
|
|
}
|
|
|
|
/**
|
|
* @template T
|
|
*
|
|
* @param callable(): T $callback
|
|
*
|
|
* @return T
|
|
*
|
|
* @throws InvalidArgumentException
|
|
*/
|
|
public function activateContexts(array $contexts, callable $callback)
|
|
{
|
|
$originalValues = [];
|
|
|
|
foreach ($contexts as $class => $id) {
|
|
$context = null;
|
|
// e.g. if context is in a bundle that is not activated
|
|
try {
|
|
$context = Contexts::get($class);
|
|
} catch (\Throwable $e) {
|
|
if (isDevelopment()) {
|
|
throw new InvalidArgumentException("Tohle by se nemělo stát, {$class} neexistuje!", previous: $e);
|
|
}
|
|
}
|
|
|
|
if ($context === null) {
|
|
continue;
|
|
}
|
|
|
|
if (!($context instanceof ContextInterface)) {
|
|
throw new InvalidArgumentException("Invalid context class: {$class} is not a ContextInterface.");
|
|
}
|
|
|
|
$originalValues[$class] = $this->getOriginalContextValue($context);
|
|
|
|
switch ($id) {
|
|
case self::CLEAR_CACHE:
|
|
$context->clearCache();
|
|
break;
|
|
|
|
case self::FORCE_EMPTY:
|
|
if (!($context instanceof EmptiableContext)) {
|
|
throw new InvalidArgumentException("{$context} is not Emptiable, but FORCE_EMPTY was passed in!");
|
|
}
|
|
|
|
$context->forceEmpty();
|
|
break;
|
|
|
|
default:
|
|
$context->activate($id);
|
|
}
|
|
}
|
|
|
|
$result = $callback();
|
|
|
|
// restore original values
|
|
foreach ($originalValues as $class => $value) {
|
|
$context = Contexts::get($class);
|
|
|
|
switch ($value) {
|
|
case self::CLEAR_CACHE:
|
|
$context->clearCache();
|
|
break;
|
|
|
|
case self::FORCE_EMPTY:
|
|
$context->forceEmpty();
|
|
break;
|
|
|
|
default:
|
|
$context->activate($value);
|
|
}
|
|
}
|
|
|
|
return $result;
|
|
}
|
|
|
|
protected function getOriginalContextValue(ContextInterface $context): mixed
|
|
{
|
|
$id = $context instanceof UserContext ? $context->getActive() : $context->getActiveId();
|
|
|
|
if ($id === null && $context instanceof EmptiableContext && $context->isEmpty()) {
|
|
$id = self::FORCE_EMPTY;
|
|
}
|
|
|
|
return $id;
|
|
}
|
|
|
|
public function getDomainFromLanguage($language)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
protected function getActivateUserContexts(\User $user): array
|
|
{
|
|
$contexts = [
|
|
UserContext::class => $user,
|
|
VatContext::class => self::CLEAR_CACHE,
|
|
];
|
|
|
|
if (findModule(\Modules::PRICE_LEVELS)) {
|
|
$contexts[PriceLevelContext::class] = self::CLEAR_CACHE;
|
|
}
|
|
|
|
if (findModule(\Modules::PRICELISTS)) {
|
|
$contexts[PricelistContext::class] = self::CLEAR_CACHE;
|
|
}
|
|
|
|
return $contexts;
|
|
}
|
|
|
|
protected function getActivateOrderContexts(\OrderBase $order): array
|
|
{
|
|
$contexts = [
|
|
UserContext::class => $order->getUser() ?? self::FORCE_EMPTY,
|
|
VatContext::class => self::CLEAR_CACHE,
|
|
];
|
|
|
|
if (findModule(\Modules::PRICE_LEVELS)) {
|
|
$contexts[PriceLevelContext::class] = self::CLEAR_CACHE;
|
|
}
|
|
|
|
if (findModule(\Modules::PRICELISTS)) {
|
|
$contexts[PricelistContext::class] = self::CLEAR_CACHE;
|
|
}
|
|
|
|
return $contexts;
|
|
}
|
|
|
|
protected function getActivateSiteContexts(int $siteId): array
|
|
{
|
|
$site = Contexts::get(SiteContext::class)->getSupported()[$siteId] ?? null;
|
|
|
|
return [
|
|
SiteContext::class => $siteId,
|
|
DomainContext::class => $site?->getDomain(),
|
|
LanguageContext::class => $site?->getLanguage(),
|
|
CurrencyContext::class => self::CLEAR_CACHE,
|
|
CountryContext::class => self::CLEAR_CACHE,
|
|
VatContext::class => self::CLEAR_CACHE,
|
|
];
|
|
}
|
|
|
|
protected function getDeactivateUserContexts(): array
|
|
{
|
|
$contexts = [
|
|
UserContext::class => self::FORCE_EMPTY,
|
|
];
|
|
|
|
if (findModule(\Modules::PRICE_LEVELS)) {
|
|
$contexts[PriceLevelContext::class] = self::CLEAR_CACHE;
|
|
}
|
|
|
|
if (findModule(\Modules::PRICELISTS)) {
|
|
$contexts[PricelistContext::class] = self::CLEAR_CACHE;
|
|
}
|
|
|
|
if (findModule(\Modules::SELLERS)) {
|
|
$contexts[SellerContext::class] = self::FORCE_EMPTY;
|
|
}
|
|
|
|
return $contexts;
|
|
}
|
|
|
|
protected function getEmptiableContexts(): array
|
|
{
|
|
$contexts = [UserContext::class];
|
|
|
|
if (findModule(\Modules::PRICE_LEVELS)) {
|
|
$contexts[] = PriceLevelContext::class;
|
|
}
|
|
if (findModule(\Modules::PRICELISTS)) {
|
|
$contexts[] = PricelistContext::class;
|
|
}
|
|
if (findModule(\Modules::SELLERS)) {
|
|
$contexts[] = SellerContext::class;
|
|
}
|
|
|
|
return $contexts;
|
|
}
|
|
|
|
public function forceEmptyContexts(): void
|
|
{
|
|
foreach ($this->getEmptiableContexts() as $context) {
|
|
Contexts::get($context)->forceEmpty();
|
|
}
|
|
}
|
|
|
|
public function checkEmptyContextsLeak(): array
|
|
{
|
|
$leaks = [];
|
|
|
|
foreach ($this->getEmptiableContexts() as $context) {
|
|
if (!Contexts::get($context)->isEmpty()) {
|
|
$leaks[$context] = Contexts::get($context);
|
|
}
|
|
}
|
|
|
|
return $leaks;
|
|
}
|
|
}
|