Merge branch 'cart'

Conflicts:
	core/lib/Thelia/Core/HttpFoundation/Session/Session.php
This commit is contained in:
Manuel Raynaud
2013-07-26 15:59:32 +02:00
9 changed files with 625 additions and 23 deletions

View File

@@ -26,6 +26,10 @@ namespace Thelia\Action;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Thelia\Core\Event\ActionEvent;
use Thelia\Core\HttpFoundation\Session\Session;
use Thelia\Model\CartQuery;
use Thelia\Model\Cart as CartModel;
use Thelia\Model\Customer;
class Cart implements EventSubscriberInterface
@@ -91,4 +95,87 @@ class Cart implements EventSubscriberInterface
"action.modifyArticle" => array("modifyArticle", 128),
);
}
public function getCart(Request $request)
{
if(null !== $cart = $request->getSession()->getCart()){
return $cart;
}
if ($request->cookies->has("thelia_cart")) {
//le cookie de panier existe, on le récupère
$token = $request->cookies->get("thelia_cart");
$cart = CartQuery::create()->findOneByToken($token);
if ($cart) {
//le panier existe en base
$customer = $request->getSession()->getCustomerUser();
if ($customer) {
if($cart->getCustomerId() != $customer->getId()) {
//le customer du panier n'est pas le mm que celui connecté, il faut cloner le panier sans le customer_id
$cart = $this->duplicateCart($cart, $request->getSession(), $customer);
}
} else {
if ($cart->getCustomerId() != null) {
//il faut dupliquer le panier sans le customer_id
$cart = $this->duplicateCart($cart, $request->getSession());
}
}
} else {
$cart = $this->createCart($request->getSession());
}
} else {
//le cookie de panier n'existe pas, il va falloir le créer et faire un enregistrement en base.
$cart = $this->createCart($request->getSession());
}
return $cart;
}
/**
* @param Session $session
* @return CartModel
*/
protected function createCart(Session $session)
{
$cart = new CartModel();
$cart->setToken($this->generateCookie());
if(null !== $customer = $session->getCustomerUser()) {
$cart->setCustomer($customer);
}
$cart->save();
$session->setCart($cart->getId());
return $cart;
}
/**
* @param CartModel $cart
* @param Session $session
* @param Customer $customer
* @return CartModel
*/
protected function duplicateCart(CartModel $cart, Session $session, Customer $customer = null)
{
$newCart = $cart->duplicate($this->generateCookie(), $customer);
$session->setCart($newCart->getId());
return $newCart;
}
protected function generateCookie()
{
$id = uniqid('', true);
setcookie("thelia_cart", $id, time()+(60*60*24*365));
return $id;
}
}

View File

@@ -25,13 +25,14 @@ namespace Thelia\Core\HttpFoundation\Session;
use Symfony\Component\HttpFoundation\Session\Session as BaseSession;
use Thelia\Core\Security\User\UserInterface;
use Thelia\Form\BaseForm;
use Thelia\Model\ConfigQuery;
use Thelia\Exception\InvalidCartException;
use Thelia\Model\CartQuery;
use Thelia\Model\Cart;
use Thelia\Tools\URL;
class Session extends BaseSession {
// -- Language ------------------------------------------------------------
class Session extends BaseSession
{
// -- Language ------------------------------------------------------------
public function getLocale()
{
@@ -47,41 +48,61 @@ class Session extends BaseSession {
public function setCustomerUser(UserInterface $user)
{
$this->set('customer_user', $user);
$this->set('customer_user', $user);
}
public function getCustomerUser()
{
return $this->get('customer_user');
return $this->get('customer_user');
}
public function clearCustomerUser()
{
return $this->remove('customer_user');
return $this->remove('customer_user');
}
// -- Admin user -----------------------------------------------------------
public function setAdminUser(UserInterface $user)
{
$this->set('admin_user', $user);
$this->set('admin_user', $user);
}
public function getAdminUser()
{
return $this->get('admin_user');
return $this->get('admin_user');
}
public function clearAdminUser()
{
return $this->remove('admin_user');
return $this->remove('admin_user');
}
// -- Error form -----------------------------------------------------------
/**
* @param string $formName the form name
*/
public function setErrorFormName($formName)
{
$this->set('error_form', $formName);
}
public function getErrorFormName()
{
return $this->get('error_form', null);
}
public function clearErrorFormName()
{
return $this->remove('error_form');
}
// -- Return page ----------------------------------------------------------
public function setReturnToUrl($url)
{
$this->set('return_to_url', $url);
$this->set('return_to_url', $url);
}
/**
@@ -90,7 +111,56 @@ class Session extends BaseSession {
*/
public function getReturnToUrl()
{
return $this->get('return_to_url', URL::getIndexPage());
return $this->get('return_to_url', URL::getIndexPage());
}
// -- Cart ------------------------------------------------------------------
/**
* return cart if exists and is valid (checking customer)
*
* @return \Thelia\Model\Cart|null
*/
public function getCart()
{
$cart_id = $this->get("cart_id");
$cart = null;
if ($cart_id) {
$cart = CartQuery::create()->findPk($cart_id);
try {
$this->verifyValidCart($cart);
} catch (InvalidCartException $e) {
$cart = null;
}
}
return $cart;
}
/**
*
*
* @param \Thelia\Model\Cart $cart
* @throws \Thelia\Exception\InvalidCartException
*/
protected function verifyValidCart(Cart $cart)
{
$customer = $this->getCustomerUser();
if ($customer && $cart->getCustomerId() != $customer->getId()) {
throw new InvalidCartException("customer in session and customer_id in cart are not the same");
} else if($customer === null && $cart->getCustomerId() !== null) {
throw new InvalidCartException("Customer exists in cart and not in session");
}
}
/**
* assign cart id in session
*
* @param $cart_id
*/
public function setCart($cart_id)
{
$this->set("cart_id", $cart_id);
}
}

View File

@@ -0,0 +1,30 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Exception;
class InvalidCartException extends \RuntimeException {
}

View File

@@ -7,4 +7,30 @@ use Thelia\Model\Base\Cart as BaseCart;
class Cart extends BaseCart
{
public function duplicate($token, Customer $customer = null)
{
$cartItems = $this->getCartItems();
$cart = new Cart();
$cart->setAddressDeliveryId($this->getAddressDeliveryId());
$cart->setAddressInvoiceId($this->getAddressInvoiceId());
$cart->setToken($token);
if ($customer){
$cart->setCustomer($customer);
}
// TODO : set current Currency
//$cart->setCurrency()
$cart->save();
foreach ($cartItems as $cartItem){
$item = new CartItem();
$item->setCart($cart);
$item->setProductId($cartItem->getProductId());
$item->setQuantity($cartItem->getQuantity());
$item->save();
}
return $cart;
}
}

View File

@@ -3,7 +3,7 @@
namespace Thelia\Model;
use Thelia\Model\Base\CartQuery as BaseCartQuery;
use Symfony\Component\HttpFoundation\Request;
/**
* Skeleton subclass for performing query and update operations on the 'cart' table.
@@ -18,4 +18,5 @@ use Thelia\Model\Base\CartQuery as BaseCartQuery;
class CartQuery extends BaseCartQuery
{
} // CartQuery

View File

@@ -116,7 +116,7 @@ class Customer extends BaseCustomer implements UserInterface
protected function generateRef()
{
return date("YmdHisu");
return uniqid(substr($this->getLastname(), 0, (strlen($this->getLastname()) >= 3) ? 3 : strlen($this->getLastname())), true);
}
public function setPassword($password)

View File

@@ -0,0 +1,239 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Tests\Action;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Thelia\Core\HttpFoundation\Request;
use Thelia\Core\HttpFoundation\Session\Session;
use Thelia\Model\Cart;
use Thelia\Model\Customer;
class CartTest extends \PHPUnit_Framework_TestCase
{
protected $session;
protected $request;
protected $actionCart;
protected $uniqid;
public function setUp()
{
$this->session = new Session(new MockArraySessionStorage());
$this->request = new Request();
$this->request->setSession($this->session);
$this->uniqid = uniqid('', true);
$this->actionCart = $this->getMock(
"\Thelia\Action\Cart",
array("generateCookie")
);
$this->actionCart
->expects($this->any())
->method("generateCookie")
->will($this->returnValue($this->uniqid));
}
/**
* no cart present in session and cart_id no yet exists in cookies.
*
* In this case, a new cart instance must be create
*/
public function testGetCartWithoutCustomerAndWithoutExistingCart()
{
$actionCart = $this->actionCart;
$cart = $actionCart->getCart($this->request);
$this->assertInstanceOf("Thelia\Model\Cart", $cart, '$cart must be an instance of cart model Thelia\Model\Cart');
$this->assertNull($cart->getCustomerId());
$this->assertNull($cart->getAddressDeliveryId());
$this->assertNull($cart->getAddressInvoiceId());
$this->assertEquals($this->uniqid, $cart->getToken());
}
/**
* Customer is connected but his cart does not exists yet
*
* Cart must be created and associated to the current connected Customer
*/
public function testGetCartWithCustomerAndWithoutExistingCart()
{
$actionCart = $this->actionCart;
$request = $this->request;
//create a fake customer just for test. If not persists test fails !
$customer = new Customer();
$customer->setFirstname("john");
$customer->setLastname("doe");
$customer->setTitleId(1);
$customer->save();
$request->getSession()->setCustomerUser($customer);
$cart = $actionCart->getCart($request);
$this->assertInstanceOf("Thelia\Model\Cart", $cart, '$cart must be an instance of cart model Thelia\Model\Cart');
$this->assertNotNull($cart->getCustomerId());
$this->assertEquals($customer->getId(), $cart->getCustomerId());
$this->assertNull($cart->getAddressDeliveryId());
$this->assertNull($cart->getAddressInvoiceId());
$this->assertEquals($this->uniqid, $cart->getToken());
}
/**
* Cart exists and his id put in cookies.
*
* Must return the same cart instance
*/
public function testGetCartWithoutCustomerAndWithExistingCart()
{
$actionCart = $this->actionCart;
$request = $this->request;
$uniqid = uniqid("test1", true);
//create a fake cart in database;
$cart = new Cart();
$cart->setToken($uniqid);
$cart->save();
$request->cookies->set("thelia_cart", $uniqid);
$getCart = $actionCart->getCart($request);
$this->assertInstanceOf("Thelia\Model\Cart", $getCart, '$cart must be an instance of cart model Thelia\Model\Cart');
$this->assertNull($getCart->getCustomerId());
$this->assertNull($getCart->getAddressDeliveryId());
$this->assertNull($getCart->getAddressInvoiceId());
$this->assertEquals($cart->getToken(), $getCart->getToken());
}
/**
* a cart id exists in cookies but this id does not exists yet in databases
*
* a new cart must be created (different token)
*/
public function testGetCartWithExistingCartButNotGoodCookies()
{
$actionCart = $this->actionCart;
$request = $this->request;
$token = "WrongToken";
$request->cookies->set("thelia_cart", $token);
$cart = $actionCart->getCart($request);
$this->assertInstanceOf("Thelia\Model\Cart", $cart, '$cart must be an instance of cart model Thelia\Model\Cart');
$this->assertNull($cart->getCustomerId());
$this->assertNull($cart->getAddressDeliveryId());
$this->assertNull($cart->getAddressInvoiceId());
$this->assertNotEquals($token, $cart->getToken());
}
/**
* cart and customer already exists. Cart and customer are linked.
*
* cart in session must be return
*/
public function testGetCartWithExistingCartAndCustomer()
{
$actionCart = $this->actionCart;
$request = $this->request;
//create a fake customer just for test. If not persists test fails !
$customer = new Customer();
$customer->setFirstname("john");
$customer->setLastname("doe");
$customer->setTitleId(1);
$customer->save();
$uniqid = uniqid("test2", true);
//create a fake cart in database;
$cart = new Cart();
$cart->setToken($uniqid);
$cart->setCustomer($customer);
$cart->save();
$request->cookies->set("thelia_cart", $uniqid);
$request->getSession()->setCustomerUser($customer);
$getCart = $actionCart->getCart($request);
$this->assertInstanceOf("Thelia\Model\Cart", $getCart, '$cart must be an instance of cart model Thelia\Model\Cart');
$this->assertNotNull($getCart->getCustomerId());
$this->assertNull($getCart->getAddressDeliveryId());
$this->assertNull($getCart->getAddressInvoiceId());
$this->assertEquals($cart->getToken(), $getCart->getToken(), "token must be the same");
$this->assertEquals($customer->getId(), $getCart->getCustomerId());
}
/**
* Customer is connected but cart not associated to him
*
* A new cart must be created (duplicated) containing customer id
*/
public function testGetCartWithExistinsCartAndCustomerButNotSameCustomerId()
{
$actionCart = $this->actionCart;
$request = $this->request;
//create a fake customer just for test. If not persists test fails !
$customer = new Customer();
$customer->setFirstname("john");
$customer->setLastname("doe");
$customer->setTitleId(1);
$customer->save();
$uniqid = uniqid("test3", true);
//create a fake cart in database;
$cart = new Cart();
$cart->setToken($uniqid);
$cart->save();
$request->cookies->set("thelia_cart", $uniqid);
$request->getSession()->setCustomerUser($customer);
$getCart = $actionCart->getCart($request);
$this->assertInstanceOf("Thelia\Model\Cart", $getCart, '$cart must be an instance of cart model Thelia\Model\Cart');
$this->assertNotNull($getCart->getCustomerId());
$this->assertNull($getCart->getAddressDeliveryId());
$this->assertNull($getCart->getAddressInvoiceId());
$this->assertNotEquals($cart->getToken(), $getCart->getToken(), "token must be different");
$this->assertEquals($customer->getId(), $getCart->getCustomerId());
}
}

View File

@@ -1,12 +1,25 @@
<?php
/**
* Created by JetBrains PhpStorm.
* User: manu
* Date: 11/07/13
* Time: 10:34
* To change this template use File | Settings | File Templates.
*/
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Tests\Command;

View File

@@ -0,0 +1,136 @@
<?php
/*************************************************************************************/
/* */
/* Thelia */
/* */
/* Copyright (c) OpenStudio */
/* email : info@thelia.net */
/* web : http://www.thelia.net */
/* */
/* This program is free software; you can redistribute it and/or modify */
/* it under the terms of the GNU General Public License as published by */
/* the Free Software Foundation; either version 3 of the License */
/* */
/* This program is distributed in the hope that it will be useful, */
/* but WITHOUT ANY WARRANTY; without even the implied warranty of */
/* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the */
/* GNU General Public License for more details. */
/* */
/* You should have received a copy of the GNU General Public License */
/* along with this program. If not, see <http://www.gnu.org/licenses/>. */
/* */
/*************************************************************************************/
namespace Thelia\Tests\Core\HttpFoundation\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
use Thelia\Core\HttpFoundation\Session\Session;
use Thelia\Model\Cart;
use Thelia\Model\Customer;
class SessionTest extends \PHPUnit_Framework_TestCase
{
protected $session;
public function setUp()
{
$this->session = new Session(new MockArraySessionStorage());
}
public function testGetCartWithoutExistingCart()
{
$session = $this->session;
$cart = $session->getCart();
$this->assertNull($cart);
}
public function testGetCartWithExistingCartWithoutCustomerConnected()
{
$session = $this->session;
$testCart = new Cart();
$testCart->setToken(uniqid("testSessionGetCart1", true));
$testCart->save();
$session->setCart($testCart->getId());
$cart = $session->getCart();
$this->assertNotNull($cart);
$this->assertInstanceOf("\Thelia\Model\Cart", $cart, '$cart must be an instance of Thelia\Model\Cart');
$this->assertEquals($testCart->getToken(), $cart->getToken());
}
public function testGetCartWithExistingCustomerButNoCart()
{
$session = $this->session;
//create a fake customer just for test. If not persists test fails !
$customer = new Customer();
$customer->setFirstname("john test session");
$customer->setLastname("doe");
$customer->setTitleId(1);
$customer->save();
$session->setCustomerUser($customer);
$cart = $session->getCart();
$this->assertNull($cart);
}
public function testGetCartWithExistingCartAndCustomerButWithoutReferenceToCustomerInCart()
{
$session = $this->session;
//create a fake customer just for test. If not persists test fails !
$customer = new Customer();
$customer->setFirstname("john test session");
$customer->setLastname("doe");
$customer->setTitleId(1);
$customer->save();
$session->setCustomerUser($customer);
$testCart = new Cart();
$testCart->setToken(uniqid("testSessionGetCart2", true));
$testCart->save();
$session->setCart($testCart->getId());
$cart = $session->getCart();
$this->assertNull($cart);
}
public function testGetCartWithExistingCartAndCustomerAndReferencesEachOther()
{
$session = $this->session;
//create a fake customer just for test. If not persists test fails !
$customer = new Customer();
$customer->setFirstname("john test session");
$customer->setLastname("doe");
$customer->setTitleId(1);
$customer->save();
$session->setCustomerUser($customer);
$testCart = new Cart();
$testCart->setToken(uniqid("testSessionGetCart3", true));
$testCart->setCustomerId($customer->getId());
$testCart->save();
$session->setCart($testCart->getId());
$cart = $session->getCart();
$this->assertNotNull($cart);
$this->assertInstanceOf("\Thelia\Model\Cart", $cart, '$cart must be an instance of Thelia\Model\Cart');
}
}