Skip to content

Instantly share code, notes, and snippets.

@steveoliver
Last active March 7, 2018 16:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save steveoliver/313e1b2e6d86a254a04fc2c2a05731f7 to your computer and use it in GitHub Desktop.
Save steveoliver/313e1b2e6d86a254a04fc2c2a05731f7 to your computer and use it in GitHub Desktop.
Testing an event subscriber
<?php
namespace Drupal\Tests\commerce_cart\Kernel;
use Drupal\commerce_order\Entity\OrderItem;
use Drupal\commerce_price\Price;
use Drupal\commerce_order\Entity\OrderInterface;
use Drupal\commerce_product\Entity\ProductVariation;
use Drupal\Tests\commerce\Kernel\CommerceKernelTestBase;
/**
* Tests the cart manager.
*
* @coversDefaultClass \Drupal\commerce_cart\CartManager
* @group commerce
*/
class CartManagerTest extends CommerceKernelTestBase {
use CartManagerTestTrait;
/**
* The cart manager.
*
* @var \Drupal\commerce_cart\CartManager
*/
protected $cartManager;
/**
* The cart provider.
*
* @var \Drupal\commerce_cart\CartProvider
*/
protected $cartProvider;
/**
* A sample user.
*
* @var \Drupal\user\UserInterface
*/
protected $user;
/**
* A product variation.
*
* @var \Drupal\commerce_product\Entity\ProductVariation
*/
protected $variation1;
/**
* A product variation.
*
* @var \Drupal\commerce_product\Entity\ProductVariation
*/
protected $variation2;
/**
* A product variation.
*
* @var \Drupal\commerce_product\Entity\ProductVariation
*/
protected $variation3;
/**
* Modules to enable.
*
* @var array
*/
public static $modules = [
'entity_reference_revisions',
'path',
'profile',
'state_machine',
'commerce_product',
'commerce_order',
];
/**
* {@inheritdoc}
*/
protected function setUp() {
parent::setUp();
$this->installEntitySchema('commerce_order');
$this->installConfig(['commerce_order']);
$this->installConfig(['commerce_product']);
$this->variation1 = ProductVariation::create([
'type' => 'default',
'sku' => 'variation1',
'title' => $this->randomString(),
'price' => new Price('1.00', 'USD'),
'status' => 1,
]);
$this->variation2 = ProductVariation::create([
'type' => 'default',
'sku' => 'variation2',
'title' => $this->randomString(),
'price' => new Price('2.00', 'USD'),
'status' => 1,
]);
$this->variation3 = ProductVariation::create([
'type' => 'default',
'sku' => 'variation3',
'title' => $this->randomString(),
'price' => new Price('3.00', 'USD'),
'status' => 1,
]);
$user = $this->createUser();
$this->user = $this->reloadEntity($user);
}
// /**
// * Tests the cart manager.
// *
// * @covers ::addEntity
// * @covers ::createOrderItem
// * @covers ::addOrderItem
// * @covers ::updateOrderItem
// * @covers ::removeOrderItem
// * @covers ::emptyCart
// */
// public function testCartManager() {
// $this->installCommerceCart();
//
// $cart = $this->cartProvider->createCart('default', $this->store, $this->user);
// $this->assertInstanceOf(OrderInterface::class, $cart);
// $this->assertEmpty($cart->getItems());
//
// $order_item1 = $this->cartManager->addEntity($cart, $this->variation1);
// $order_item1 = $this->reloadEntity($order_item1);
// $this->assertNotEmpty($cart->hasItem($order_item1));
// $this->assertEquals(1, $order_item1->getQuantity());
// $this->assertEquals(new Price('1.00', 'USD'), $cart->getTotalPrice());
//
// $order_item1->setQuantity(2);
// $this->cartManager->updateOrderItem($cart, $order_item1);
// $this->assertNotEmpty($cart->hasItem($order_item1));
// $this->assertEquals(2, $order_item1->getQuantity());
// $this->assertEquals(new Price('2.00', 'USD'), $cart->getTotalPrice());
//
// $order_item2 = $this->cartManager->addEntity($cart, $this->variation2, 3);
// $order_item2 = $this->reloadEntity($order_item2);
// $this->assertNotEmpty($cart->hasItem($order_item1));
// $this->assertNotEmpty($cart->hasItem($order_item2));
// $this->assertEquals(3, $order_item2->getQuantity());
// $this->assertEquals(new Price('8.00', 'USD'), $cart->getTotalPrice());
//
// $this->cartManager->removeOrderItem($cart, $order_item1);
// $this->assertNotEmpty($cart->hasItem($order_item2));
// $this->assertEmpty($cart->hasItem($order_item1));
// $this->assertEquals(new Price('6.00', 'USD'), $cart->getTotalPrice());
//
// $this->cartManager->emptyCart($cart);
// $this->assertEmpty($cart->getItems());
// $this->assertEquals(NULL, $cart->getTotalPrice());
// }
//
// /**
// * Tests that order items without purchasable entities do not cause crashes.
// */
// public function testAddOrderItem() {
// $this->installCommerceCart();
// $cart = $this->cartProvider->createCart('default', $this->store, $this->user);
//
// $order_item = OrderItem::create([
// 'type' => 'default',
// 'quantity' => 2,
// 'unit_price' => new Price('12.00', 'USD'),
// ]);
// $order_item->save();
// $this->cartManager->addOrderItem($cart, $order_item);
// $this->assertEquals(1, count($cart->getItems()));
// }
/**
* Tests that order items added in an event subscriber get added to the order.
*/
public function testEventAddOrderItem() {
$this->installCommerceCart();
$this->enableModules(['commerce_cart_test_event_subscriber']);
$cart = $this->cartProvider->createCart('default', $this->store, $this->user);
$order_item = OrderItem::create([
'type' => 'default',
'quantity' => 1,
'unit_price' => new Price('12.00', 'USD'),
'purchased_entity' => $this->variation3,
]);
$order_item->save();
$this->cartManager->addOrderItem($cart, $order_item);
$this->assertEquals(2, count($cart->getItems()));
}
}
<?php
namespace Drupal\commerce_cart_test_event_subscriber\EventSubscriber;
use Drupal\commerce\PurchasableEntityInterface;
use Drupal\commerce_cart\CartManagerInterface;
use Drupal\commerce_cart\CartProviderInterface;
use Drupal\commerce_cart\Event\CartEntityAddEvent;
use Drupal\commerce_cart\Event\CartEvents;
use Drupal\commerce_cart\Event\CartOrderItemRemoveEvent;
use Drupal\commerce_order\Entity\OrderInterface;
use Drupal\commerce_order\Entity\OrderItemInterface;
use Drupal\commerce_product\Entity\ProductInterface;
use Drupal\commerce_product\Entity\ProductVariation;
use Drupal\commerce_product\ProductVariationStorage;
use Drupal\commerce_store\CurrentStoreInterface;
use Drupal\commerce_store\Entity\StoreInterface;
use Drupal\Core\Entity\EntityStorageException;
use Drupal\Core\Entity\EntityTypeManagerInterface;
use Drupal\user\UserInterface;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
/**
* Responds to cart events.
*/
class CartEventSubscriber implements EventSubscriberInterface {
/**
* The cart manager.
*
* @var \Drupal\commerce_cart\CartManagerInterface
*/
protected $cartManager;
/**
* The cart provider.
*
* @var \Drupal\commerce_cart\CartProviderInterface
*/
protected $cartProvider;
/**
* The current store.
*
* @var \Drupal\commerce_store\CurrentStoreInterface
*/
protected $currentStore;
/**
* The order item storage.
*
* @var \Drupal\commerce_order\OrderItemStorageInterface
*/
protected $orderItemStorage;
/**
* Product variation storage.
*
* @var \Drupal\commerce_product\ProductVariationStorageInterface
*/
protected $variationStorage;
/**
* CartEventSubscriber constructor.
*
* @param \Drupal\commerce_cart\CartManagerInterface $cart_manager
* The cart manager.
* @param \Drupal\commerce_cart\CartProviderInterface $cart_provider
* The cart provider.
* @param \Drupal\commerce_store\CurrentStoreInterface $current_store
* The current store.
* @param \Drupal\Core\Entity\EntityTypeManagerInterface $entity_type_manager
* The entity type manager.
*
* @throws \Drupal\Component\Plugin\Exception\InvalidPluginDefinitionException
*/
public function __construct(CartManagerInterface $cart_manager, CartProviderInterface $cart_provider, CurrentStoreInterface $current_store, EntityTypeManagerInterface $entity_type_manager) {
$this->cartManager = $cart_manager;
$this->cartProvider = $cart_provider;
$this->currentStore = $current_store;
$this->orderItemStorage = $entity_type_manager->getStorage('commerce_order_item');
$this->variationStorage = $entity_type_manager->getStorage('commerce_product_variation');
}
/**
* {@inheritdoc}
*/
public static function getSubscribedEvents() {
return [
CartEvents::CART_ENTITY_ADD => 'onAddToCart',
];
}
/**
* Responds to Add to cart events.
*
* @param \Drupal\commerce_cart\Event\CartEntityAddEvent $event
* The entity add to cart event.
*
* @throws \Exception
*/
public function onAddToCart(CartEntityAddEvent $event) {
$order_item = $event->getOrderItem();
echo 'FOO';
/** @var \Drupal\commerce_product\Entity\ProductVariationInterface $purchased_entity */
$purchased_entity = $order_item->getPurchasedEntity();
if ($purchased_entity->getSku() === 'variation3') {
$store = $this->selectStore($purchased_entity);
$cart = $this->getCart($store, 'default');
$variation2_id = $this->variationStorage->getQuery()
->condition('sku', 'variation2')
->execute();
$variation2 = $this->variationStorage->load($variation2_id);
$order_item = $this->cartManager->addEntity($cart, $variation2, 1);
try {
$order_item->save();
// @todo: BUG: Sessions don't get added to cart on a fresh cart (after
// checkout). Once cart is initialized, it looks like, then will session
// products be added. WTF?
}
catch (EntityStorageException $e) {
drupal_set_message(t(':variation could not be added to cart. Please contact customer support.', [
':variation' => $variation2->label(),
]));
}
}
}
/**
* Gets or creates a cart for the given store and order type.
*
* @param \Drupal\commerce_store\Entity\StoreInterface $store
* The store.
* @param string $order_type_id
* The order type id.
*
* @return \Drupal\commerce_order\Entity\OrderInterface
* A cart.
*/
protected function getCart(StoreInterface $store, $order_type_id) {
$cart = $this->cartProvider->getCart($order_type_id, $store);
if (!$cart) {
$cart = $this->cartProvider->createCart($order_type_id, $store);
}
return $cart;
}
/**
* Selects the store for the given purchasable entity.
*
* If the entity is sold from one store, then that store is selected.
* If the entity is sold from multiple stores, and the current store is
* one of them, then that store is selected.
*
* @param \Drupal\commerce\PurchasableEntityInterface $entity
* The entity being added to cart.
*
* @throws \Exception
* When the entity can't be purchased from the current store.
*
* @return \Drupal\commerce_store\Entity\StoreInterface
* The selected store.
*/
protected function selectStore(PurchasableEntityInterface $entity) {
$stores = $entity->getStores();
if (count($stores) === 1) {
$store = reset($stores);
}
elseif (count($stores) === 0) {
// Malformed entity.
throw new \Exception('The given entity is not assigned to any store.');
}
else {
$store = $this->currentStore->getStore();
if (!in_array($store, $stores)) {
// Indicates that the site listings are not filtered properly.
throw new \Exception("The given entity can't be purchased from the current store.");
}
}
return $store;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment