Skip to content

Commit

Permalink
Merge pull request Sylius#5216 from Zales0123/list-checkout-shipping-…
Browse files Browse the repository at this point in the history
…methods-also-by-channel

[Core][Shipping] Fix shipping method choice type
  • Loading branch information
Paweł Jędrzejewski committed Jun 10, 2016
2 parents 78a3cfc + 8da4ace commit 5065c7a
Show file tree
Hide file tree
Showing 2 changed files with 233 additions and 0 deletions.
102 changes: 102 additions & 0 deletions Resolver/ShippingMethodsByZonesAndChannelResolver.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php

/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace Sylius\Component\Core\Resolver;

use Sylius\Component\Addressing\Matcher\ZoneMatcherInterface;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\ShipmentInterface;
use Sylius\Component\Shipping\Model\ShippingSubjectInterface;
use Sylius\Component\Shipping\Repository\ShippingMethodRepositoryInterface;
use Sylius\Component\Shipping\Resolver\MethodsResolverInterface;

/**
* @author Mateusz Zalewski <mateusz.zalewski@lakion.com>
*/
class ShippingMethodsByZonesAndChannelResolver implements MethodsResolverInterface
{
/**
* @var ShippingMethodRepositoryInterface
*/
private $shippingMethodRepository;

/**
* @var ZoneMatcherInterface
*/
private $zoneMatcher;

/**
* @param ShippingMethodRepositoryInterface $shippingMethodRepository
* @param ZoneMatcherInterface $zoneMatcher
*/
public function __construct(
ShippingMethodRepositoryInterface $shippingMethodRepository,
ZoneMatcherInterface $zoneMatcher
) {
$this->shippingMethodRepository = $shippingMethodRepository;
$this->zoneMatcher = $zoneMatcher;
}

/**
* {@inheritdoc}
*/
public function getSupportedMethods(ShippingSubjectInterface $subject)
{
$zones = $this->getZonesIdsForAddress($subject->getOrder());
if (empty($zones)) {
return [];
}

/** @var ChannelInterface $channel */
$channel = $subject->getOrder()->getChannel();

$methods = [];
foreach ($this->shippingMethodRepository->findBy(['enabled' => true, 'zone' => $zones]) as $method) {
if ($channel->hasShippingMethod($method)) {
$methods[] = $method;
}
}

return $methods;
}

/**
* @param OrderInterface $order
*
* @return array
*/
private function getZonesIdsForAddress(OrderInterface $order)
{
$matchedZones = $this->zoneMatcher->matchAll($order->getShippingAddress());
if (empty($matchedZones)) {
return [];
}

$zones = [];
foreach ($matchedZones as $zone) {
$zones[] = $zone->getId();
}

return $zones;
}

/**
* {@inheritdoc}
*/
public function supports(ShippingSubjectInterface $subject)
{
return $subject instanceof ShipmentInterface &&
null !== $subject->getOrder() &&
null !== $subject->getOrder()->getShippingAddress()
;
}
}
131 changes: 131 additions & 0 deletions spec/Resolver/ShippingMethodsByZonesAndChannelResolverSpec.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
<?php

