commerce_api-8.x-1.x-dev/src/Resource/CartUpdateItemResource.php

src/Resource/CartUpdateItemResource.php
<?php

namespace Drupal\commerce_api\Resource;

use Drupal\commerce_api\EntityResourceShim;
use Drupal\commerce_cart\CartManagerInterface;
use Drupal\commerce_cart\CartProviderInterface;
use Drupal\commerce_order\Entity\OrderInterface;
use Drupal\commerce_order\Entity\OrderItemInterface;
use Drupal\commerce_order\Exception\OrderVersionMismatchException;
use Drupal\commerce_order\OrderItemStorageInterface;
use Drupal\Component\Serialization\Json;
use Drupal\Core\Access\AccessResult;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Render\RenderContext;
use Drupal\Core\Render\RendererInterface;
use Drupal\jsonapi\Entity\EntityValidationTrait;
use Drupal\jsonapi\Exception\EntityAccessDeniedHttpException;
use Drupal\jsonapi\JsonApiResource\JsonApiDocumentTopLevel;
use Drupal\jsonapi\JsonApiResource\ResourceObject;
use Drupal\jsonapi\JsonApiResource\ResourceObjectData;
use Drupal\jsonapi\ResourceResponse;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpKernel\Exception\BadRequestHttpException;
use Symfony\Component\HttpKernel\Exception\ConflictHttpException;

final class CartUpdateItemResource extends CartResourceBase {

  use EntityValidationTrait;

  /**
   * Constructs a new CartUpdateItemResource object.
   *
   * @param \Drupal\commerce_cart\CartProviderInterface $cartProvider
   *   The cart provider.
   * @param \Drupal\commerce_cart\CartManagerInterface $cartManager
   *   The cart manager.
   * @param \Drupal\commerce_api\EntityResourceShim $inner
   *   The JSON:API controller shim.
   * @param \Drupal\Core\Render\RendererInterface $renderer
   *   The renderer.
   */
  public function __construct(protected CartProviderInterface $cartProvider, protected CartManagerInterface $cartManager, protected EntityResourceShim $inner, private RendererInterface $renderer) {
    parent::__construct($cartProvider, $cartManager);
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container) {
    return new static(
      $container->get('commerce_cart.cart_provider'),
      $container->get('commerce_cart.cart_manager'),
      $container->get('commerce_api.jsonapi_controller_shim'),
      $container->get('renderer')
    );
  }

  /**
   * Update an order item from a cart.
   *
   * @param \Symfony\Component\HttpFoundation\Request $request
   *   The request.
   * @param \Drupal\commerce_order\Entity\OrderInterface $commerce_order
   *   The order.
   * @param \Drupal\commerce_order\Entity\OrderItemInterface $commerce_order_item
   *   The order item.
   *
   * @return \Drupal\jsonapi\ResourceResponse
   *   The response.
   *
   * @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
   * @throws \Drupal\Component\Plugin\Exception\PluginNotFoundException
   * @throws \Drupal\Core\Entity\EntityStorageException
   */
  public function process(Request $request, OrderInterface $commerce_order, OrderItemInterface $commerce_order_item): ResourceResponse {
    $resource_type = $this->resourceTypeRepository->get($commerce_order_item->getEntityTypeId(), $commerce_order_item->bundle());
    $parsed_entity = $this->inner->deserialize($resource_type, $request, JsonApiDocumentTopLevel::class);
    assert($parsed_entity instanceof OrderItemInterface);

    $body = Json::decode($request->getContent());
    $data = $body['data'];
    if ($data['id'] !== $commerce_order_item->uuid()) {
      throw new BadRequestHttpException(sprintf('The selected entity (%s) does not match the ID in the payload (%s).', $commerce_order_item->uuid(), $data['id']));
    }
    $data += ['attributes' => [], 'relationships' => []];
    $data_field_names = array_merge(array_keys($data['attributes']), array_keys($data['relationships']));
    // Prevent modifying `purchased_entity` on existing order items.
    // We make this check explicitly here and not through field access to ensure
    // that the field value is always validated.
    if (in_array('purchased_entity', $data_field_names, TRUE)) {
      throw new EntityAccessDeniedHttpException($commerce_order_item, AccessResult::forbidden(), '/data/attributes/purchased_entity', 'The `purchased_entity` field cannot be modified.');
    }

    // Ensure `purchased_entity` is always validated.
    $field_names = ['purchased_entity'];
    foreach ($data_field_names as $data_field_name) {
      $field_name = $resource_type->getInternalName($data_field_name);

      $parsed_field_item = $parsed_entity->get($field_name);
      $original_field_item = $commerce_order_item->get($field_name);
      if ($this->inner->checkPatchFieldAccess($parsed_field_item, $original_field_item)) {
        $commerce_order_item->set($field_name, $parsed_field_item->getValue());
      }
      $field_names[] = $field_name;
    }

    static::validate($commerce_order_item, $field_names);

    $render_context = new RenderContext();
    $this->renderer->executeInRenderContext($render_context, function () use ($commerce_order, $commerce_order_item) {
      try {
        $this->cartManager->updateOrderItem($commerce_order, $commerce_order_item);
      }
      catch (EntityStorageException $exception) {
        if ($exception->getPrevious() instanceof OrderVersionMismatchException) {
          throw new ConflictHttpException($exception->getMessage(), $exception);
        }
        throw $exception;
      }
    });

    $order_item_storage = $this->entityTypeManager->getStorage('commerce_order_item');
    assert($order_item_storage instanceof OrderItemStorageInterface);
    // Reload the order item as the cart has refreshed.
    $commerce_order_item = $order_item_storage->load($commerce_order_item->id());

    $resource_object = ResourceObject::createFromEntity($this->resourceTypeRepository->get($commerce_order_item->getEntityTypeId(), $commerce_order_item->bundle()), $commerce_order_item);
    $primary_data = new ResourceObjectData([$resource_object], 1);
    $response = $this->createJsonapiResponse($primary_data, $request);

    if (!$render_context->isEmpty()) {
      $response->addCacheableDependency($render_context->pop());
    }

    return $response;
  }

}

Главная | Обратная связь

drupal hosting | друпал хостинг | it patrol .inc