commercetools-8.x-1.2-alpha1/src/EventSubscriber/CommercetoolsGraphQlOperationTokensSubscriber.php
src/EventSubscriber/CommercetoolsGraphQlOperationTokensSubscriber.php
<?php
declare(strict_types=1);
namespace Drupal\commercetools\EventSubscriber;
use Drupal\commercetools\Event\CommercetoolsGraphQlOperationEvent;
use Drupal\Component\DependencyInjection\ContainerInterface;
use Drupal\Component\Utility\NestedArray;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Replace tokens in the variable array on values.
*/
class CommercetoolsGraphQlOperationTokensSubscriber implements EventSubscriberInterface {
/**
* Dummy cart id.
*
* Non-existent ID to prevent the cart request from failing
* if the user doesn't have a cart yet.
*/
const DUMMY_CART_ID = '00000000-0000-0000-0000-000000000000';
/**
* Contains already used context.
*
* @var array
*/
protected array $context;
/**
* CommercetoolsGraphQlOperationTokensSubscriber constructor.
*
* @param \Symfony\Component\DependencyInjection\ContainerInterface|null $container
* The service container.
*/
public function __construct(
protected ContainerInterface $container,
) {
}
/**
* Before GraphQl execution event handler.
*/
public function onExecute(CommercetoolsGraphQlOperationEvent $event): void {
$variables = &$event->variables;
if (!empty($variables)) {
$variables = $this->parseVariables($variables);
}
}
/**
* Replace tokens in the variable array on token values.
*
* @param array $variables
* An array of the request variables.
*/
protected function parseVariables(array $variables): array {
foreach ($variables as &$variable) {
if (is_array($variable)) {
$variable = $this->parseVariables($variable);
}
elseif (is_string($variable)) {
$variable = $this->replaceTokens($variable);
}
}
return $variables;
}
/**
* Find token in the string and replace on token value.
*
* @param string $value
* The value to be scanned for possible tokens.
*
* @return mixed
* Value with the replaced token.
*/
protected function replaceTokens(string $value): mixed {
if (preg_match('/\[([^\s\[\]:]+):([^\[\]]+)\]/x', $value, $matches)) {
$tokenValue = $this->getTokenValue($matches[1], explode(':', $matches[2])) ?? $matches[0];
return $matches[0] === $value ? $tokenValue : str_replace($matches[0], $tokenValue, $value);
}
return $value;
}
/**
* Get a token value from the context object.
*
* @param string $contextName
* The context name.
* @param array $fields
* The hierarchy of object fields.
*
* @return mixed
* Token value.
*/
protected function getTokenValue(string $contextName, array $fields): mixed {
if (empty($this->context[$contextName])) {
switch ($contextName) {
case 'current_cart':
$currentCart = $this->container->get('commercetools.carts')->getCurrentCart();
$this->context[$contextName] = isset($currentCart) && $currentCart->getData()
? $currentCart->getData()
: ['id' => self::DUMMY_CART_ID];
break;
case 'current_cart_or_create':
$ctCarts = $this->container->get('commercetools.carts');
$currentCart = $ctCarts->getCurrentCart();
$this->context[$contextName] = isset($currentCart) && $currentCart->getData()
? $currentCart->getData()
: $ctCarts->createCart()->getData();
$ctCarts->setCurrentCart($this->context[$contextName]);
break;
case 'current_customer':
$ctCustomers = $this->container->get('commercetools.customers');
$this->context[$contextName] = $ctCustomers->getCustomerByUser();
break;
case 'order_number':
$ctCarts = $this->container->get('commercetools.carts');
return $ctCarts->generateOrderNumber();
default:
return NULL;
}
}
return NestedArray::getValue($this->context[$contextName], $fields);
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents(): array {
return [
CommercetoolsGraphQlOperationEvent::class => ['onExecute', 100],
];
}
}
