Fix code after feedback, add ability to disable guest orders

This commit is contained in:
stloyd 2014-09-12 11:09:52 +02:00
parent 1ae1afdb47
commit 6f2f67893a
18 changed files with 132 additions and 150 deletions

View file

@ -48,6 +48,8 @@ parameters:
sylius.promotion.item_based: false
sylius.order.allow_guest_order: false
sylius.order.pending.duration: 3 hours
sylius.uploader.filesystem: sylius_image

View file

@ -14,7 +14,7 @@ class Version20140724192706 extends AbstractMigration
{
// this up() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql", "Migration can only be executed safely on 'mysql'.");
$this->addSql("ALTER TABLE sylius_order ADD email VARCHAR(255) DEFAULT NULL");
$this->addSql("UPDATE sylius_order o SET email = (SELECT email FROM sylius_user u WHERE u.id = o.user_id) WHERE user_id IS NOT NULL");
}
@ -23,7 +23,7 @@ class Version20140724192706 extends AbstractMigration
{
// this down() migration is auto-generated, please modify it to your needs
$this->abortIf($this->connection->getDatabasePlatform()->getName() != "mysql", "Migration can only be executed safely on 'mysql'.");
$this->addSql("ALTER TABLE sylius_order DROP email");
}
}

View file

@ -11,6 +11,9 @@
namespace Sylius\Bundle\CoreBundle\Checkout\Step;
use FOS\UserBundle\Event\FilterUserResponseEvent;
use FOS\UserBundle\Event\FormEvent;
use FOS\UserBundle\FOSUserEvents;
use Sylius\Bundle\FlowBundle\Process\Context\ProcessContextInterface;
use Sylius\Component\Core\Model\OrderInterface;
use Sylius\Component\Core\Model\UserInterface;
@ -44,7 +47,7 @@ class SecurityStep extends CheckoutStep
$this->overrideSecurityTargetPath();
return $this->renderStep($context, $this->getGuestForm($this->getCurrentCart()));
return $this->renderStep($context, $this->getRegistrationForm(), $this->getGuestForm($order));
}
/**
@ -55,32 +58,44 @@ class SecurityStep extends CheckoutStep
$order = $this->getCurrentCart();
$this->dispatchCheckoutEvent(SyliusCheckoutEvents::SECURITY_INITIALIZE, $order);
$request = $this->getRequest();
$guestForm = $this->getGuestForm($order);
$request = $this->getRequest();
$guestForm = $this->getGuestForm($order);
$registrationForm = $this->getRegistrationForm();
if ($guestForm->handleRequest($request)->isValid()) {
if ($this->isGuestOrderAllowed() && $guestForm->handleRequest($request)->isValid()) {
$this->getManager()->persist($order);
$this->getManager()->flush();
return $this->complete();
} elseif ($registrationForm->handleRequest($request)->isValid()) {
$user = $registrationForm->getData();
$this->dispatchEvent(FOSUserEvents::REGISTRATION_SUCCESS, new FormEvent($registrationForm, $request));
$this->dispatchEvent(FOSUserEvents::REGISTRATION_COMPLETED, new FilterUserResponseEvent($user, $request, new Response()));
$this->saveUser($user);
return $this->complete();
}
return $this->renderStep($context, $this->getGuestForm($order));
return $this->renderStep($context, $registrationForm, $guestForm);
}
/**
* Render step.
*
* @param ProcessContextInterface $context
* @param FormInterface $guestForm
* @param FormInterface $registrationForm
* @param null|FormInterface $guestForm
*
* @return Response
*/
protected function renderStep(ProcessContextInterface $context, FormInterface $guestForm)
protected function renderStep(ProcessContextInterface $context, FormInterface $registrationForm, FormInterface $guestForm = null)
{
return $this->render($this->container->getParameter(sprintf('sylius.checkout.step.%s.template', $this->getName())), array(
'context' => $context,
'registration_form' => $this->getRegistrationForm()->createView(),
'guest_form' => $guestForm->createView(),
'registration_form' => $registrationForm->createView(),
'guest_form' => null !== $guestForm ? $guestForm->createView() : null,
));
}
@ -91,7 +106,13 @@ class SecurityStep extends CheckoutStep
*/
protected function getRegistrationForm()
{
return $this->get('fos_user.registration.form.factory')->createForm();
$user = $this->get('fos_user.user_manager')->createUser();
$user->setEnabled(true);
$form = $this->get('fos_user.registration.form.factory')->createForm();
$form->setData($user);
return $form;
}
/**
@ -99,13 +120,25 @@ class SecurityStep extends CheckoutStep
*
* @param OrderInterface $order
*
* @return FormInterface
* @return null|FormInterface
*/
protected function getGuestForm(OrderInterface $order)
{
if (!$this->isGuestOrderAllowed()) {
return null;
}
return $this->createForm('sylius_checkout_guest', $order);
}
/**
* @return bool
*/
protected function isGuestOrderAllowed()
{
return $this->container->getParameter('sylius.order.allow_guest_order');
}
/**
* Override security target path, it will redirect user to checkout after login.
*/

