Merge branch '1.11'

* 1.11:
  Use request stack service everytimes
  [Zones] disabled country choosing made possible
  Apply suggestions from code review
  Fix Phpspec errors again
  Trying to fix Phpspec on Symfony 4.4
  Fix Psalm errors
  Keep session for now
  Fix zone member integrity listener
This commit is contained in:
Grzegorz Sadowski 2022-06-08 20:23:52 +02:00
commit 42c163f08f
No known key found for this signature in database
GPG key ID: EF87FF4E6E3BD364
9 changed files with 125 additions and 32 deletions

View file

@ -6,6 +6,7 @@ Feature: Adding a new zone with country type members
Background:
Given the store has country "France"
And the store has disabled country "Austria"
And the store also has country "United States"
And this country has the "Alabama" province with "AL" code
And the store has a zone "North America" with code "NA"
@ -52,3 +53,13 @@ Feature: Adding a new zone with country type members
Then I should be notified that it has been successfully created
And the zone named "European Union" with the "France" country member should appear in the registry
And its scope should be "shipping"
@ui @javascript @api
Scenario: Adding zone with disabled country
When I want to create a new zone consisting of country
And I name it "European Union"
And I specify its code as "EU"
And I add a country "Austria"
And I add it
Then I should be notified that it has been successfully created
And the zone named "European Union" with the "Austria" country member should appear in the registry

View file

@ -144,6 +144,12 @@
</errorLevel>
</InvalidDocblock>
<UndefinedMethod>
<errorLevel type="suppress">
<referencedMethod name="Symfony\Component\HttpFoundation\RequestStack::getSession" />
</errorLevel>
</UndefinedMethod>
<MissingReturnType errorLevel="info" />
<PropertyNotSetInConstructor errorLevel="info" />

View file