/*
* This file is part of the Sylius package.
*
* (c) Paweł Jędrzejewski
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/

namespace spec\Sylius\Component\Core\Resolver;

use PhpSpec\ObjectBehavior;
use Sylius\Component\Addressing\Matcher\ZoneMatcherInterface;
use Sylius\Component\Addressing\Model\ZoneInterface;
use Sylius\Component\Core\Model\AddressInterface;
use Sylius\Component\Core\Model\ChannelInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\ShipmentInterface;
use Sylius\Component\Core\Model\ShippingMethodInterface;
use Sylius\Component\Core\Resolver\ShippingMethodsByZonesAndChannelResolver;
use Sylius\Component\Shipping\Model\ShippingSubjectInterface;
use Sylius\Component\Shipping\Repository\ShippingMethodRepositoryInterface;
use Sylius\Component\Shipping\Resolver\MethodsResolverInterface;

/**
* @mixin ShippingMethodsByZonesAndChannelResolver
*
* @author Mateusz Zalewski <mateusz.zalewski@lakion.com>
*/
class ShippingMethodsByZonesAndChannelResolverSpec extends ObjectBehavior
{
function let(
ShippingMethodRepositoryInterface $shippingMethodRepository,
ZoneMatcherInterface $zoneMatcher
) {
$this->beConstructedWith($shippingMethodRepository, $zoneMatcher);
}

function it_is_initializable()
{
$this->shouldHaveType('Sylius\Component\Core\Resolver\ShippingMethodsByZonesAndChannelResolver');
}

function it_implements_shipping_methods_by_zones_and_channel_resolver_interface()
{
$this->shouldImplement(MethodsResolverInterface::class);
}

function it_returns_shipping_methods_matched_for_shipment_order_shipping_address_and_order_channel(
AddressInterface $address,
ChannelInterface $channel,
OrderInterface $order,
ShipmentInterface $shipment,
ShippingMethodInterface $firstShippingMethod,
ShippingMethodInterface $secondShippingMethod,
ShippingMethodInterface $thirdShippingMethod,
ShippingMethodRepositoryInterface $shippingMethodRepository,
ZoneInterface $firstZone,
ZoneInterface $secondZone,
ZoneMatcherInterface $zoneMatcher
) {
$shipment->getOrder()->willReturn($order);
$order->getShippingAddress()->willReturn($address);
$order->getChannel()->willReturn($channel);

$zoneMatcher->matchAll($address)->willReturn([$firstZone, $secondZone]);

$firstZone->getId()->willReturn(1);
$secondZone->getId()->willReturn(4);

$shippingMethodRepository
->findBy(['enabled' => true, 'zone' => [1, 4]])
->willReturn([$firstShippingMethod, $secondShippingMethod, $thirdShippingMethod])
;

$channel->hasShippingMethod($firstShippingMethod)->willReturn(true);
$channel->hasShippingMethod($secondShippingMethod)->willReturn(true);
$channel->hasShippingMethod($thirdShippingMethod)->willReturn(false);

$this->getSupportedMethods($shipment)->shouldReturn([$firstShippingMethod, $secondShippingMethod]);
}

function it_returns_empty_array_if_zone_matcher_could_not_match_any_zone(
AddressInterface $address,
OrderInterface $order,
ShipmentInterface $shipment,
ZoneMatcherInterface $zoneMatcher
) {
$shipment->getOrder()->willReturn($order);
$order->getShippingAddress()->willReturn($address);

$zoneMatcher->matchAll($address)->willReturn([]);

$this->getSupportedMethods($shipment)->shouldReturn([]);
}

function it_supports_shipments_with_order_and_its_shipping_address_defined(
AddressInterface $address,
OrderInterface $order,
ShipmentInterface $shipment
) {
$shipment->getOrder()->willReturn($order);
$order->getShippingAddress()->willReturn($address);

$this->supports($shipment)->shouldReturn(true);
}

function it_does_not_support_shipments_which_order_has_no_shipping_address_defined(
OrderInterface $order,
ShipmentInterface $shipment
) {
$shipment->getOrder()->willReturn($order);
$order->getShippingAddress()->willReturn(null);

$this->supports($shipment)->shouldReturn(false);
}

function it_does_not_support_shipments_which_has_no_order_defined(ShipmentInterface $shipment)
{
$shipment->getOrder()->willReturn(null);

$this->supports($shipment)->shouldReturn(false);
}

function it_does_not_support_different_shipping_subject_than_shipment(ShippingSubjectInterface $subject)
{
$this->supports($subject)->shouldReturn(false);
}
}

0 comments on commit 5065c7a

Please sign in to comment.