View file

@ -44,8 +44,8 @@ class Configuration implements ConfigurationInterface
$emailNode
->addDefaultsIfNotSet()
->canBeEnabled()
->children()
->booleanNode('enabled')->defaultFalse()->end()
->arrayNode('from_email')
->addDefaultsIfNotSet()
->children()
@ -76,8 +76,8 @@ class Configuration implements ConfigurationInterface
->arrayNode($name)
->addDefaultsIfNotSet()
->canBeUnset()
->canBeEnabled()
->children()
->booleanNode('enabled')->defaultTrue()->end()
->scalarNode('template')->defaultValue($template)->end()
->arrayNode('from_email')
->canBeUnset()

View file

@ -128,6 +128,7 @@ sylius_addressing:
model: Sylius\Component\Core\Model\Address
sylius_order:
guest_order: %sylius.order.allow_guest_order%
classes:
order:
model: Sylius\Component\Core\Model\Order

View file

@ -50,7 +50,6 @@
<field name="currency" length="3" />
<field type="string" name="paymentState" column="payment_state" />
<field type="string" name="shippingState" column="shipping_state" />
<field type="string" name="email" column="email" nullable="true"/>
<many-to-many field="promotions" target-entity="Sylius\Component\Promotion\Model\PromotionInterface">
<join-table name="sylius_promotion_order">

View file

@ -37,6 +37,13 @@ class Configuration implements ConfigurationInterface
->addDefaultsIfNotSet()
->children()
->scalarNode('driver')->isRequired()->cannotBeEmpty()->end()
->booleanNode('guest_order')
->beforeNormalization()
->ifString()
->then(function($v) { return (bool) $v; })
->end()
->defaultFalse()
->end()
->end()
;

View file

@ -26,11 +26,13 @@ class SyliusOrderExtension extends AbstractResourceExtension
*/
public function load(array $config, ContainerBuilder $container)
{
$this->configure(
list($config) = $this->configure(
$config,
new Configuration(),
$container,
self::CONFIGURE_LOADER | self::CONFIGURE_DATABASE | self::CONFIGURE_PARAMETERS | self::CONFIGURE_VALIDATORS
);
$container->setParameter('sylius.order.allow_guest_order', $config['guest_order']);
}
}

View file

@ -23,6 +23,7 @@
</id>
<field name="number" column="number" type="string" unique="true" nullable="true" />
<field type="string" name="email" column="email" nullable="true"/>
<field name="state" column="state" type="string" />
<field name="completedAt" column="completed_at" type="datetime" nullable="true" />

View file

@ -1,65 +0,0 @@
<?php
/*
* This file is part of the FOSUserBundle package.
*
* (c) FriendsOfSymfony <http://friendsofsymfony.github.com/>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Sylius\Bundle\WebBundle\EventListener;
use FOS\UserBundle\Event\FormEvent;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\Security\Http\HttpUtils;
/**
* Class RegistrationListener
*
* @author Dmitrijs Balabka <dmitry.balabka@gmail.com>
*/
class RegistrationListener
{
/**
* @var HttpUtils
*/
protected $httpUtils;
/**
* @var string
*/
protected $targetPathParameter = '_target_path';
/**
* @param HttpUtils $httpUtils
*/
public function __construct(HttpUtils $httpUtils)
{
$this->httpUtils = $httpUtils;
}
/**
* @param FormEvent $event
*
* @return array
*/
public function handleEvent(FormEvent $event)
{
$request = $event->getRequest();
if ($url = $this->determineTargetUrl($request)) {
$event->setResponse($this->httpUtils->createRedirectResponse($request, $url));
}
}
/**
* @param Request $request
*
* @return string|null
*/
protected function determineTargetUrl(Request $request)
{
return $request->request->get($this->targetPathParameter);
}
}

View file

@ -1,5 +1,16 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
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.
-->
<container xmlns="http://symfony.com/schema/dic/services"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/services
@ -20,7 +31,6 @@
<parameter key="sylius.form.frontend.profile.type.class">Sylius\Bundle\WebBundle\Form\ProfileFormType</parameter>
<parameter key="sylius.form.frontend.registration.type.class">Sylius\Bundle\CoreBundle\Form\Type\RegistrationFormType</parameter>
<parameter key="sylius.listener.registration.class">Sylius\Bundle\WebBundle\EventListener\RegistrationListener</parameter>
</parameters>
<services>
@ -126,11 +136,6 @@
<tag name="form.type" alias="sylius_user_registration" />
<argument>%fos_user.model.user.class%</argument>
</service>
<service id="sylius.listener.registration" class="%sylius.listener.registration.class%">
<tag name="kernel.event_listener" event="fos_user.registration.success" method="handleEvent"/>
<argument type="service" id="security.http_utils"/>
</service>
</services>
</container>

View file

