Loading modules/checkout/tests/src/Kernel/CheckoutAccessTest.php +10 −7 Original line number Diff line number Diff line Loading @@ -83,7 +83,7 @@ class CheckoutAccessTest extends CartKernelTestBase { 'type' => 'default', 'title' => $this->randomMachineName(), 'stores' => [$this->store], 'variations' => [$this->variation], 'variations' => [$variation], ]); $product->save(); $this->variation = $this->reloadEntity($variation); Loading @@ -95,8 +95,8 @@ class CheckoutAccessTest extends CartKernelTestBase { * Tests that users need the `access checkout` permission. */ public function testAccessCheckoutPermission() { $user_with_access = $this->createUser([], ['access checkout']); $user_without_access = $this->createUser([], []); $user_with_access = $this->createUser([], ['access checkout', 'view commerce_product']); $user_without_access = $this->createUser([], ['view commerce_product']); $order = $this->createOrder($user_with_access); $request = $this->createRequest($order); Loading @@ -111,8 +111,8 @@ class CheckoutAccessTest extends CartKernelTestBase { * Tests that only the order's owner can view its checkout. */ public function testOwnerCheckoutAccess() { $user1 = $this->createUser([], ['access checkout']); $user2 = $this->createUser([], ['access checkout']); $user1 = $this->createUser([], ['access checkout', 'view commerce_product']); $user2 = $this->createUser([], ['access checkout', 'view commerce_product']); /** @var \Drupal\commerce_order\Entity\Order $order */ $order = $this->createOrder($user1); $request = $this->createRequest($order); Loading @@ -124,7 +124,7 @@ class CheckoutAccessTest extends CartKernelTestBase { * Tests that canceled orders cannot enter checkout. */ public function testCanceledOrderCheckout() { $user1 = $this->createUser([], ['access checkout']); $user1 = $this->createUser([], ['access checkout', 'view commerce_product']); $order = $this->createOrder($user1); $order->getState()->applyTransitionById('cancel'); $request = $this->createRequest($order); Loading @@ -135,7 +135,7 @@ class CheckoutAccessTest extends CartKernelTestBase { * Tests that an order must have items to enter checkout. */ public function testOrderMustHaveItems() { $user1 = $this->createUser([], ['access checkout']); $user1 = $this->createUser([], ['access checkout', 'view commerce_product']); $order = $this->createOrder($user1); $order->setItems([]); $request = $this->createRequest($order); Loading Loading @@ -196,6 +196,9 @@ class CheckoutAccessTest extends CartKernelTestBase { $order_item->save(); $order->addItem($order_item); $order->save(); $order = $this->reloadEntity($order); assert($order instanceof OrderInterface); $this->assertCount(1, $order->getItems()); return $order; } Loading modules/order/commerce_order.services.yml +5 −0 Original line number Diff line number Diff line Loading @@ -102,3 +102,8 @@ services: commerce_order.price_calculator: class: Drupal\commerce_order\PriceCalculator arguments: ['@commerce_order.adjustment_transformer', '@commerce_order.chain_order_type_resolver', '@commerce_price.chain_price_resolver', '@entity_type.manager', '@request_stack'] commerce_order.entity_accessible_availability_checker: class: Drupal\commerce_order\EntityAccessibleAvailabilityChecker tags: - { name: commerce_order.availability_checker } modules/order/src/EntityAccessibleAvailabilityChecker.php 0 → 100644 +38 −0 Original line number Diff line number Diff line <?php namespace Drupal\commerce_order; use Drupal\commerce\Context; use Drupal\commerce_order\Entity\OrderItemInterface; use Drupal\Core\Entity\EntityPublishedInterface; /** * Determines availability based on the purchased entity access. */ final class EntityAccessibleAvailabilityChecker implements AvailabilityCheckerInterface { /** * {@inheritdoc} */ public function applies(OrderItemInterface $order_item) { return $order_item->hasPurchasedEntity() && $order_item->getPurchasedEntity(); } /** * {@inheritdoc} */ public function check(OrderItemInterface $order_item, Context $context) { $purchasable_entity = $order_item->getPurchasedEntity(); // If the purchasable entity is publishable, immediately return false if // it is unpublished and skip entity access checks for performance. if ($purchasable_entity instanceof EntityPublishedInterface && $purchasable_entity->isPublished() === FALSE) { return AvailabilityResult::unavailable(); } if (!$purchasable_entity->access('view', $context->getCustomer())) { return AvailabilityResult::unavailable(); } return AvailabilityResult::neutral(); } } modules/order/tests/src/Kernel/PurchasedEntityConstraintValidatorTest.php +19 −8 Original line number Diff line number Diff line Loading @@ -9,6 +9,8 @@ use Drupal\commerce_order\Entity\OrderItem; use Drupal\commerce_price\Price; use Drupal\commerce_product\Entity\Product; use Drupal\commerce_product\Entity\ProductVariation; use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\DependencyInjection\ServiceModifierInterface; use Symfony\Component\Validator\ConstraintViolationInterface; /** Loading @@ -17,7 +19,7 @@ use Symfony\Component\Validator\ConstraintViolationInterface; * @group commerce_order * @coversDefaultClass \Drupal\commerce_order\Plugin\Validation\Constraint\PurchasedEntityAvailableConstraintValidator */ final class PurchasedEntityConstraintValidatorTest extends OrderKernelTestBase { final class PurchasedEntityConstraintValidatorTest extends OrderKernelTestBase implements ServiceModifierInterface { /** * Modules to enable. Loading @@ -28,6 +30,14 @@ final class PurchasedEntityConstraintValidatorTest extends OrderKernelTestBase { 'commerce_order_test', ]; /** * {@inheritdoc} */ public function alter(ContainerBuilder $container) { // We're focusing on testing the test availability checker. $container->removeDefinition('commerce_order.entity_accessible_availability_checker'); } /** * Tests the availability constraint. * Loading @@ -43,8 +53,9 @@ final class PurchasedEntityConstraintValidatorTest extends OrderKernelTestBase { * @dataProvider dataProviderCheckerData * @covers ::validate */ public function testAvailabilityConstraint($sku, $order_state, AvailabilityResult $expected_check_result, $expected_constraint) { public function testAvailabilityConstraint($sku, $order_state, AvailabilityResult $expected_check_result, bool $expected_constraint) { $context = new Context($this->createUser(), $this->store); /** @var \Drupal\commerce_order\AvailabilityManagerInterface $availability_manager */ $availability_manager = $this->container->get('commerce_order.availability_manager'); $product_variation = $this->createTestProductVariation([ Loading Loading @@ -207,18 +218,18 @@ final class PurchasedEntityConstraintValidatorTest extends OrderKernelTestBase { * @throws \Drupal\Core\Entity\EntityStorageException */ protected function createTestProductVariation(array $variation_data) { /** @var \Drupal\commerce_product\Entity\ProductVariation $product_variation */ $product_variation = ProductVariation::create($variation_data + [ 'type' => 'default', ]); $product_variation->save(); /** @var \Drupal\commerce_product\Entity\Product $product */ $product = Product::create([ 'title' => 'test product', 'type' => 'default', 'stores' => [$this->store->id()], 'variations' => [$product_variation], ]); /** @var \Drupal\commerce_product\Entity\ProductVariation $product_variation */ $product_variation = ProductVariation::create($variation_data + [ 'type' => 'default', ]); $product_variation->save(); $product->addVariation($product_variation); $product->save(); return $this->reloadEntity($product_variation); } Loading modules/order/tests/src/Unit/EntityAccessibleAvailabilityCheckerTest.php 0 → 100644 +79 −0 Original line number Diff line number Diff line <?php namespace Drupal\Tests\commerce_order\Unit; use Drupal\commerce\Context; use Drupal\commerce_order\AvailabilityResult; use Drupal\commerce_order\Entity\OrderItemInterface; use Drupal\commerce_order\EntityAccessibleAvailabilityChecker; use Drupal\commerce\PurchasableEntityInterface; use Drupal\commerce_product\Entity\ProductVariationInterface; use Drupal\commerce_store\Entity\StoreInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Tests\UnitTestCase; use Drupal\user\UserInterface; use Prophecy\Argument; /** * @coversDefaultClass \Drupal\commerce_order\EntityAccessibleAvailabilityChecker * @group commerce */ class EntityAccessibleAvailabilityCheckerTest extends UnitTestCase { /** * @covers ::applies */ public function testApplies() { $checker = new EntityAccessibleAvailabilityChecker(); $purchasable_entity = $this->prophesize(PurchasableEntityInterface::class); $order_item = $this->prophesize(OrderItemInterface::class); $order_item->hasPurchasedEntity()->willReturn(TRUE); $order_item->getPurchasedEntity()->willReturn($purchasable_entity); $this->assertTrue($checker->applies($order_item->reveal())); $order_item->hasPurchasedEntity()->willReturn(FALSE); $this->assertFalse($checker->applies($order_item->reveal())); $order_item->hasPurchasedEntity()->willReturn(TRUE); $order_item->getPurchasedEntity()->willReturn(NULL); $this->assertFalse($checker->applies($order_item->reveal())); } /** * @covers ::check */ public function testCheck() { $checker = new EntityAccessibleAvailabilityChecker(); $context = new Context( $this->prophesize(UserInterface::class)->reveal(), $this->prophesize(StoreInterface::class)->reveal() ); // Purchasable entity doesn't implement the EntityPublishedInterface, // hence the isPublished() check will be skipped. $purchasable_entity = $this->prophesize(PurchasableEntityInterface::class); $purchasable_entity->access('view', Argument::type(AccountInterface::class))->willReturn(TRUE); $order_item = $this->prophesize(OrderItemInterface::class); $order_item->getPurchasedEntity()->willReturn($purchasable_entity); $this->assertEquals(AvailabilityResult::neutral(), $checker->check($order_item->reveal(), $context)); $purchasable_entity->access('view', Argument::type(AccountInterface::class))->willReturn(FALSE); $order_item->getPurchasedEntity()->willReturn($purchasable_entity); $this->assertEquals(AvailabilityResult::unavailable(), $checker->check($order_item->reveal(), $context)); $purchasable_entity = $this->prophesize(ProductVariationInterface::class); $purchasable_entity->access('view', Argument::type(AccountInterface::class))->willReturn(TRUE); $purchasable_entity->isPublished()->willReturn(TRUE); $order_item = $this->prophesize(OrderItemInterface::class); $order_item->getPurchasedEntity()->willReturn($purchasable_entity); $this->assertEquals(AvailabilityResult::neutral(), $checker->check($order_item->reveal(), $context)); $purchasable_entity->isPublished()->willReturn(FALSE); $order_item->getPurchasedEntity()->willReturn($purchasable_entity); $this->assertEquals(AvailabilityResult::unavailable(), $checker->check($order_item->reveal(), $context)); $purchasable_entity->isPublished()->willReturn(TRUE); $purchasable_entity->access('view', Argument::type(AccountInterface::class))->willReturn(FALSE); $this->assertEquals(AvailabilityResult::unavailable(), $checker->check($order_item->reveal(), $context)); } } Loading
modules/checkout/tests/src/Kernel/CheckoutAccessTest.php +10 −7 Original line number Diff line number Diff line Loading @@ -83,7 +83,7 @@ class CheckoutAccessTest extends CartKernelTestBase { 'type' => 'default', 'title' => $this->randomMachineName(), 'stores' => [$this->store], 'variations' => [$this->variation], 'variations' => [$variation], ]); $product->save(); $this->variation = $this->reloadEntity($variation); Loading @@ -95,8 +95,8 @@ class CheckoutAccessTest extends CartKernelTestBase { * Tests that users need the `access checkout` permission. */ public function testAccessCheckoutPermission() { $user_with_access = $this->createUser([], ['access checkout']); $user_without_access = $this->createUser([], []); $user_with_access = $this->createUser([], ['access checkout', 'view commerce_product']); $user_without_access = $this->createUser([], ['view commerce_product']); $order = $this->createOrder($user_with_access); $request = $this->createRequest($order); Loading @@ -111,8 +111,8 @@ class CheckoutAccessTest extends CartKernelTestBase { * Tests that only the order's owner can view its checkout. */ public function testOwnerCheckoutAccess() { $user1 = $this->createUser([], ['access checkout']); $user2 = $this->createUser([], ['access checkout']); $user1 = $this->createUser([], ['access checkout', 'view commerce_product']); $user2 = $this->createUser([], ['access checkout', 'view commerce_product']); /** @var \Drupal\commerce_order\Entity\Order $order */ $order = $this->createOrder($user1); $request = $this->createRequest($order); Loading @@ -124,7 +124,7 @@ class CheckoutAccessTest extends CartKernelTestBase { * Tests that canceled orders cannot enter checkout. */ public function testCanceledOrderCheckout() { $user1 = $this->createUser([], ['access checkout']); $user1 = $this->createUser([], ['access checkout', 'view commerce_product']); $order = $this->createOrder($user1); $order->getState()->applyTransitionById('cancel'); $request = $this->createRequest($order); Loading @@ -135,7 +135,7 @@ class CheckoutAccessTest extends CartKernelTestBase { * Tests that an order must have items to enter checkout. */ public function testOrderMustHaveItems() { $user1 = $this->createUser([], ['access checkout']); $user1 = $this->createUser([], ['access checkout', 'view commerce_product']); $order = $this->createOrder($user1); $order->setItems([]); $request = $this->createRequest($order); Loading Loading @@ -196,6 +196,9 @@ class CheckoutAccessTest extends CartKernelTestBase { $order_item->save(); $order->addItem($order_item); $order->save(); $order = $this->reloadEntity($order); assert($order instanceof OrderInterface); $this->assertCount(1, $order->getItems()); return $order; } Loading
modules/order/commerce_order.services.yml +5 −0 Original line number Diff line number Diff line Loading @@ -102,3 +102,8 @@ services: commerce_order.price_calculator: class: Drupal\commerce_order\PriceCalculator arguments: ['@commerce_order.adjustment_transformer', '@commerce_order.chain_order_type_resolver', '@commerce_price.chain_price_resolver', '@entity_type.manager', '@request_stack'] commerce_order.entity_accessible_availability_checker: class: Drupal\commerce_order\EntityAccessibleAvailabilityChecker tags: - { name: commerce_order.availability_checker }
modules/order/src/EntityAccessibleAvailabilityChecker.php 0 → 100644 +38 −0 Original line number Diff line number Diff line <?php namespace Drupal\commerce_order; use Drupal\commerce\Context; use Drupal\commerce_order\Entity\OrderItemInterface; use Drupal\Core\Entity\EntityPublishedInterface; /** * Determines availability based on the purchased entity access. */ final class EntityAccessibleAvailabilityChecker implements AvailabilityCheckerInterface { /** * {@inheritdoc} */ public function applies(OrderItemInterface $order_item) { return $order_item->hasPurchasedEntity() && $order_item->getPurchasedEntity(); } /** * {@inheritdoc} */ public function check(OrderItemInterface $order_item, Context $context) { $purchasable_entity = $order_item->getPurchasedEntity(); // If the purchasable entity is publishable, immediately return false if // it is unpublished and skip entity access checks for performance. if ($purchasable_entity instanceof EntityPublishedInterface && $purchasable_entity->isPublished() === FALSE) { return AvailabilityResult::unavailable(); } if (!$purchasable_entity->access('view', $context->getCustomer())) { return AvailabilityResult::unavailable(); } return AvailabilityResult::neutral(); } }
modules/order/tests/src/Kernel/PurchasedEntityConstraintValidatorTest.php +19 −8 Original line number Diff line number Diff line Loading @@ -9,6 +9,8 @@ use Drupal\commerce_order\Entity\OrderItem; use Drupal\commerce_price\Price; use Drupal\commerce_product\Entity\Product; use Drupal\commerce_product\Entity\ProductVariation; use Drupal\Core\DependencyInjection\ContainerBuilder; use Drupal\Core\DependencyInjection\ServiceModifierInterface; use Symfony\Component\Validator\ConstraintViolationInterface; /** Loading @@ -17,7 +19,7 @@ use Symfony\Component\Validator\ConstraintViolationInterface; * @group commerce_order * @coversDefaultClass \Drupal\commerce_order\Plugin\Validation\Constraint\PurchasedEntityAvailableConstraintValidator */ final class PurchasedEntityConstraintValidatorTest extends OrderKernelTestBase { final class PurchasedEntityConstraintValidatorTest extends OrderKernelTestBase implements ServiceModifierInterface { /** * Modules to enable. Loading @@ -28,6 +30,14 @@ final class PurchasedEntityConstraintValidatorTest extends OrderKernelTestBase { 'commerce_order_test', ]; /** * {@inheritdoc} */ public function alter(ContainerBuilder $container) { // We're focusing on testing the test availability checker. $container->removeDefinition('commerce_order.entity_accessible_availability_checker'); } /** * Tests the availability constraint. * Loading @@ -43,8 +53,9 @@ final class PurchasedEntityConstraintValidatorTest extends OrderKernelTestBase { * @dataProvider dataProviderCheckerData * @covers ::validate */ public function testAvailabilityConstraint($sku, $order_state, AvailabilityResult $expected_check_result, $expected_constraint) { public function testAvailabilityConstraint($sku, $order_state, AvailabilityResult $expected_check_result, bool $expected_constraint) { $context = new Context($this->createUser(), $this->store); /** @var \Drupal\commerce_order\AvailabilityManagerInterface $availability_manager */ $availability_manager = $this->container->get('commerce_order.availability_manager'); $product_variation = $this->createTestProductVariation([ Loading Loading @@ -207,18 +218,18 @@ final class PurchasedEntityConstraintValidatorTest extends OrderKernelTestBase { * @throws \Drupal\Core\Entity\EntityStorageException */ protected function createTestProductVariation(array $variation_data) { /** @var \Drupal\commerce_product\Entity\ProductVariation $product_variation */ $product_variation = ProductVariation::create($variation_data + [ 'type' => 'default', ]); $product_variation->save(); /** @var \Drupal\commerce_product\Entity\Product $product */ $product = Product::create([ 'title' => 'test product', 'type' => 'default', 'stores' => [$this->store->id()], 'variations' => [$product_variation], ]); /** @var \Drupal\commerce_product\Entity\ProductVariation $product_variation */ $product_variation = ProductVariation::create($variation_data + [ 'type' => 'default', ]); $product_variation->save(); $product->addVariation($product_variation); $product->save(); return $this->reloadEntity($product_variation); } Loading
modules/order/tests/src/Unit/EntityAccessibleAvailabilityCheckerTest.php 0 → 100644 +79 −0 Original line number Diff line number Diff line <?php namespace Drupal\Tests\commerce_order\Unit; use Drupal\commerce\Context; use Drupal\commerce_order\AvailabilityResult; use Drupal\commerce_order\Entity\OrderItemInterface; use Drupal\commerce_order\EntityAccessibleAvailabilityChecker; use Drupal\commerce\PurchasableEntityInterface; use Drupal\commerce_product\Entity\ProductVariationInterface; use Drupal\commerce_store\Entity\StoreInterface; use Drupal\Core\Session\AccountInterface; use Drupal\Tests\UnitTestCase; use Drupal\user\UserInterface; use Prophecy\Argument; /** * @coversDefaultClass \Drupal\commerce_order\EntityAccessibleAvailabilityChecker * @group commerce */ class EntityAccessibleAvailabilityCheckerTest extends UnitTestCase { /** * @covers ::applies */ public function testApplies() { $checker = new EntityAccessibleAvailabilityChecker(); $purchasable_entity = $this->prophesize(PurchasableEntityInterface::class); $order_item = $this->prophesize(OrderItemInterface::class); $order_item->hasPurchasedEntity()->willReturn(TRUE); $order_item->getPurchasedEntity()->willReturn($purchasable_entity); $this->assertTrue($checker->applies($order_item->reveal())); $order_item->hasPurchasedEntity()->willReturn(FALSE); $this->assertFalse($checker->applies($order_item->reveal())); $order_item->hasPurchasedEntity()->willReturn(TRUE); $order_item->getPurchasedEntity()->willReturn(NULL); $this->assertFalse($checker->applies($order_item->reveal())); } /** * @covers ::check */ public function testCheck() { $checker = new EntityAccessibleAvailabilityChecker(); $context = new Context( $this->prophesize(UserInterface::class)->reveal(), $this->prophesize(StoreInterface::class)->reveal() ); // Purchasable entity doesn't implement the EntityPublishedInterface, // hence the isPublished() check will be skipped. $purchasable_entity = $this->prophesize(PurchasableEntityInterface::class); $purchasable_entity->access('view', Argument::type(AccountInterface::class))->willReturn(TRUE); $order_item = $this->prophesize(OrderItemInterface::class); $order_item->getPurchasedEntity()->willReturn($purchasable_entity); $this->assertEquals(AvailabilityResult::neutral(), $checker->check($order_item->reveal(), $context)); $purchasable_entity->access('view', Argument::type(AccountInterface::class))->willReturn(FALSE); $order_item->getPurchasedEntity()->willReturn($purchasable_entity); $this->assertEquals(AvailabilityResult::unavailable(), $checker->check($order_item->reveal(), $context)); $purchasable_entity = $this->prophesize(ProductVariationInterface::class); $purchasable_entity->access('view', Argument::type(AccountInterface::class))->willReturn(TRUE); $purchasable_entity->isPublished()->willReturn(TRUE); $order_item = $this->prophesize(OrderItemInterface::class); $order_item->getPurchasedEntity()->willReturn($purchasable_entity); $this->assertEquals(AvailabilityResult::neutral(), $checker->check($order_item->reveal(), $context)); $purchasable_entity->isPublished()->willReturn(FALSE); $order_item->getPurchasedEntity()->willReturn($purchasable_entity); $this->assertEquals(AvailabilityResult::unavailable(), $checker->check($order_item->reveal(), $context)); $purchasable_entity->isPublished()->willReturn(TRUE); $purchasable_entity->access('view', Argument::type(AccountInterface::class))->willReturn(FALSE); $this->assertEquals(AvailabilityResult::unavailable(), $checker->check($order_item->reveal(), $context)); } }