@ -18,6 +18,7 @@ use Sylius\Component\Addressing\Checker\ZoneDeletionCheckerInterface;
use Sylius\Component\Addressing\Model\CountryInterface;
use Sylius\Component\Addressing\Model\ZoneInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
use Webmozart\Assert\Assert;
@ -25,7 +26,7 @@ use Webmozart\Assert\Assert;
final class ZoneMemberIntegrityListener
{
public function __construct(
private SessionInterface $session,
private RequestStack $requestStack,
private ZoneDeletionCheckerInterface $zoneDeletionChecker,
private CountryProvincesDeletionCheckerInterface $countryProvincesDeletionChecker
) {
@ -38,7 +39,7 @@ final class ZoneMemberIntegrityListener
if (!$this->zoneDeletionChecker->isDeletable($zone)) {
/** @var FlashBagInterface $flashes */
$flashes = $this->session->getBag('flashes');
$flashes = $this->getSession()->getBag('flashes');
$flashes->add('error', [
'message' => 'sylius.resource.delete_error',
'parameters' => ['%resource%' => 'zone'],
@ -56,7 +57,7 @@ final class ZoneMemberIntegrityListener
if (!$this->countryProvincesDeletionChecker->isDeletable($country)) {
/** @var FlashBagInterface $flashes */
$flashes = $this->session->getBag('flashes');
$flashes = $this->getSession()->getBag('flashes');
$flashes->add('error', [
'message' => 'sylius.resource.delete_error',
'parameters' => ['%resource%' => 'province'],
@ -65,4 +66,14 @@ final class ZoneMemberIntegrityListener
$event->stopPropagation();
}
}
private function getSession(): SessionInterface
{
// bc-layer for Symfony 4
if (!method_exists(RequestStack::class, 'getSession')) {
return $this->requestStack->getMasterRequest()->getSession();
}
return $this->requestStack->getSession();
}
}

View file

@ -41,13 +41,11 @@ final class CountryChoiceType extends AbstractType
->setDefaults([
'choice_filter' => null,
'choices' => function (Options $options): iterable {
if (null === $options['enabled']) {
$countries = $this->countryRepository->findAll();
} else {
$countries = $this->countryRepository->findBy(['enabled' => $options['enabled']]);
if ($options['enabled'] === true) {
return $this->countryRepository->findBy(['enabled' => $options['enabled']]);
}
return $countries;
return $this->countryRepository->findAll();
},
'choice_value' => 'code',
'choice_label' => 'name',

View file

@ -101,7 +101,11 @@ final class ZoneType extends AbstractResourceType
private function getZoneMemberEntryOptions(string $zoneMemberType): array
{
$zoneMemberEntryOptions = [
ZoneInterface::TYPE_COUNTRY => ['label' => 'sylius.form.zone.types.country'],
ZoneInterface::TYPE_COUNTRY => [
'label' => 'sylius.form.zone.types.country',
'enabled' => false,
'attr' => ['class' => 'country_search_dropdown ui fluid search selection dropdown'],
],
ZoneInterface::TYPE_PROVINCE => ['label' => 'sylius.form.zone.types.province'],
ZoneInterface::TYPE_ZONE => ['label' => 'sylius.form.zone.types.zone'],
];

View file

@ -16,7 +16,7 @@
<defaults public="true" />
<service id="sylius.listener.zone_member_integrity" class="Sylius\Bundle\AddressingBundle\EventListener\ZoneMemberIntegrityListener">
<argument type="service" id="session" />
<argument type="service" id="request_stack" />
<argument type="service" id="Sylius\Component\Addressing\Checker\ZoneDeletionCheckerInterface" />
<argument type="service" id="Sylius\Component\Addressing\Checker\CountryProvincesDeletionCheckerInterface" />
<tag name="kernel.event_listener" event="sylius.zone.pre_delete" method="protectFromRemovingZone" />

View file

@ -33,6 +33,9 @@ final class CountryChoiceTypeTest extends TypeTestCase
/** @var ProphecyInterface|CountryInterface */
private $poland;
/** @var ProphecyInterface|CountryInterface */
private $austria;
protected function setUp(): void
{
$this->countryRepository = $this->prophesize(RepositoryInterface::class);
@ -49,6 +52,13 @@ final class CountryChoiceTypeTest extends TypeTestCase
$poland->getName()->willReturn('Poland');
$this->poland = $poland;
/** @var ProphecyInterface|CountryInterface $austria */
$austria = $this->prophesize(CountryInterface::class);
$austria->getCode()->willReturn('AT');
$austria->getName()->willReturn('Austria');
$austria->isEnabled()->willReturn(false);
$this->austria = $austria;
parent::setUp();
}
@ -61,9 +71,7 @@ final class CountryChoiceTypeTest extends TypeTestCase
];
}
/**
* @test
*/
/** @test */
public function it_returns_only_enabled_countries_by_default(): void
{
$this->countryRepository->findBy(['enabled' => true])->willReturn([
@ -74,23 +82,20 @@ final class CountryChoiceTypeTest extends TypeTestCase
$this->assertChoicesLabels(['France', 'Poland']);
}
/**
* @test
*/
public function it_returns_all_countries(): void
/** @test */
public function it_returns_all_countries_when_option_enabled_is_false(): void
{
$this->countryRepository->findAll()->willReturn([
$this->france->reveal(),
$this->poland->reveal(),
$this->austria->reveal(),
]);
$this->assertChoicesLabels(['France', 'Poland'], ['enabled' => null]);
$this->assertChoicesLabels(['Austria','France', 'Poland'], ['enabled' => false]);
}
/**
* @test
*/
public function it_returns_countries_in_an_alphabetical_order(): void
/** @test */
public function it_returns_enabled_countries_in_an_alphabetical_order(): void
{
$this->countryRepository->findBy(['enabled' => true])->willReturn([
$this->poland->reveal(),
@ -100,10 +105,32 @@ final class CountryChoiceTypeTest extends TypeTestCase
$this->assertChoicesLabels(['France', 'Poland']);
}
/**
* @test
*/
public function it_returns_filtered_out_countries(): void
/** @test */
public function it_returns_all_countries_in_an_alphabetical_order(): void
{
$this->countryRepository->findAll()->willReturn([
$this->poland->reveal(),
$this->france->reveal(),
$this->austria->reveal(),
]);
$this->assertChoicesLabels(['Austria', 'France', 'Poland'], ['enabled' => false]);
}
/** @test */
public function it_returns_all_filtered_out_countries(): void
{
$this->countryRepository->findAll()->willReturn([
$this->france->reveal(),
$this->poland->reveal(),
$this->austria->reveal(),
]);
$this->assertChoicesLabels(['Poland'], ['choice_filter' => static fn (?CountryInterface $country): bool => $country !== null && $country->getName() === 'Poland', 'enabled' => false]);
}
/** @test */
public function it_returns_enabled_filtered_out_countries(): void
{
$this->countryRepository->findBy(['enabled' => true])->willReturn([
$this->france->reveal(),

View file

@ -14,36 +14,46 @@ declare(strict_types=1);
namespace spec\Sylius\Bundle\AddressingBundle\EventListener;
use PhpSpec\ObjectBehavior;
use Sylius\Bundle\AddressingBundle\EventListener\ZoneMemberIntegrityListener;
use Sylius\Component\Addressing\Checker\CountryProvincesDeletionCheckerInterface;
use Sylius\Component\Addressing\Checker\ZoneDeletionCheckerInterface;
use Sylius\Component\Addressing\Model\CountryInterface;
use Sylius\Component\Addressing\Model\ZoneInterface;
use Symfony\Component\EventDispatcher\GenericEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\RequestStack;
use Symfony\Component\HttpFoundation\Session\Flash\FlashBagInterface;
use Symfony\Component\HttpFoundation\Session\SessionInterface;
class ZoneMemberIntegrityListenerSpec extends ObjectBehavior
{
function let(
SessionInterface $session,
RequestStack $requestStack,
ZoneDeletionCheckerInterface $zoneDeletionChecker,
CountryProvincesDeletionCheckerInterface $countryProvincesDeletionChecker
): void {
$this->beConstructedWith($session, $zoneDeletionChecker, $countryProvincesDeletionChecker);
$this->beConstructedWith($requestStack, $zoneDeletionChecker, $countryProvincesDeletionChecker);
}
function it_does_not_allow_to_remove_zone_if_it_exists_as_a_zone_member(
RequestStack $requestStack,
SessionInterface $session,
ZoneDeletionCheckerInterface $zoneDeletionChecker,
GenericEvent $event,
ZoneInterface $zone,
FlashBagInterface $flashes
FlashBagInterface $flashes,
Request $request,
): void {
$event->getSubject()->willReturn($zone);
$zoneDeletionChecker->isDeletable($zone)->willReturn(false);
if (!method_exists(RequestStack::class, 'getSession')) {
$requestStack->getMasterRequest()->willReturn($request);
$request->getSession()->willReturn($session);
} else {
$requestStack->getSession()->willReturn($session);
}
$session->getBag('flashes')->willReturn($flashes);
$flashes
@ -60,15 +70,25 @@ class ZoneMemberIntegrityListenerSpec extends ObjectBehavior
}
function it_does_nothing_if_zone_does_not_exist_as_a_zone_member(
RequestStack $requestStack,
SessionInterface $session,
ZoneDeletionCheckerInterface $zoneDeletionChecker,
GenericEvent $event,
ZoneInterface $zone
ZoneInterface $zone,
Request $request,
): void {
if (!method_exists(RequestStack::class, 'getSession')) {
$requestStack->getMasterRequest()->willReturn($request);
$request->getSession()->willReturn($session);
} else {
$requestStack->getSession()->willReturn($session);
}
$event->getSubject()->willReturn($zone);
$zoneDeletionChecker->isDeletable($zone)->willReturn(true);
$session->getBag('flashes')->shouldNotBeCalled();
$event->stopPropagation()->shouldNotBeCalled();
@ -86,16 +106,25 @@ class ZoneMemberIntegrityListenerSpec extends ObjectBehavior
}
function it_does_not_allow_to_remove_province_if_it_exists_as_a_zone_member(
RequestStack $requestStack,
SessionInterface $session,
CountryProvincesDeletionCheckerInterface $countryProvincesDeletionChecker,
GenericEvent $event,
CountryInterface $country,
FlashBagInterface $flashes
FlashBagInterface $flashes,
Request $request,
): void {
$event->getSubject()->willReturn($country);
$countryProvincesDeletionChecker->isDeletable($country)->willReturn(false);
if (!method_exists(RequestStack::class, 'getSession')) {
$requestStack->getMasterRequest()->willReturn($request);
$request->getSession()->willReturn($session);
} else {
$requestStack->getSession()->willReturn($session);
}
$session->getBag('flashes')->willReturn($flashes);
$flashes

View file

@ -13,3 +13,10 @@
<h4 class="ui dividing header">{{ 'sylius.ui.members'|trans }}</h4>
{{ form_row(form.members, {'label': false}) }}
</div>
<style>
.ui.form .field>.country_search_dropdown {
display: inline-block;
width: 150px!important;
}
</style>