custom/plugins/PickwareErpStarter/vendor/pickware/api-error-handling-bundle/src/ControllerExceptionHandling/AdminApiJsonApiErrorSerializableExceptionHandler.php line 49

Open in your IDE?
  1. <?php
  2. /*
  3.  * Copyright (c) Pickware GmbH. All rights reserved.
  4.  * This file is part of software that is released under a proprietary license.
  5.  * You must not copy, modify, distribute, make publicly available, or execute
  6.  * its contents or parts thereof without express permission by the copyright
  7.  * holder, unless otherwise permitted by law.
  8.  */
  9. declare(strict_types=1);
  10. namespace Pickware\ApiErrorHandlingBundle\ControllerExceptionHandling;
  11. use Pickware\HttpUtils\JsonApi\JsonApiErrors;
  12. use Pickware\HttpUtils\JsonApi\JsonApiErrorSerializable;
  13. use Pickware\HttpUtils\JsonApi\JsonApiErrorsSerializable;
  14. use Psr\Log\LoggerInterface;
  15. use Shopware\Core\Framework\Api\Context\AdminApiSource;
  16. use Shopware\Core\Framework\Context;
  17. use Shopware\Core\PlatformRequest;
  18. use Symfony\Component\EventDispatcher\EventSubscriberInterface;
  19. use Symfony\Component\HttpFoundation\Response;
  20. use Symfony\Component\HttpKernel\Event\ExceptionEvent;
  21. use Throwable;
  22. class AdminApiJsonApiErrorSerializableExceptionHandler implements EventSubscriberInterface
  23. {
  24.     private bool $debug;
  25.     private LoggerInterface $logger;
  26.     public function __construct(bool $debugLoggerInterface $logger)
  27.     {
  28.         $this->debug $debug;
  29.         $this->logger $logger;
  30.     }
  31.     public static function getSubscribedEvents(): array
  32.     {
  33.         return [
  34.             // Use Priority 0 because Shopware uses -1 in its  ResponseExceptionListener, and we want to run BEFORE
  35.             // Shopware. Otherwise, Shopware would handle our error.
  36.             ExceptionEvent::class => [
  37.                 'onKernelException',
  38.                 0,
  39.             ],
  40.         ];
  41.     }
  42.     public function onKernelException(ExceptionEvent $event): void
  43.     {
  44.         $throwable $event->getThrowable();
  45.         if (!($throwable instanceof JsonApiErrorSerializable) && !($throwable instanceof JsonApiErrorsSerializable)) {
  46.             return;
  47.         }
  48.         /** @var Context $context */
  49.         $context $event->getRequest()->attributes->get(PlatformRequest::ATTRIBUTE_CONTEXT_OBJECT);
  50.         // Only the Admin API uses JSON API therefore we can only respond with JSON API error here.
  51.         if (!$context || !($context->getSource() instanceof AdminApiSource)) {
  52.             return;
  53.         }
  54.         if ($throwable instanceof JsonApiErrorSerializable) {
  55.             $errors = new JsonApiErrors([$throwable->serializeToJsonApiError()->setStatus(500)]);
  56.         } else {
  57.             $errors $throwable->serializeToJsonApiErrors();
  58.         }
  59.         $exceptionDetails $this->getExceptionDetails($throwable);
  60.         $this->logger->error(
  61.             sprintf('Caught JsonApiErrorSerializable exception in admin controller: %s'$throwable->getMessage()),
  62.             [
  63.                 'exception' => $exceptionDetails,
  64.                 'jsonApiErrors' => $errors,
  65.             ],
  66.         );
  67.         $response $errors->toJsonApiErrorResponse(Response::HTTP_INTERNAL_SERVER_ERROR);
  68.         if ($this->debug) {
  69.             $json json_decode($response->getContent(), false512JSON_THROW_ON_ERROR);
  70.             $json->_exceptionDetails $exceptionDetails;
  71.             $response->setData($json);
  72.         }
  73.         $event->setResponse($response);
  74.     }
  75.     private function getExceptionDetails(Throwable $exception): array
  76.     {
  77.         $details = [
  78.             'message' => $exception->getMessage(),
  79.             'code' => $exception->getCode(),
  80.             'file' => $exception->getFile(),
  81.             'line' => $exception->getLine(),
  82.             'trace' => $this->escapeStringsInStacktrace($exception->getTrace()),
  83.         ];
  84.         if ($exception->getPrevious()) {
  85.             $details['previous'] = $this->getExceptionDetails($exception->getPrevious());
  86.         }
  87.         return $details;
  88.     }
  89.     private function escapeStringsInStacktrace(array $array): array
  90.     {
  91.         foreach ($array as $key => $value) {
  92.             if (\is_array($value)) {
  93.                 $array[$key] = $this->escapeStringsInStacktrace($value);
  94.             }
  95.             if (\is_string($value)) {
  96.                 if (!ctype_print($value) && mb_strlen($value) === 16) {
  97.                     $array[$key] = sprintf('ATTENTION: Converted binary string by the "%s": %s'self::class, bin2hex($value));
  98.                 } elseif (!mb_detect_encoding($valuemb_detect_order(), true)) {
  99.                     $array[$key] = utf8_encode($value);
  100.                 }
  101.             }
  102.         }
  103.         return $array;
  104.     }
  105. }