Commit 308ed5da authored by Bojan Živanović's avatar Bojan Živanović
Browse files

Merge pull request #225 from crbanman/2511266

Issue #2511266 by cbanman: Create a service for determining variation availability
parents f668a7d2 300ac10a
Loading
Loading
Loading
Loading
+5 −0
Changes for modules/order/commerce_order.services.yml: 5 added lines, 0 removed lines.
Original line number Diff line number Diff line
services:
  commerce_order.availability_manager:
    class: Drupal\commerce_order\AvailabilityManager
    tags:
      - { name: service_collector, tag: commerce_order.availability_checker, call: addAvailabilityChecker }
+43 −0
Changes for modules/order/src/AvailabilityCheckerInterface.php: 43 added lines, 0 removed lines.
Original line number Diff line number Diff line
<?php

/**
 * @file
 * Contains \Drupal\commerce_order\AvailabilityCheckerInterface.
 */

namespace Drupal\commerce_order;

use Drupal\commerce\LineItemSourceInterface;

/**
 * Defines the interface for availability checkers.
 */
interface AvailabilityCheckerInterface {

  /**
   * Determines whether the checker can be used with the given source entity.
   *
   * @param \Drupal\commerce\LineItemSourceInterface $source
   *   The source.
   *
   * @return bool
   *   Returns TRUE if the given source entity can be used with the checker,
   *   returns FALSE if it cannot.
   */
  public function applies(LineItemSourceInterface $source);

  /**
   * Checks the availability of a given source and quantity.
   *
   * @param \Drupal\commerce\LineItemSourceInterface $source
   *   The source.
   * @param int $quantity
   *   The quantity.
   *
   * @return bool
   *   Returns TRUE if the source is available, FALSE if it is not available,
   *   or NULL if it has no opinion on the source.
   */
  public function check(LineItemSourceInterface $source, $quantity);

}
+48 −0
Changes for modules/order/src/AvailabilityManager.php: 48 added lines, 0 removed lines.
Original line number Diff line number Diff line
<?php

/**
 * @file
 * Contains \Drupal\commerce_order\AvailabilityManager.
 */

namespace Drupal\commerce_order;

use Drupal\commerce\LineItemSourceInterface;

class AvailabilityManager implements AvailabilityManagerInterface {

  /**
   * The availability checkers.
   *
   * @var array
   */
  protected $availabilityCheckers = [];

  /**
   * Adds availability checker to the registered availability checkers.
   *
   * @param \Drupal\commerce_order\AvailabilityCheckerInterface $availabilityChecker
   *   The availability checker.
   */
  public function addAvailabilityChecker(AvailabilityCheckerInterface $availabilityChecker) {
    $this->availabilityCheckers[] = $availabilityChecker;
  }

  /**
   * {@inheritdoc}
   */
  public function check(LineItemSourceInterface $source, $quantity) {
    foreach ($this->availabilityCheckers as $availabilityChecker) {
      if ($availabilityChecker->applies($source)) {
        $check = $availabilityChecker->check($source, $quantity);

        if ($check === FALSE) {
          return FALSE;
        }
      }
    }

    return TRUE;
  }

}
+30 −0
Changes for modules/order/src/AvailabilityManagerInterface.php: 30 added lines, 0 removed lines.
Original line number Diff line number Diff line
<?php

/**
 * @file
 * Contains \Drupal\commerce_order\AvailabilityManagerInterface.
 */

namespace Drupal\commerce_order;

use Drupal\commerce\LineItemSourceInterface;

/**
 * Defines the interface for availability managers.
 */
interface AvailabilityManagerInterface {

  /**
   * Checks availability of a source with the registered availability checkers.
   *
   * @param \Drupal\commerce\LineItemSourceInterface $source
   *   The source.
   * @param int $quantity
   *   The quantity.
   *
   * @return bool
   *   Returns TRUE if the source is available, FALSE if it is not available.
   */
  public function check(LineItemSourceInterface $source, $quantity);

}
+103 −0
Changes for modules/order/src/Tests/AvailabilityManagerTest.php: 103 added lines, 0 removed lines.
Original line number Diff line number Diff line
<?php

/**
 * @file
 * Contains \Drupal\commerce_order\Tests\AvailabilityManagerTest.
 */

namespace Drupal\commerce_order\Tests;

use Drupal\commerce_order\AvailabilityManager;
use Drupal\Tests\UnitTestCase;

/**
 * Tests the availability manager.
 *
 * @group commerce
 */
class AvailabilityManagerTest extends UnitTestCase {

  /**
   * @var \Drupal\commerce_order\AvailabilityManager
   */
  protected $availabilityManager;

  /**
   * {@inheritdoc}
   */
  public function setUp() {
    parent::setUp();
    $this->availabilityManager = new AvailabilityManager();
  }

  /**
   * ::covers check
   */
  public function testCheck() {
    $mockCheckerBuilder = $this->getMockBuilder('Drupal\commerce_order\AvailabilityCheckerInterface')
      ->disableOriginalConstructor();

    $mockSource = $this->getMock('Drupal\commerce_product\ProductVariationInterface');

    $firstChecker = $mockCheckerBuilder->getMock();
    $firstChecker->expects($this->any())
      ->method('applies')
      ->with($mockSource)
      ->willReturn(TRUE);
    $firstChecker->expects($this->any())
      ->method('check')
      ->with($mockSource, 1)
      ->willReturn(NULL);

    $secondChecker = $mockCheckerBuilder->getMock();
    $secondChecker->expects($this->any())
      ->method('applies')
      ->with($mockSource)
      ->willReturn(TRUE);
    $secondChecker->expects($this->any())
      ->method('check')
      ->with($mockSource, 1)
      ->willReturn(TRUE);

    $thirdChecker = $mockCheckerBuilder->getMock();
    $thirdChecker->expects($this->any())
      ->method('applies')
      ->with($mockSource)
      ->willReturn(FALSE);
    $thirdChecker->expects($this->any())
      ->method('check')
      ->with($mockSource, 1)
      ->willReturn(FALSE);

    $fourthChecker = $mockCheckerBuilder->getMock();
    $fourthChecker->expects($this->any())
      ->method('applies')
      ->with($mockSource)
      ->willReturn(TRUE);
    $fourthChecker->expects($this->any())
      ->method('check')
      ->with($mockSource, 1)
      ->willReturn(FALSE);

    $this->availabilityManager->addAvailabilityChecker($firstChecker);

    $result = $this->availabilityManager->check($mockSource, 1);
    $this->assertTrue($result, 'The checked source is available when a checker returns NULL.');

    $this->availabilityManager->addAvailabilityChecker($secondChecker);

    $result = $this->availabilityManager->check($mockSource, 1);
    $this->assertTrue($result, 'The checked source is available when no checkers return FALSE.');

    $this->availabilityManager->addAvailabilityChecker($thirdChecker);

    $result = $this->availabilityManager->check($mockSource, 1);
    $this->assertTrue($result, 'The checked source is available when a checker that would return FALSE does not apply to the given source.');

    $this->availabilityManager->addAvailabilityChecker($fourthChecker);

    $result = $this->availabilityManager->check($mockSource, 1);
    $this->assertFalse($result, 'The checked source is not available when a checker that returns FALSE applies to the given source.');
  }

}