commercetools-8.x-1.2-alpha1/src/Controller/SubscriptionsController.php
src/Controller/SubscriptionsController.php
<?php
namespace Drupal\commercetools\Controller;
use Drupal\commercetools\Cache\CacheableCommercetoolsGraphQlResponse;
use Drupal\commercetools\Form\SubscriptionSettingsForm;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Controller\ControllerBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
/**
* Webhook endpoint for subscription events and cache invalidation.
*/
class SubscriptionsController extends ControllerBase {
const SUBSCRIPTION_CHANGES = [
'product' => [CacheableCommercetoolsGraphQlResponse::CACHE_TAG_PRODUCT_PREFIX],
'category' => [CacheableCommercetoolsGraphQlResponse::CACHE_TAG_CATEGORY_LIST],
'cart' => [CacheableCommercetoolsGraphQlResponse::CACHE_TAG_CART_PREFIX],
];
/**
* The cache tags invalidator.
*
* @var \Drupal\Core\Cache\CacheTagsInvalidatorInterface
*/
protected $cacheTagsInvalidator;
/**
* A config factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* A logger instance.
*
* @var \Psr\Log\LoggerInterface
*/
protected $logger;
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
$instance = parent::create($container);
$instance->cacheTagsInvalidator = $container->get('cache_tags.invalidator');
$instance->configFactory = $container->get('config.factory');
$instance->logger = $container->get('logger.factory')->get('commercetools');
return $instance;
}
/**
* Handles the incoming webhook payload and processes event messages.
*
* @param \Symfony\Component\HttpFoundation\Request $request
* The HTTP request containing the JSON payload.
*
* @return \Symfony\Component\HttpFoundation\JsonResponse
* The JSON response.
*/
public function call(Request $request): JsonResponse {
$data = json_decode($request->getContent(), TRUE);
$tags = [];
foreach ($data['message'] as $message) {
$body = json_decode($message['body'], TRUE);
$typeId = $body['resource']['typeId'] ?? NULL;
$id = $body['resource']['id'] ?? NULL;
if (isset(static::SUBSCRIPTION_CHANGES[$typeId])) {
foreach (static::SUBSCRIPTION_CHANGES[$typeId] as $tagPrefix) {
$tags[] = $tagPrefix . $id;
}
}
else {
$this->logger->error("Webhook call. Resource type '@typeId' validation prefix not found.", ['@typeId' => $typeId]);
}
if ($typeId === 'product') {
$tags[] = CacheableCommercetoolsGraphQlResponse::CACHE_TAG_PRODUCT_LIST;
}
if ($this->configFactory->get(SubscriptionSettingsForm::CONFIGURATION_NAME)->get('logging')) {
$this->logger->info(
'Webhook call: typeId: @typeId, id: @id. Cache tags: @tags',
[
'@typeId' => $typeId ?? '-',
'@id' => $id ?? '-',
'@tags' => var_export($tags, TRUE),
]
);
}
}
if ($tags) {
$this->cacheTagsInvalidator->invalidateTags($tags);
}
return new JsonResponse([
'status' => 'success',
], 200, [
'Content-Type' => 'application/json',
]);
}
/**
* Checks access.
*/
public function access(Request $request): AccessResult {
$auth = $request->headers->get('Authorization', '');
$requestToken = (preg_match('/^Bearer\s+(.+)$/i', $auth, $m)) ? $m[1] : '';
$trueToken = (string) $this->config(SubscriptionSettingsForm::CONFIGURATION_NAME)->get('webhook_token');
return AccessResult::allowedIf($requestToken == $trueToken)->setCacheMaxAge(0);
}
}
