diff --git a/.bunnyshell/docker/php/Dockerfile b/.bunnyshell/docker/php/Dockerfile index 78df60e65c..9634e6ca5f 100644 --- a/.bunnyshell/docker/php/Dockerfile +++ b/.bunnyshell/docker/php/Dockerfile @@ -1,10 +1,10 @@ # the different stages of this Dockerfile are meant to be built into separate images # https://docs.docker.com/compose/compose-file/#target -ARG PHP_VERSION=8.1 -ARG NODE_VERSION=16 -ARG ALPINE_VERSION=3.15 -ARG COMPOSER_VERSION=2.4 +ARG PHP_VERSION=8.2 +ARG NODE_VERSION=18 +ARG ALPINE_VERSION=3.18 +ARG COMPOSER_VERSION=2.6 ARG PHP_EXTENSION_INSTALLER_VERSION=latest FROM composer:${COMPOSER_VERSION} AS composer diff --git a/phpstan.neon.dist b/phpstan.neon.dist index 579c9164b2..88e98b0d80 100644 --- a/phpstan.neon.dist +++ b/phpstan.neon.dist @@ -38,9 +38,10 @@ parameters: - 'src/Sylius/Bundle/ApiBundle/**.php' ignoreErrors: + - '/(Interface|Class) [a-zA-Z\\]+ specifies template type (\w+) of interface [a-zA-Z\\]+ as [a-zA-Z\\]+ (of [a-zA-Z\\]+ )?but it''s already specified as/' # turns off a weird generics check behavior, we are basing on Psalm for generics checks - '/Access to an undefined property Doctrine\\Common\\Collections\\ArrayCollection/' + - '/Class "Sylius\\Bundle\\CoreBundle\\Fixture\\PaymentFixture" not found/' + - '/Class Symfony\\Component\\Clock\\Clock not found\./' - '/Class Symfony\\Component\\Security\\Core\\Authentication\\Token\\UsernamePasswordToken constructor invoked with 4 parameters\, 2\-3 required./' - '/Method Symfony\\Component\\Serializer\\Normalizer\\NormalizerInterface\:\:supportsNormalization\(\) invoked with 3 parameters\, 1\-2 required\./' - - '/(Interface|Class) [a-zA-Z\\]+ specifies template type (\w+) of interface [a-zA-Z\\]+ as [a-zA-Z\\]+ (of [a-zA-Z\\]+ )?but it''s already specified as/' # turns off a weird generics check behavior, we are basing on Psalm for generics checks - '/Symfony\\Component\\Serializer\\NameConverter\\NameConverterInterface::normalize\(\) invoked with 2 parameters, 1 required./' - - '/Class "Sylius\\Bundle\\CoreBundle\\Fixture\\PaymentFixture" not found/' diff --git a/psalm.xml b/psalm.xml index 6dff4b706a..1a3deaa214 100644 --- a/psalm.xml +++ b/psalm.xml @@ -265,6 +265,7 @@ + diff --git a/src/Sylius/Bundle/ApiBundle/disabledSpec/DataPersister/MessengerDataPersisterSpec.php b/src/Sylius/Bundle/ApiBundle/disabledSpec/DataPersister/MessengerDataPersisterSpec.php index 320ace81c5..57d235cb4a 100644 --- a/src/Sylius/Bundle/ApiBundle/disabledSpec/DataPersister/MessengerDataPersisterSpec.php +++ b/src/Sylius/Bundle/ApiBundle/disabledSpec/DataPersister/MessengerDataPersisterSpec.php @@ -17,6 +17,7 @@ use ApiPlatform\Core\DataPersister\ContextAwareDataPersisterInterface; use PhpSpec\ObjectBehavior; use Prophecy\Argument; use Sylius\Bundle\ApiBundle\Command\Checkout\CompleteOrder; +use Symfony\Component\HttpKernel\Kernel; use Symfony\Component\Messenger\Envelope; use Symfony\Component\Messenger\Exception\DelayedMessageHandlingException; use Symfony\Component\Messenger\Exception\HandlerFailedException; @@ -42,7 +43,13 @@ final class MessengerDataPersisterSpec extends ObjectBehavior $completeOrder->setOrderTokenValue('ORDERTOKEN'); $envelope = new Envelope($completeOrder); - $decoratedDataPersister->persist($envelope, [])->willThrow(new DelayedMessageHandlingException([new \RuntimeException('Delayed message exception')])); + if (version_compare(Kernel::VERSION, '6.3.5', '>=')) { + $exception = new DelayedMessageHandlingException([new \RuntimeException('Delayed message exception')], $envelope); + } else { + $exception = new DelayedMessageHandlingException([new \RuntimeException('Delayed message exception')]); + } + + $decoratedDataPersister->persist($envelope, [])->willThrow($exception); $this->shouldThrow(new \RuntimeException('Delayed message exception'))->during('persist', [$envelope, []]); } diff --git a/src/Sylius/Bundle/CoreBundle/EventListener/Workflow/OrderShipping/AfterOrderShippedListener.php b/src/Sylius/Bundle/CoreBundle/EventListener/Workflow/OrderShipping/AfterOrderShippedListener.php index c621d63873..e7a97e68c6 100644 --- a/src/Sylius/Bundle/CoreBundle/EventListener/Workflow/OrderShipping/AfterOrderShippedListener.php +++ b/src/Sylius/Bundle/CoreBundle/EventListener/Workflow/OrderShipping/AfterOrderShippedListener.php @@ -26,10 +26,8 @@ final class AfterOrderShippedListener public function onOrderShippingCompleted(CompletedEvent $event): void { - Assert::isInstanceOf($event->getSubject(), OrderInterface::class); - - /** @var OrderInterface $order */ $order = $event->getSubject(); + Assert::isInstanceOf($order, OrderInterface::class); $this->orderStateResolver->resolve($order); } diff --git a/src/Sylius/Bundle/CoreBundle/EventListener/Workflow/Shipment/AssignShippingDateListener.php b/src/Sylius/Bundle/CoreBundle/EventListener/Workflow/Shipment/AssignShippingDateListener.php new file mode 100644 index 0000000000..ad687c83dd --- /dev/null +++ b/src/Sylius/Bundle/CoreBundle/EventListener/Workflow/Shipment/AssignShippingDateListener.php @@ -0,0 +1,34 @@ +getSubject(); + Assert::isInstanceOf($shipment, ShipmentInterface::class); + + $this->shippingDateAssigner->assign($shipment); + } +} diff --git a/src/Sylius/Bundle/CoreBundle/EventListener/Workflow/Shipment/ResolveOrderShipmentStateListener.php b/src/Sylius/Bundle/CoreBundle/EventListener/Workflow/Shipment/ResolveOrderShipmentStateListener.php new file mode 100644 index 0000000000..a18fcc1861 --- /dev/null +++ b/src/Sylius/Bundle/CoreBundle/EventListener/Workflow/Shipment/ResolveOrderShipmentStateListener.php @@ -0,0 +1,38 @@ +getSubject(); + Assert::isInstanceOf($shipment, ShipmentInterface::class); + + $order = $shipment->getOrder(); + Assert::isInstanceOf($order, OrderInterface::class); + + $this->orderStateResolver->resolve($order); + } +} diff --git a/src/Sylius/Bundle/CoreBundle/Resources/config/app/workflow/sylius_order_shipping.yaml b/src/Sylius/Bundle/CoreBundle/Resources/config/app/workflow/sylius_order_shipping.yaml index d33661036d..7f48a51cec 100644 --- a/src/Sylius/Bundle/CoreBundle/Resources/config/app/workflow/sylius_order_shipping.yaml +++ b/src/Sylius/Bundle/CoreBundle/Resources/config/app/workflow/sylius_order_shipping.yaml @@ -4,7 +4,7 @@ framework: type: state_machine marking_store: type: method - property: ShippingState + property: shippingState supports: - Sylius\Component\Core\Model\OrderInterface initial_marking: !php/const Sylius\Component\Core\OrderShippingStates::STATE_CART diff --git a/src/Sylius/Bundle/CoreBundle/Resources/config/app/workflow/sylius_shipment.yaml b/src/Sylius/Bundle/CoreBundle/Resources/config/app/workflow/sylius_shipment.yaml new file mode 100644 index 0000000000..bf1edf953b --- /dev/null +++ b/src/Sylius/Bundle/CoreBundle/Resources/config/app/workflow/sylius_shipment.yaml @@ -0,0 +1,25 @@ +framework: + workflows: + !php/const Sylius\Component\Shipping\ShipmentTransitions::GRAPH: + type: state_machine + marking_store: + type: method + property: state + supports: + - Sylius\Component\Core\Model\ShipmentInterface + initial_marking: !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_CART + places: + - !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_CART + - !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_READY + - !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_SHIPPED + - !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_CANCELLED + transitions: + !php/const Sylius\Component\Shipping\ShipmentTransitions::TRANSITION_CREATE: + from: !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_CART + to: !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_READY + !php/const Sylius\Component\Shipping\ShipmentTransitions::TRANSITION_SHIP: + from: !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_READY + to: !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_SHIPPED + !php/const Sylius\Component\Shipping\ShipmentTransitions::TRANSITION_CANCEL: + from: !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_READY + to: !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_CANCELLED diff --git a/src/Sylius/Bundle/CoreBundle/Resources/config/services.xml b/src/Sylius/Bundle/CoreBundle/Resources/config/services.xml index 03b3bb28fb..f377386cc7 100644 --- a/src/Sylius/Bundle/CoreBundle/Resources/config/services.xml +++ b/src/Sylius/Bundle/CoreBundle/Resources/config/services.xml @@ -42,7 +42,6 @@ - diff --git a/src/Sylius/Bundle/CoreBundle/Resources/config/services/listeners.xml b/src/Sylius/Bundle/CoreBundle/Resources/config/services/listeners.xml index d52fe61c74..34d58f5f24 100644 --- a/src/Sylius/Bundle/CoreBundle/Resources/config/services/listeners.xml +++ b/src/Sylius/Bundle/CoreBundle/Resources/config/services/listeners.xml @@ -12,6 +12,10 @@ --> + + + + diff --git a/src/Sylius/Bundle/CoreBundle/Resources/config/services/workflow/listeners.xml b/src/Sylius/Bundle/CoreBundle/Resources/config/services/listeners/workflow/order_shipping.xml similarity index 98% rename from src/Sylius/Bundle/CoreBundle/Resources/config/services/workflow/listeners.xml rename to src/Sylius/Bundle/CoreBundle/Resources/config/services/listeners/workflow/order_shipping.xml index 66bcbbcbd7..27e57021cc 100644 --- a/src/Sylius/Bundle/CoreBundle/Resources/config/services/workflow/listeners.xml +++ b/src/Sylius/Bundle/CoreBundle/Resources/config/services/listeners/workflow/order_shipping.xml @@ -16,7 +16,7 @@ - + + + + + + + + + + + + + + + + + + + diff --git a/src/Sylius/Bundle/CoreBundle/Resources/config/services/workflow.xml b/src/Sylius/Bundle/CoreBundle/Resources/config/services/workflow.xml deleted file mode 100644 index caabedb6cc..0000000000 --- a/src/Sylius/Bundle/CoreBundle/Resources/config/services/workflow.xml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - diff --git a/src/Sylius/Bundle/CoreBundle/Tests/Functional/StateMachine/ShipmentWorkflowTest.php b/src/Sylius/Bundle/CoreBundle/Tests/Functional/StateMachine/ShipmentWorkflowTest.php new file mode 100644 index 0000000000..75584484a4 --- /dev/null +++ b/src/Sylius/Bundle/CoreBundle/Tests/Functional/StateMachine/ShipmentWorkflowTest.php @@ -0,0 +1,66 @@ +order = new Order(); + + $this->shipment = new Shipment(); + $this->shipment->setOrder($this->order); + } + + /** + * @test + * + * @dataProvider availableTransitionsFromReadyState + */ + public function it_applies_all_available_transitions_for_create_state(string $transition, string $expectedStatus): void + { + $stateMachine = $this->getStateMachine(); + $stateMachine->apply($this->order, 'sylius_order_shipping', 'request_shipping'); + $stateMachine->apply($this->shipment, 'sylius_shipment', 'create'); + $stateMachine->apply($this->shipment, 'sylius_shipment', $transition); + + $this->assertSame($expectedStatus, $this->shipment->getState()); + } + + public function availableTransitionsFromReadyState(): iterable + { + yield ['cancel', 'cancelled']; + yield ['ship', 'shipped']; + } + + private function getStateMachine(): StateMachineInterface + { + return self::getContainer()->get('sylius.state_machine.adapter.symfony_workflow'); + } +} diff --git a/src/Sylius/Bundle/CoreBundle/Tests/Functional/StateMachine/WorkflowAdapter/OrderShippingWorkflowTest.php b/src/Sylius/Bundle/CoreBundle/Tests/Functional/StateMachine/WorkflowAdapter/OrderShippingWorkflowTest.php index 25650bc7ae..c28e7a354a 100644 --- a/src/Sylius/Bundle/CoreBundle/Tests/Functional/StateMachine/WorkflowAdapter/OrderShippingWorkflowTest.php +++ b/src/Sylius/Bundle/CoreBundle/Tests/Functional/StateMachine/WorkflowAdapter/OrderShippingWorkflowTest.php @@ -35,9 +35,7 @@ final class OrderShippingWorkflowTest extends KernelTestCase $this->assertSame($expectedStatus, $subject->getShippingState()); } - /** - * @test - */ + /** @test */ public function it_applies_ship_transition_if_order_is_partially_shipped(): void { $stateMachine = $this->getStateMachine(); diff --git a/src/Sylius/Bundle/CoreBundle/spec/EventListener/Workflow/OrderShipping/AfterOrderShippedListenerSpec.php b/src/Sylius/Bundle/CoreBundle/spec/EventListener/Workflow/OrderShipping/AfterOrderShippedListenerSpec.php index 86e1faa721..ccfeb82490 100644 --- a/src/Sylius/Bundle/CoreBundle/spec/EventListener/Workflow/OrderShipping/AfterOrderShippedListenerSpec.php +++ b/src/Sylius/Bundle/CoreBundle/spec/EventListener/Workflow/OrderShipping/AfterOrderShippedListenerSpec.php @@ -28,10 +28,13 @@ final class AfterOrderShippedListenerSpec extends ObjectBehavior function it_throws_an_exception_on_non_supported_subject(\stdClass $callback): void { - $this->shouldThrow(\InvalidArgumentException::class)->during('onOrderShippingCompleted', [new CompletedEvent($callback->getWrappedObject(), new Marking())]); + $this + ->shouldThrow(\InvalidArgumentException::class) + ->during('onOrderShippingCompleted', [new CompletedEvent($callback->getWrappedObject(), new Marking())]) + ; } - function it_resolves_orders_after_order_being_shipped( + function it_resolves_order_state_after_order_being_shipped( StateResolverInterface $stateResolver, ): void { $order = new Order(); diff --git a/src/Sylius/Bundle/CoreBundle/spec/EventListener/Workflow/Shipment/AssignShippingDateListenerSpec.php b/src/Sylius/Bundle/CoreBundle/spec/EventListener/Workflow/Shipment/AssignShippingDateListenerSpec.php new file mode 100644 index 0000000000..a6896ee691 --- /dev/null +++ b/src/Sylius/Bundle/CoreBundle/spec/EventListener/Workflow/Shipment/AssignShippingDateListenerSpec.php @@ -0,0 +1,47 @@ +beConstructedWith($shippingDateAssigner); + } + + function it_throws_an_exception_on_non_supported_subject(\stdClass $subject): void + { + $this + ->shouldThrow(\InvalidArgumentException::class) + ->during('__invoke', [new TransitionEvent($subject->getWrappedObject(), new Marking())]) + ; + } + + function it_resolves_order_state_after_order_being_shipped( + ShippingDateAssignerInterface $shippingDateAssigner, + ): void { + $shipment = new Shipment(); + $event = new TransitionEvent($shipment, new Marking()); + + $shippingDateAssigner->assign($shipment)->shouldBeCalled(); + + $this->__invoke($event); + } +} diff --git a/src/Sylius/Bundle/CoreBundle/spec/EventListener/Workflow/Shipment/ResolveOrderShipmentStateListenerSpec.php b/src/Sylius/Bundle/CoreBundle/spec/EventListener/Workflow/Shipment/ResolveOrderShipmentStateListenerSpec.php new file mode 100644 index 0000000000..8d934ae192 --- /dev/null +++ b/src/Sylius/Bundle/CoreBundle/spec/EventListener/Workflow/Shipment/ResolveOrderShipmentStateListenerSpec.php @@ -0,0 +1,51 @@ +beConstructedWith($stateResolver); + } + + function it_throws_an_exception_on_non_supported_subject(\stdClass $subject): void + { + $this + ->shouldThrow(\InvalidArgumentException::class) + ->during('__invoke', [new CompletedEvent($subject->getWrappedObject(), new Marking())]) + ; + } + + function it_resolves_order_shipment_state_after_order_being_shipped( + StateResolverInterface $stateResolver, + ): void { + $shipment = new Shipment(); + $order = new Order(); + $shipment->setOrder($order); + + $event = new CompletedEvent($shipment, new Marking()); + + $stateResolver->resolve($order)->shouldBeCalled(); + + $this->__invoke($event); + } +} diff --git a/src/Sylius/Bundle/ShippingBundle/Provider/Calendar.php b/src/Sylius/Bundle/ShippingBundle/Provider/Calendar.php index 150dbd8bdf..d2b29df8da 100644 --- a/src/Sylius/Bundle/ShippingBundle/Provider/Calendar.php +++ b/src/Sylius/Bundle/ShippingBundle/Provider/Calendar.php @@ -24,7 +24,7 @@ trigger_deprecation( ); /** - * @deprecated since Sylius 1.11 and will be removed in Sylius 2.0. Use {@see \Sylius\Calendar\Provider\Calendar} instead. + * @deprecated since Sylius 1.13 and will be removed in Sylius 2.0. Use {@see 'Symfony\Component\Clock\Clock'} instead. */ final class Calendar implements DateTimeProvider { diff --git a/src/Sylius/Bundle/ShippingBundle/Resources/config/workflow/state_machine.yaml b/src/Sylius/Bundle/ShippingBundle/Resources/config/workflow/state_machine.yaml new file mode 100644 index 0000000000..289b675db0 --- /dev/null +++ b/src/Sylius/Bundle/ShippingBundle/Resources/config/workflow/state_machine.yaml @@ -0,0 +1,25 @@ +framework: + workflows: + !php/const Sylius\Component\Shipping\ShipmentTransitions::GRAPH: + type: state_machine + marking_store: + type: method + property: shippingState + supports: + - Sylius\Component\Shipping\Model\ShipmentInterface + initial_marking: !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_CART + places: + - !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_CART + - !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_READY + - !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_SHIPPED + - !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_CANCELLED + transitions: + !php/const Sylius\Component\Shipping\ShipmentTransitions::TRANSITION_CREATE: + from: !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_CART + to: !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_READY + !php/const Sylius\Component\Shipping\ShipmentTransitions::TRANSITION_SHIP: + from: !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_READY + to: !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_SHIPPED + !php/const Sylius\Component\Shipping\ShipmentTransitions::TRANSITION_CANCEL: + from: !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_READY + to: !php/const Sylius\Component\Shipping\Model\ShipmentInterface::STATE_CANCELLED diff --git a/src/Sylius/Bundle/TaxonomyBundle/Controller/TaxonSlugController.php b/src/Sylius/Bundle/TaxonomyBundle/Controller/TaxonSlugController.php index b48e9dfddb..72d043f66a 100644 --- a/src/Sylius/Bundle/TaxonomyBundle/Controller/TaxonSlugController.php +++ b/src/Sylius/Bundle/TaxonomyBundle/Controller/TaxonSlugController.php @@ -62,6 +62,12 @@ final class TaxonSlugController $parentId = $request->query->get('parentId'); if (null !== $parentId) { + trigger_deprecation( + 'sylius/taxonomy-bundle', + '1.13', + 'Using "parentId" for slug generation is deprecated and will not be possible in 2.0. Use "parentCode" instead.', + ); + return $this->taxonRepository->find($parentId); } diff --git a/src/Sylius/Component/Order/Modifier/OrderModifier.php b/src/Sylius/Component/Order/Modifier/OrderModifier.php index ba6db458bc..de94d0a0df 100644 --- a/src/Sylius/Component/Order/Modifier/OrderModifier.php +++ b/src/Sylius/Component/Order/Modifier/OrderModifier.php @@ -35,6 +35,7 @@ final class OrderModifier implements OrderModifierInterface public function removeFromOrder(OrderInterface $cart, OrderItemInterface $item): void { $cart->removeItem($item); + $this->orderProcessor->process($cart); }