@ -33,6 +33,7 @@
</div>
</div>
<div class="col-md-6 checkout-new-customer">
{% if guest_form is not empty %}
<div class="well">
<form action="{{ path(context.process.forwardRoute, {'stepName': context.currentStep.name}) }}" method="post" novalidate class="form-horizontal">
<fieldset>
@ -40,18 +41,16 @@
{{ form_widget(guest_form) }}
</fieldset>
<div class="form-actions">
<button type="submit" class="btn btn-success btn-block">
{{ 'sylius.checkout.security.proceed_order'|trans }}
</button>
<input type="submit" class="btn btn-success btn-block" value="{{ 'sylius.checkout.security.proceed_order'|trans }}" />
</div>
</form>
</div>
{% endif %}
<div class="well">
<form action="{{ path('fos_user_registration_register') }}" method="post" novalidate class="form-horizontal">
<form action="{{ path(context.process.forwardRoute, {'stepName': context.currentStep.name}) }}" method="post" novalidate class="form-horizontal">
<fieldset>
<legend>{{ 'sylius.checkout.security.new_customer'|trans }}</legend>
{{ form_widget(registration_form) }}
<input type="hidden" name="_target_path" value="sylius_checkout_security">
</fieldset>
<div class="form-actions">
<input type="submit" class="btn btn-success btn-block" value="{{ 'sylius.checkout.security.register'|trans }}" />

View file

@ -98,13 +98,6 @@ class Order extends Cart implements OrderInterface
*/
protected $promotions;
/**
* Customer email
*
* @var string
*/
protected $email;
/**
* Constructor.
*/
@ -132,31 +125,13 @@ class Order extends Cart implements OrderInterface
public function setUser(UserInterface $user = null)
{
$this->user = $user;
if ($this->user) {
$this->setEmail($this->user->getEmail());
if (null !== $this->user) {
$this->email = $this->user->getEmail();
}
return $this;
}
/**
* {@inheritdoc}
*/
public function getEmail()
{
return $this->email;
}
/**
* {@inheritdoc}
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* {@inheritdoc}
*/

View file

@ -45,22 +45,6 @@ interface OrderInterface extends CartInterface, PaymentsSubjectInterface, Promot
*/
public function setUser(UserInterface $user);
/**
* Get customer email
*
* @return string
*/
public function getEmail();
/**
* Set customer email
*
* @param string $email
*
* @return mixed
*/
public function setEmail($email);
/**
* Get shipping address.
*

View file

@ -204,7 +204,7 @@ class OrderSpec extends ObjectBehavior
function it_not_a_backorder_if_contains_no_backordered_units(
InventoryUnitInterface $unit1,
InventoryUnitInterface $unit2,
OrderItemInterface $item
OrderItemInterface $item
) {
$unit1->getInventoryState()->willReturn(InventoryUnitInterface::STATE_SOLD);
$unit2->getInventoryState()->willReturn(InventoryUnitInterface::STATE_SOLD);
@ -217,6 +217,13 @@ class OrderSpec extends ObjectBehavior
$this->shouldNotBeBackorder();
}
function it_should_allow_defining_email_from_user(UserInterface $user)
{
$user->getEmail()->willReturn('example@example.com');
$this->setUser($user);
$this->getEmail()->shouldReturn('example@example.com');
}
/**
* Helper method
*/
@ -233,17 +240,4 @@ class OrderSpec extends ObjectBehavior
$order->addAdjustment($shippingAdjustment);
$order->addAdjustment($taxAdjustment);
}
function it_should_allow_defining_email()
{
$this->setEmail('example@example.com');
$this->getEmail()->shouldReturn('example@example.com');
}
function it_should_allow_defining_email_from_user(UserInterface $user)
{
$user->getEmail()->willReturn('example@example.com');
$this->setUser($user);
$this->getEmail()->shouldReturn('example@example.com');
}
}

View file

@ -120,6 +120,13 @@ class Order implements OrderInterface
*/
protected $state = OrderInterface::STATE_CART;
/**
* Customer email.
*
* @var string
*/
protected $email;
/**
* Constructor.
*/
@ -138,6 +145,24 @@ class Order implements OrderInterface
return $this->id;
}
/**
* {@inheritdoc}
*/
public function getEmail()
{
return $this->email;
}
/**
* {@inheritdoc}
*/
public function setEmail($email)
{
$this->email = $email;
return $this;
}
/**
* {@inheritdoc}
*/

View file

@ -32,6 +32,20 @@ interface OrderInterface extends AdjustableInterface, TimestampableInterface, So
const STATE_CANCELLED = 'cancelled';
const STATE_RETURNED = 'returned';
/**
* Get customer email.
*
* @return string
*/
public function getEmail();
/**
* Set customer email.
*
* @param string $email
*/
public function setEmail($email);
/**
* Has the order been completed by user and can be handled.
*

View file

@ -371,4 +371,10 @@ class OrderSpec extends ObjectBehavior
$this->hasAdjustment($adjustment)->shouldReturn(false);
}
function it_should_allow_defining_email()
{
$this->setEmail('example@example.com');
$this->getEmail()->shouldReturn('example@example.com');
}
}