New version using resource bundle and phpspec

This commit is contained in:
Paweł Jędrzejewski 2012-11-01 22:40:31 +01:00
parent 595c8f0025
commit 1cd0f16551
63 changed files with 820 additions and 2309 deletions

View file

@ -1,7 +1,5 @@
phpunit.xml
Tests/autoload.php
vendor/
bin/
composer.phar
composer.lock

View file

@ -4,10 +4,9 @@ php:
- 5.3
- 5.4
before_script:
- wget http://getcomposer.org/composer.phar
- php composer.phar install --dev
before_script: composer install --dev
script: php bin/phpspec run
notifications:
email:
- travis-ci@sylius.org
email: travis-ci@sylius.org

View file

@ -1,6 +1,14 @@
CHANGELOG
=========
### 01-11-2012
* Bundle now uses [SyliusResourceBundle](http://github.com/Sylius/SyliusResourceBundle) for model persistence.
* New controller.
* Renamed **Item** to **CartItem**.
* Renamed **ItemType** to **CartItemType**.
* Introduce specs with [phpspec2](http://phpspec.net).
### 28-05-2012
* Renamed **CartFormType** to **CartType** to be consistent.

View file

@ -1,54 +0,0 @@
<?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\Bundle\CartBundle\Command;
use Sylius\Bundle\CartBundle\EventDispatcher\SyliusCartEvents;
use Symfony\Bundle\FrameworkBundle\Command\ContainerAwareCommand;
use Symfony\Component\Console\Input\InputInterface;
use Symfony\Component\Console\Output\OutputInterface;
/**
* Command for console that deletes expired carts.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class FlushCartsCommand extends ContainerAwareCommand
{
/**
* {@inheritdoc}
*/
protected function configure()
{
$this
->setName('sylius:cart:flush')
->setDescription('Deletes expired carts.')
->setHelp(
<<<EOT
The <info>sylius:cart:flush</info> command deletes expired carts:
<info>php sylius/console sylius:cart:flush</info>
EOT
)
;
}
/**
* {@inheritdoc}
*/
protected function execute(InputInterface $input, OutputInterface $output)
{
$this->getContainer()->get('event_dispatcher')->dispatch(SyliusCartEvents::CART_FLUSH);
$this->getContainer()->get('sylius_cart.manager.cart')->flushCarts();
$output->writeln('<info>[Sylius:Cart]</info> Deleted expired carts.');
}
}

View file

@ -0,0 +1,251 @@
<?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\Bundle\CartBundle\Controller;
use Sylius\Bundle\ResourceBundle\Controller\ResourceController;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
/**
* Cart frontend controller.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class CartController extends ResourceController
{
/**
* Displays cart.
*
* @param Request
*
* @return Response
*/
public function showAction(Request $request)
{
$cart = $this->getCurrentCart();
$form = $this->createForm($this->getResourceFormType(), $cart);
return $this->renderResponse('show.html', array(
'cart' => $cart,
'form' => $form->createView()
));
}
/**
* Adds item to cart.
*
* @param Request $request
*
* @return Response
*/
public function addItemAction(Request $request)
{
$cart = $this->getCurrentCart();
$item = $this->getResolver()->resolveItemToAdd($request);
if (!$item) {
$this->setFlash('error', 'sylius_cart.flashes.add.error');
return $this->redirectToCart();
}
$cartOperator = $this->getOperator();
$cartOperator
->addItem($cart, $item)
->refresh($cart)
;
$errors = $this->get('validator')->validate($cart);
if (0 === count($errors)) {
$this->setFlash('success', 'sylius_cart.flashes.add.success');
$cartOperator->save($cart);
}
return $this->redirectToCart();
}
/**
* Removes item from cart.
*
* @param Request $request
*
* @return Response
*/
public function removeItemAction(Request $request)
{
$cart = $this->getCurrentCart();
$item = $this->getResolver()->resolveItemToRemove($request);
if (!$item || false === $cart->hasItem($item)) {
$this->setFlash('error', 'sylius_cart.flashes.remove.error');
return $this->redirectToCart();
}
$this
->getOperator()
->removeItem($cart, $item)
->refresh($cart)
->save($cart)
;
$this->setFlash('success', 'sylius_cart.flashes.remove.success');
return $this->redirectToCart();
}
/**
* Saves cart.
*
* @param Request $request
*
* @return Response
*/
public function saveAction(Request $request)
{
$cart = $this->getCurrentCart();
$form = $this
->createForm($this->getResourceFormType(), $cart)
->bind($request)
;
if ($form->isValid()) {
$this
->getOperator()
->refresh($cart)
->save($cart)
;
$this->setFlash('success', 'sylius_cart.flashes.saved');
}
return $this->renderResponse('show.html', array(
'cart' => $cart,
'form' => $form->createView()
));
}
/**
* Clears cart.
*
* @return Response
*/
public function clearAction()
{
$this
->getOperator()
->clear($this->getCurrentCart())
;
$this->setFlash('success', 'sylius_cart.flashes.cleared');
return $this->redirectToCart();
}
/**
* Redirect to show cart action.
*
* @return RedirectResponse
*/
protected function redirectToCart()
{
return $this->redirect($this->generateUrl($this->getCartRoute()));
}
/**
* Cart show action route.
*
* @return string
*/
protected function getCartRoute()
{
return 'sylius_cart_show';
}
/**
* Get current cart.
*
* @return CartInterface
*/
protected function getCurrentCart()
{
return $this
->getProvider()
->getCart()
;
}
/**
* Get cart provider.
*
* @return CartProviderInterface
*/
protected function getProvider()
{
return $this->get('sylius_cart.provider');
}
/**
* Get cart operator.
*
* @return CartOperatorInterface
*/
protected function getOperator()
{
return $this->get('sylius_cart.operator');
}
/**
* Get cart item resolver.
*
* @return CartResolverInterface
*/
protected function getResolver()
{
return $this->get('sylius_cart.resolver');
}
/**
* {@inheritdoc}
*/
protected function getResourceFormType()
{
return 'sylius_cart';
}
/**
* {@inheritdoc}
*/
protected function getBundlePrefix()
{
return 'sylius_cart';
}
/**
* {@inheritdoc}
*/
protected function getResourceName()
{
return 'cart';
}
/**
* {@inheritdoc}
*/
protected function getTemplateNamespace()
{
return 'SyliusCartBundle:Cart';
}
}

View file

@ -1,168 +0,0 @@
<?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\Bundle\CartBundle\Controller\Frontend;
use Sylius\Bundle\CartBundle\EventDispatcher\Event\CartOperationEvent;
use Sylius\Bundle\CartBundle\EventDispatcher\Event\FilterCartEvent;
use Sylius\Bundle\CartBundle\EventDispatcher\SyliusCartEvents;
use Symfony\Component\DependencyInjection\ContainerAware;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
/**
* Cart frontend controller.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class CartController extends ContainerAware
{
/**
* Displays cart.
*
* @return Response
*/
public function showAction()
{
$cart = $this->container->get('sylius_cart.provider')->getCart();
$form = $this->container->get('form.factory')->create('sylius_cart');
$form->setData($cart);
return $this->container->get('templating')->renderResponse('SyliusCartBundle:Frontend/Cart:show.html.'.$this->getEngine(), array(
'cart' => $cart,
'form' => $form->createView()
));
}
/**
* Adds item to cart.
*
* @param Request $request
*
* @return Response
*/
public function addItemAction(Request $request)
{
$cart = $this->container->get('sylius_cart.provider')->getCart();
$item = $this->container->get('sylius_cart.resolver')->resolveItemToAdd($request);
if (!$item) {
$this->container->get('session')->setFlash('error', 'sylius_cart.flashes.add.error');
return new RedirectResponse($request->headers->get('referer'));
}
$this->container->get('event_dispatcher')->dispatch(SyliusCartEvents::ITEM_ADD, new CartOperationEvent($cart, $item));
$cartOperator = $this->container->get('sylius_cart.operator');
$cartOperator->addItem($cart, $item);
$cartOperator->refresh($cart);
$errors = $this->container->get('validator')->validate($cart);
if (0 === count($errors)) {
$this->container->get('session')->setFlash('success', 'sylius_cart.flashes.add.success');
$cartOperator->save($cart);
}
return new RedirectResponse($this->container->get('router')->generate('sylius_cart_show'));
}
/**
* Removes item from cart.
*
* @param Request $request
*
* @return Response
*/
public function removeItemAction(Request $request)
{
$cart = $this->container->get('sylius_cart.provider')->getCart();
$item = $this->container->get('sylius_cart.resolver')->resolveItemToRemove($request);
if (!$item || false === $cart->hasItem($item)) {
$this->container->get('session')->setFlash('error', 'sylius_cart.flashes.remove.error');
return new RedirectResponse($request->headers->get('referer'));
}
$this->container->get('event_dispatcher')->dispatch(SyliusCartEvents::ITEM_REMOVE, new CartOperationEvent($cart, $item));
$cartOperator = $this->container->get('sylius_cart.operator');
$cartOperator->removeItem($cart, $item);
$cartOperator->refresh($cart);
$cartOperator->save($cart);
$this->container->get('session')->setFlash('success', 'sylius_cart.flashes.remove.success');
return new RedirectResponse($this->container->get('router')->generate('sylius_cart_show'));
}
/**
* Saves cart.
*
* @param Request $request
*
* @return Response
*/
public function saveAction(Request $request)
{
$cart = $this->container->get('sylius_cart.provider')->getCart();
$form = $this->container->get('form.factory')->create('sylius_cart');
$form->setData($cart);
$form->bindRequest($request);
if ($form->isValid()) {
$this->container->get('event_dispatcher')->dispatch(SyliusCartEvents::CART_SAVE, new FilterCartEvent($cart));
$cartOperator = $this->container->get('sylius_cart.operator');
$cartOperator->refresh($cart);
$cartOperator->save($cart);
$this->container->get('session')->setFlash('success', 'sylius_cart.flashes.saved');
}
return $this->container->get('templating')->renderResponse('SyliusCartBundle:Frontend/Cart:show.html.'.$this->getEngine(), array(
'cart' => $cart,
'form' => $form->createView()
));
}
/**
* Clears cart.
*
* @return Response
*/
public function clearAction()
{
$cart = $this->container->get('sylius_cart.provider')->getCart();
$this->container->get('event_dispatcher')->dispatch(SyliusCartEvents::CART_CLEAR, new FilterCartEvent($cart));
$this->container->get('sylius_cart.operator')->clear($cart);
$this->container->get('session')->setFlash('success', 'sylius_cart.flashes.cleared');
return new RedirectResponse($this->container->get('router')->generate('sylius_cart_show'));
}
/**
* Returns templating engine name.
*
* @return string
*/
protected function getEngine()
{
return $this->container->getParameter('sylius_cart.engine');
}
}

View file

@ -70,22 +70,10 @@ class Configuration implements ConfigurationInterface
->scalarNode('item')->isRequired()->cannotBeEmpty()->end()
->end()
->end()
->arrayNode('manager')
->addDefaultsIfNotSet()
->children()
->scalarNode('cart')->defaultValue('Sylius\\Bundle\\CartBundle\\Entity\\CartManager')->end()
->scalarNode('item')->defaultValue('Sylius\\Bundle\\CartBundle\\Entity\\ItemManager')->end()
->end()
->end()
->arrayNode('controller')
->addDefaultsIfNotSet()
->children()
->arrayNode('frontend')
->addDefaultsIfNotSet()
->children()
->scalarNode('cart')->defaultValue('Sylius\Bundle\\CartBundle\\Controller\\Frontend\\CartController')->end()
->end()
->end()
->scalarNode('cart')->defaultValue('Sylius\\Bundle\\CartBundle\\Controller\\CartController')->end()
->end()
->end()
->arrayNode('form')
@ -95,17 +83,11 @@ class Configuration implements ConfigurationInterface
->addDefaultsIfNotSet()
->children()
->scalarNode('cart')->defaultValue('Sylius\Bundle\CartBundle\Form\Type\CartType')->end()
->scalarNode('item')->defaultValue('Sylius\Bundle\CartBundle\Form\Type\ItemType')->end()
->scalarNode('item')->defaultValue('Sylius\Bundle\CartBundle\Form\Type\CartItemType')->end()
->end()
->end()
->end()
->end()
->arrayNode('listener')
->addDefaultsIfNotSet()
->children()
->scalarNode('request')->defaultValue('Sylius\Bundle\\CartBundle\\EventDispatcher\\Listener\\RequestListener')->end()
->end()
->end()
->end()
->end()
->end();

View file

@ -35,14 +35,13 @@ class SyliusCartExtension extends Extension
$configuration = new Configuration();
$config = $processor->processConfiguration($configuration, $config);
$loader = new XmlFileLoader($container, new FileLocator(__DIR__.'/../Resources/config/container'));
if (!in_array($config['driver'], SyliusCartBundle::getSupportedDrivers())) {
throw new \InvalidArgumentException(sprintf('Driver "%s" is unsupported for this extension.', $config['driver']));
}
if (!in_array($config['engine'], array('php', 'twig'))) {
if ('twig' !== $config['engine']) {
throw new \InvalidArgumentException(sprintf('Engine "%s" is unsupported for this extension.', $config['engine']));
}
@ -58,62 +57,14 @@ class SyliusCartExtension extends Extension
$container->setParameter('sylius_cart.provider.class', $config['classes']['provider']);
$configurations = array(
'controllers',
'forms',
'provider',
'storage'
);
$loader->load('services.xml');
foreach($configurations as $basename) {
$loader->load(sprintf('%s.xml', $basename));
}
$container->setParameter('sylius_cart.model.cart.class', $config['classes']['model']['cart']);
$container->setParameter('sylius_cart.model.item.class', $config['classes']['model']['item']);
$this->remapParametersNamespaces($config['classes'], $container, array(
'listener' => 'sylius_cart.listener.%s.class',
'model' => 'sylius_cart.model.%s.class',
'manager' => 'sylius_cart.manager.%s.class',
));
$container->setParameter('sylius_cart.controller.cart.class', $config['classes']['controller']['cart']);
$this->remapParametersNamespaces($config['classes']['controller'], $container, array(
'backend' => 'sylius_cart.controller.backend.%s.class',
'frontend' => 'sylius_cart.controller.frontend.%s.class'
));
$this->remapParametersNamespaces($config['classes']['form'], $container, array(
'type' => 'sylius_cart.form.type.%s.class',
));
}
protected function remapParameters(array $config, ContainerBuilder $container, array $map)
{
foreach ($map as $name => $paramName) {
if (isset($config[$name])) {
$container->setParameter($paramName, $config[$name]);
}
}
}
protected function remapParametersNamespaces(array $config, ContainerBuilder $container, array $namespaces)
{
foreach ($namespaces as $ns => $map) {
if ($ns) {
if (!isset($config[$ns])) {
continue;
}
$namespaceConfig = $config[$ns];
} else {
$namespaceConfig = $config;
}
if (is_array($map)) {
$this->remapParameters($namespaceConfig, $container, $map);
} else {
foreach ($namespaceConfig as $name => $value) {
if (null !== $value) {
$container->setParameter(sprintf($map, $name), $value);
}
}
}
}
$container->setParameter('sylius_cart.form.type.cart.class', $config['classes']['form']['type']['cart']);
$container->setParameter('sylius_cart.form.type.item.class', $config['classes']['form']['type']['item']);
}
}

View file

@ -11,9 +11,7 @@
namespace Sylius\Bundle\CartBundle\Entity;
use Doctrine\Common\Collections\ArrayCollection;
use Sylius\Bundle\CartBundle\Model\Cart as BaseCart;
use Sylius\Bundle\CartBundle\Model\ItemInterface;
/**
* Cart entity.
@ -22,56 +20,4 @@ use Sylius\Bundle\CartBundle\Model\ItemInterface;
*/
class Cart extends BaseCart
{
/**
* Constructor.
*/
public function __construct()
{
parent::__construct();
$this->items = new ArrayCollection();
}
/**
* {@inheritdoc}
*/
public function removeItem(ItemInterface $item)
{
if ($this->hasItem($item)) {
$this->items->removeElement($item);
$item->setCart(null);
}
}
/**
* {@inheritdoc}
*/
public function hasItem(ItemInterface $item)
{
return $this->items->contains($item);
}
/**
* {@inheritdoc}
*/
public function searchItem(ItemInterface $item)
{
return $this->items->indexOf($item);
}
/**
* {@inheritdoc}
*/
public function isEmpty()
{
return $this->items->isEmpty();
}
/**
* {@inheritdoc}
*/
public function clearItems()
{
$this->items->clear();
}
}

View file

@ -11,13 +11,13 @@
namespace Sylius\Bundle\CartBundle\Entity;
use Sylius\Bundle\CartBundle\Model\Item as BaseItem;
use Sylius\Bundle\CartBundle\Model\CartItem as BaseCartItem;
/**
* Entity for cart items.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
abstract class Item extends BaseItem
abstract class CartItem extends BaseCartItem
{
}

View file

@ -1,131 +0,0 @@
<?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\Bundle\CartBundle\Entity;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
use Sylius\Bundle\CartBundle\Model\CartInterface;
use Sylius\Bundle\CartBundle\Model\CartManager as BaseCartManager;
/**
* Cart manager for doctrine/orm driver.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class CartManager extends BaseCartManager
{
/**
* Entity Manager.
*
* @var EntityManager
*/
protected $entityManager;
/**
* Carts repository.
*
* @var EntityRepository
*/
protected $repository;
/**
* Constructor.
*
* @param EntityManager $entityManager
*/
public function __construct(EntityManager $entityManager, $class)
{
parent::__construct($class);
$this->entityManager = $entityManager;
$this->repository = $this->entityManager->getRepository($class);
}
/**
* {@inheritdoc}
*/
public function createCart()
{
$class = $this->getClass();
return new $class;
}
/**
* {@inheritdoc}
*/
public function persistCart(CartInterface $cart)
{
$this->entityManager->persist($cart);
$this->entityManager->flush();
}
/**
* {@inheritdoc}
*/
public function removeCart(CartInterface $cart)
{
$this->entityManager->remove($cart);
$this->entityManager->flush();
}
/**
* {@inheritdoc}
*/
public function flushCarts()
{
$expiredCarts = $this->entityManager->createQueryBuilder()
->select('c')
->from($this->getClass(), 'c')
->where('c.locked = false AND c.expiresAt < ?1')
->setParameter(1, new \DateTime("now"))
->getQuery()
->getResult()
;
foreach ($expiredCarts as $cart) {
$this->removeCart($cart);
}
}
/**
* {@inheritdoc}
*/
public function findCart($id)
{
return $this->repository->find($id);
}
/**
* {@inheritdoc}
*/
public function findCartBy(array $criteria)
{
return $this->repository->findOneBy($criteria);
}
/**
* {@inheritdoc}
*/
public function findCarts()
{
return $this->repository->findAll();
}
/**
* {@inheritdoc}
*/
public function findCartsBy(array $criteria)
{
return $this->findBy($criteria);
}
}

View file

@ -1,107 +0,0 @@
<?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\Bundle\CartBundle\Entity;
use Doctrine\ORM\EntityManager;
use Doctrine\ORM\EntityRepository;
use Sylius\Bundle\CartBundle\Model\ItemInterface;
use Sylius\Bundle\CartBundle\Model\ItemManager as BaseItemManager;
class ItemManager extends BaseItemManager
{
/**
* Entity Manager.
*
* @var EntityManager
*/
protected $entityManager;
/**
* Items repository.
*
* @var EntityRepository
*/
protected $repository;
/**
* Constructor.
*
* @param EntityManager $entityManager
*/
public function __construct(EntityManager $entityManager, $class)
{
parent::__construct($class);
$this->entityManager = $entityManager;
$this->repository = $this->entityManager->getRepository($class);
}
/**
* {@inheritdoc}
*/
public function createItem()
{
$class = $this->getClass();
return new $class;
}
/**
* {@inheritdoc}
*/
public function persistItem(ItemInterface $cart)
{
$this->entityManager->persist($cart);
$this->entityManager->flush();
}
/**
* {@inheritdoc}
*/
public function removeItem(ItemInterface $cart)
{
$this->entityManager->remove($cart);
$this->entityManager->flush();
}
/**
* {@inheritdoc}
*/
public function findItem($id)
{
return $this->repository->find($id);
}
/**
* {@inheritdoc}
*/
public function findItemBy(array $criteria)
{
return $this->repository->findOneBy($criteria);
}
/**
* {@inheritdoc}
*/
public function findItems()
{
return $this->repository->findAll();
}
/**
* {@inheritdoc}
*/
public function findItemsBy(array $criteria)
{
return $this->findBy($criteria);
}
}

View file

@ -1,53 +0,0 @@
<?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\Bundle\CartBundle\EventDispatcher\Event;
use Sylius\Bundle\CartBundle\Model\CartInterface;
use Sylius\Bundle\CartBundle\Model\ItemInterface;
/**
* Cart operation event.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
final class CartOperationEvent extends FilterCartEvent
{
/**
* Cart item.
*
* @var ItemInterface
*/
private $item;
/**
* Constructor.
*
* @param CartInterface $cart
* @param ItemInterface $item
*/
public function __construct(CartInterface $cart, ItemInterface $item)
{
$this->item = $item;
parent::__construct($cart);
}
/**
* Returns item.
*
* @return ItemInterface
*/
public function getItem()
{
return $this->item;
}
}

View file

@ -1,50 +0,0 @@
<?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\Bundle\CartBundle\EventDispatcher\Event;
use Sylius\Bundle\CartBundle\Model\CartInterface;
use Symfony\Component\EventDispatcher\Event;
/**
* Filter cart event.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class FilterCartEvent extends Event
{
/**
* Cart.
*
* @var CartInterface
*/
protected $cart;
/**
* Constructor.
*
* @param CartInterface $cart
*/
public function __construct(CartInterface $cart)
{
$this->cart = $cart;
}
/**
* Returns cart.
*
* @return CartInterface
*/
public function getCart()
{
return $this->cart;
}
}

View file

@ -1,26 +0,0 @@
<?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\Bundle\CartBundle\EventDispatcher;
/**
* Events.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
final class SyliusCartEvents
{
const ITEM_ADD = 'sylius_cart.event.item.add';
const ITEM_REMOVE = 'sylius_cart.event.item.remove';
const CART_SAVE = 'sylius_cart.event.cart.save';
const CART_CLEAR = 'sylius_cart.event.cart.clear';
const CART_FLUSH = 'sylius_cart.event.cart.flush';
}

View file

@ -20,7 +20,7 @@ use Symfony\Component\OptionsResolver\OptionsResolverInterface;
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class ItemType extends AbstractType
class CartItemType extends AbstractType
{
/**
* Data class.

View file

@ -11,6 +11,9 @@
namespace Sylius\Bundle\CartBundle\Model;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
/**
* Model for carts.
* All driver entities and documents should extend this class or implement
@ -18,7 +21,7 @@ namespace Sylius\Bundle\CartBundle\Model;
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
abstract class Cart implements CartInterface
class Cart implements CartInterface
{
/**
* Id.
@ -30,7 +33,7 @@ abstract class Cart implements CartInterface
/**
* Items in cart.
*
* @var array
* @var Collection
*/
protected $items;
@ -41,6 +44,11 @@ abstract class Cart implements CartInterface
*/
protected $totalItems;
/**
* Total value.
*/
protected $total;
/**
* Locked.
*
@ -60,8 +68,9 @@ abstract class Cart implements CartInterface
*/
public function __construct()
{
$this->items = array();
$this->items = new ArrayCollection();
$this->totalItems = 0;
$this->total = 0;
$this->locked = false;
$this->incrementExpiresAt();
}
@ -74,14 +83,6 @@ abstract class Cart implements CartInterface
return $this->id;
}
/**
* {@inheritdoc}
*/
public function setId($id)
{
$this->id = $id;
}
/**
* {@inheritdoc}
*/
@ -101,9 +102,9 @@ abstract class Cart implements CartInterface
/**
* {@inheritdoc}
*/
public function incrementTotalItems($amount = 1)
public function getTotalItems()
{
$this->totalItems += $amount;
return $this->totalItems;
}
/**
@ -111,15 +112,23 @@ abstract class Cart implements CartInterface
*/
public function setTotalItems($totalItems)
{
if (0 > $totalItems) {
throw new \OutOfRangeException('Total items must not be less than 0');
}
$this->totalItems = $totalItems;
}
/**
* {@inheritdoc}
*/
public function getTotalItems()
public function changeTotalItems($amount)
{
return $this->totalItems;
$this->totalItems += $amount;
if (0 > $this->totalItems) {
$this->totalItems = 0;
}
}
/**
@ -141,11 +150,21 @@ abstract class Cart implements CartInterface
/**
* {@inheritdoc}
*/
public function setItems($items)
public function setItems(Collection $items)
{
$this->items = $items;
}
/**
* {@inheritdoc}
*/
public function clearItems()
{
$this->items->clear();
return $this;
}
/**
* {@inheritdoc}
*/
@ -157,60 +176,65 @@ abstract class Cart implements CartInterface
/**
* {@inheritdoc}
*/
public function addItem(ItemInterface $item)
public function addItem(CartItemInterface $item)
{
$exists = false;
if ($this->items->contains($item)) {
return $this;
}
foreach ($this->items as $existingItem) {
/** @var $existingItem ItemInterface */
if ($existingItem->equals($item)) {
$existingItem->incrementQuantity($item->getQuantity());
$exists = true;
break;
$existingItem->setQuantity($existingItem->getQuantity() + $item->getQuantity());
return $this;
}
}
if (!$exists) {
$item->setCart($this);
$this->items[] = $item;
}
$this->items->add($item);
$item->setCart($this);
return $this;
}
/**
* {@inheritdoc}
*/
public function removeItem(ItemInterface $item)
public function removeItem(CartItemInterface $item)
{
$key = $this->searchItem($item);
if (false !== $key) {
unset($this->items[$key]);
if ($this->items->contains($item)) {
$this->items->removeElement($item);
$item->setCart(null);
}
return $this;
}
/**
* {@inheritdoc}
*/
public function hasItem(ItemInterface $item)
public function hasItem(CartItemInterface $item)
{
return false !== $this->searchItem($item);
return $this->items->contains($item);
}
/**
* @param ItemInterface $item
*
* @return boolean|integer
*/
public function searchItem(ItemInterface $item)
public function getTotal()
{
return array_search($item, $this->items, true);
return $this->total;
}
/**
* {@inheritdoc}
*/
public function clearItems()
public function setTotal($total)
{
$this->items = array();
$this->total = $total;
}
public function calculateTotal()
{
// Reset total.
$this->total = 0;
foreach ($this->items as $item) {
$item->calculateTotal();
$this->total += $item->getTotal();
}
}
/**
@ -218,7 +242,7 @@ abstract class Cart implements CartInterface
*/
public function isExpired()
{
return $this->getExpiresAt() < new \DateTime;
return $this->getExpiresAt() < new \DateTime('now');
}
/**

View file

@ -11,49 +11,52 @@
namespace Sylius\Bundle\CartBundle\Model;
use Doctrine\Common\Collections\Collection;
use Sylius\Bundle\ResourceBundle\Model\ResourceInterface;
/**
* Cart model interface.
* All driver cart entities or documents should implement this interface.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
interface CartInterface
interface CartInterface extends ResourceInterface
{
/**
* Returns cart id.
*
* @return mixed
*/
function getId();
/**
* Sets cart id.
*
* @param mixed $id
*/
function setId($id);
/**
* Returns number of items in cart.
*
* @return integer
*/
function getTotalItems();
public function getTotalItems();
/**
* Sets number of items in cart.
*
* @param integer $totalItems;
*/
function setTotalItems($totalItems);
public function setTotalItems($totalItems);
/**
* Increments total items number by given amount.
* Default is 1.
* Change total items number by given amount.
*
* @param integer $amount
*/
function incrementTotalItems($amount = 1);
public function changeTotalItems($amount);
/**
* Get total cart value.
*/
public function getTotal();
/**
* Set total value.
*/
public function setTotal($total);
/**
* Calculate total.
*/
public function calculateTotal();
/**
* Checks whether the cart is locked or not.
@ -61,93 +64,93 @@ interface CartInterface
*
* @return Boolean
*/
function isLocked();
public function isLocked();
/**
* Sets whether the cart is locked or not.
*
* @param Boolean $locked
*/
function setLocked($locked);
public function setLocked($locked);
/**
* Checks whether the cart is empty or not.
*
* @return Boolean
*/
function isEmpty();
public function isEmpty();
/**
* Counts manually all items in cart.
*
* @return integer
*/
function countItems();
public function countItems();
/**
* Clears all items in cart.
*/
function clearItems();
public function clearItems();
/**
* Sets collection of items
*
* @param mixed $items
* @param Collection $items
*/
function setItems($items);
public function setItems(Collection $items);
/**
* Returns collection of items in cart.
*
* @return mixed
*/
function getItems();
public function getItems();
/**
* Adds item to cart.
*
* @param ItemInterface $item
* @param CartItemInterface $item
*/
function addItem(ItemInterface $item);
public function addItem(CartItemInterface $item);
/**
* Removes item from cart.
*
* @param ItemInterface $item
* @param CartItemInterface $item
*/
function removeItem(ItemInterface $item);
public function removeItem(CartItemInterface $item);
/**
* Checks whether given item is inside cart or not.
*
* @return Boolean
*/
function hasItem(ItemInterface $item);
public function hasItem(CartItemInterface $item);
/**
* Gets expiration time.
*
* @return \DateTime
*/
function getExpiresAt();
public function getExpiresAt();
/**
* Sets expiration time.
*
* @param \DateTime $expiresAt
*/
function setExpiresAt(\DateTime $expiresAt = null);
public function setExpiresAt(\DateTime $expiresAt = null);
/**
* Bumps the expiration time.
* Default is +3 hours.
*/
function incrementExpiresAt();
public function incrementExpiresAt();
/**
* Checks whether the cart is expired or not.
*
* @return Boolean
*/
function isExpired();
public function isExpired();
}

View file

@ -16,12 +16,10 @@ namespace Sylius\Bundle\CartBundle\Model;
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
abstract class Item implements ItemInterface
class CartItem implements CartItemInterface
{
/**
* Id.
*
* @var mixed
* Cart item id.
*/
protected $id;
@ -39,12 +37,24 @@ abstract class Item implements ItemInterface
*/
protected $quantity;
/**
* Unit price.
*/
protected $unitPrice;
/**
* Total value.
*/
protected $total;
/**
* Constructor.
*/
public function __construct()
{
$this->quantity = 1;
$this->unitPrice = 0;
$this->total = 0;
}
/**
@ -55,14 +65,6 @@ abstract class Item implements ItemInterface
return $this->id;
}
/**
* {@inheritdoc}
*/
public function setId($id)
{
$this->id = $id;
}
/**
* {@inheritdoc}
*/
@ -93,34 +95,39 @@ abstract class Item implements ItemInterface
public function setQuantity($quantity)
{
if (1 > $quantity) {
throw new \OutOfRangeException('Quantity value must be bigger than zero.');
throw new \OutOfRangeException('Quantity must be greater than 0');
}
$this->quantity = $quantity;
}
/**
* {@inheritdoc}
*/
public function incrementQuantity($amount = 1)
public function getUnitPrice()
{
$this->quantity += $amount;
// Quantity must be bigger than zero
if (1 > $this->quantity) {
$this->quantity = 1;
}
return $this->unitPrice;
}
/**
* {@inheritdoc}
*/
public function equals(ItemInterface $item)
public function setUnitPrice($unitPrice)
{
if ($item->getId() !== $this->getId()) {
return false;
}
$this->unitPrice = $unitPrice;
}
return true;
public function getTotal()
{
return $this->total;
}
public function setTotal($total)
{
$this->total = $total;
}
public function calculateTotal()
{
$this->total = $this->quantity * $this->unitPrice;
}
public function equals(CartItemInterface $cartItem)
{
return $this->getId() === $cartItem->getId();
}
}

View file

@ -11,68 +11,75 @@
namespace Sylius\Bundle\CartBundle\Model;
use Sylius\Bundle\ResourceBundle\Model\ResourceInterface;
/**
* Interface for cart item model.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
interface ItemInterface
interface CartItemInterface extends ResourceInterface
{
/**
* Returns item id.
*
* @return mixed
*/
function getId();
/**
* Sets item id.
*
* @param mixed $id
*/
function setId($id);
/**
* Returns associated cart.
*
* @return CartInterface
*/
function getCart();
public function getCart();
/**
* Sets cart.
*
* @param CartInterface
*/
function setCart(CartInterface $cart = null);
public function setCart(CartInterface $cart = null);
/**
* Returns quantity.
*
* @return integer
*/
function getQuantity();
public function getQuantity();
/**
* Sets quantity.
*
* @param $quantity
*/
function setQuantity($quantity);
public function setQuantity($quantity);
/**
* Increment quantity by given amount.
* By 1 as default.
*
* @param integer $quantity
* Get item price.
*/
function incrementQuantity($amount = 1);
public function getUnitPrice();
/**
* Set item price.
*/
public function setUnitPrice($price);
/**
* Set total.
*/
public function getTotal();
/**
* Set total.
*/
public function setTotal($total);
/**
* Calulcate line total.
*/
public function calculateTotal();
/**
* Checks whether the item given as argument corresponds to
* the same cart item. Can be overriden to sum up quantity.
*
* @param CartItemInterface $cartItem
*
* @return Boolean
*/
function equals(ItemInterface $item);
public function equals(CartItemInterface $cartItem);
}

View file

@ -1,45 +0,0 @@
<?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\Bundle\CartBundle\Model;
/**
* Base class for cart model manager.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
abstract class CartManager implements CartManagerInterface
{
/**
* FQCN of cart model.
*
* @var string
*/
protected $class;
/**
* Constructor.
*
* @param string $class FQCN of cart model
*/
public function __construct($class)
{
$this->class = $class;
}
/**
* {@inheritdoc}
*/
public function getClass()
{
return $this->class;
}
}

View file

@ -1,84 +0,0 @@
<?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\Bundle\CartBundle\Model;
/**
* Interface for cart manager.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
interface CartManagerInterface
{
/* }}} */
/**
* Creates a new cart instance.
*
* @return CartInterface
*/
function createCart();
/**
* Persists cart object.
*
* @param CartInterface $cart
*/
function persistCart(CartInterface $cart);
/**
* Removes cart object.
*
* @param CartInterface $cart
*/
function removeCart(CartInterface $cart);
/**
* Removes all saved carts that are expired.
*/
function flushCarts();
/**
* Finds cart by id.
*
* @param $id
*
* @return CartInterface|null
*/
function findCart($id);
/**
* Finds cart by given criteria.
*
* @param array $criteria
*/
function findCartBy(array $criteria);
/**
* Finds all carts.
*
* @return array
*/
function findCarts();
/**
* Finds carts by criteria.
*
* @param array $criteria
*/
function findCartsBy(array $criteria);
/**
* Returns FQCN of cart model.
*
* @return string
*/
function getClass();
}

View file

@ -1,45 +0,0 @@
<?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\Bundle\CartBundle\Model;
/**
* Base class for cart item model manager.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
abstract class ItemManager implements ItemManagerInterface
{
/**
* FQCN for cart item model.
*
* @var string
*/
protected $class;
/**
* Constructor.
*
* @param string $class The FQCN for cart item model
*/
public function __construct($class)
{
$this->class = $class;
}
/**
* {@inheritdoc}
*/
public function getClass()
{
return $this->class;
}
}

View file

@ -1,74 +0,0 @@
<?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\Bundle\CartBundle\Model;
/**
* Interface for cart intem model manager.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
interface ItemManagerInterface
{
/**
* Returns FQCN of cart item model.
*
* @return string
*/
function getClass();
/**
* Creates item model object.
*/
function createItem();
/**
* Persists item.
*
* @param ItemInterface $item
*/
function persistItem(ItemInterface $item);
/**
* Removes item.
*
* @param ItemInterface $item
*/
function removeItem(ItemInterface $item);
/**
* Finds item by id.
*
* @param integer $id
*/
function findItem($id);
/**
* Finds item by criteria.
*
* @param array $criteria
*/
function findItemBy(array $criteria);
/**
* Finds all items.
*
* @return array
*/
function findItems();
/**
* Finds items by criteria.
*
* @param array $criteria
*/
function findItemsBy(array $criteria);
}

View file

@ -12,8 +12,8 @@
namespace Sylius\Bundle\CartBundle\Operator;
use Sylius\Bundle\CartBundle\Model\CartInterface;
use Sylius\Bundle\CartBundle\Model\CartManagerInterface;
use Sylius\Bundle\CartBundle\Model\ItemInterface;
use Sylius\Bundle\CartBundle\Model\CartItemInterface;
use Sylius\Bundle\ResourceBundle\Manager\ResourceManagerInterface;
/**
* Base class for cart operator.
@ -22,21 +22,21 @@ use Sylius\Bundle\CartBundle\Model\ItemInterface;
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
abstract class CartOperator implements CartOperatorInterface
class CartOperator implements CartOperatorInterface
{
/**
* Cart manager.
*
* @var CartManagerInterface
* @var ResourceManagerInterface
*/
protected $cartManager;
/**
* Constructor.
*
* @param CartManagerInterface $cartManager;
* @param ResourceManagerInterface $cartManager;
*/
public function __construct(CartManagerInterface $cartManager)
public function __construct(ResourceManagerInterface $cartManager)
{
$this->cartManager = $cartManager;
}
@ -44,17 +44,21 @@ abstract class CartOperator implements CartOperatorInterface
/**
* {@inheritdoc}
*/
public function addItem(CartInterface $cart, ItemInterface $item)
public function addItem(CartInterface $cart, CartItemInterface $item)
{
$cart->addItem($item);
return $this;
}
/**
* {@inheritdoc}
*/
public function removeItem(CartInterface $cart, ItemInterface $item)
public function removeItem(CartInterface $cart, CartItemInterface $item)
{
$cart->removeItem($item);
return $this;
}
/**
@ -62,7 +66,10 @@ abstract class CartOperator implements CartOperatorInterface
*/
public function refresh(CartInterface $cart)
{
$cart->calculateTotal();
$cart->setTotalItems($cart->countItems());
return $this;
}
/**
@ -70,7 +77,9 @@ abstract class CartOperator implements CartOperatorInterface
*/
public function clear(CartInterface $cart)
{
$this->cartManager->removeCart($cart);
$this->cartManager->remove($cart);
return $this;
}
/**
@ -78,6 +87,8 @@ abstract class CartOperator implements CartOperatorInterface
*/
public function save(CartInterface $cart)
{
$this->cartManager->persistCart($cart);
$this->cartManager->persist($cart);
return $this;
}
}

View file

@ -12,7 +12,7 @@
namespace Sylius\Bundle\CartBundle\Operator;
use Sylius\Bundle\CartBundle\Model\CartInterface;
use Sylius\Bundle\CartBundle\Model\ItemInterface;
use Sylius\Bundle\CartBundle\Model\CartItemInterface;
/**
* Interface for cart operator.
@ -24,37 +24,37 @@ interface CartOperatorInterface
/**
* Adds item to cart.
*
* @param CartInterface $cart
* @param ItemInterface $item
* @param CartInterface $cart
* @param CartItemInterface $item
*/
function addItem(CartInterface $cart, ItemInterface $item);
public function addItem(CartInterface $cart, CartItemInterface $item);
/**
* Removes item from cart.
*
* @param CartInterface $cart
* @param ItemInterface $item
* @param CartInterface $cart
* @param CartItemInterface $item
*/
function removeItem(CartInterface $cart, ItemInterface $item);
public function removeItem(CartInterface $cart, CartItemInterface $item);
/**
* Refreshes cart data.
*
* @param CartInterface $cart
*/
function refresh(CartInterface $cart);
public function refresh(CartInterface $cart);
/**
* Saves cart at current state.
*
* @param CartInterface $cart
*/
function save(CartInterface $cart);
public function save(CartInterface $cart);
/**
* Clears current cart.
*
* @param CartInterface $cart
*/
function clear(CartInterface $cart);
public function clear(CartInterface $cart);
}

View file

@ -12,8 +12,8 @@
namespace Sylius\Bundle\CartBundle\Provider;
use Sylius\Bundle\CartBundle\Model\CartInterface;
use Sylius\Bundle\CartBundle\Model\CartManagerInterface;
use Sylius\Bundle\CartBundle\Storage\CartStorageInterface;
use Sylius\Bundle\ResourceBundle\Manager\ResourceManagerInterface;
/**
* Default provider cart.
@ -32,7 +32,7 @@ class CartProvider implements CartProviderInterface
/**
* Cart manager.
*
* @var CartManagerInterface
* @var ResourceManagerInterface
*/
protected $cartManager;
@ -46,10 +46,10 @@ class CartProvider implements CartProviderInterface
/**
* Constructor.
*
* @param CartStorageInterface $storage
* @param CartManagerInterface $cartManager
* @param CartStorageInterface $storage
* @param ResourceManagerInterface $cartManager
*/
public function __construct(CartStorageInterface $storage, CartManagerInterface $cartManager)
public function __construct(CartStorageInterface $storage, ResourceManagerInterface $cartManager)
{
$this->storage = $storage;
$this->cartManager = $cartManager;
@ -68,12 +68,13 @@ class CartProvider implements CartProviderInterface
if ($cart) {
$this->cart = $cart;
return $cart;
}
}
$cart = $this->cartManager->createCart();
$this->cartManager->persistCart($cart);
$cart = $this->cartManager->create();
$this->cartManager->persist($cart);
$this->storage->setCurrentCartIdentifier($cart);
$this->cart = $cart;
@ -103,11 +104,11 @@ class CartProvider implements CartProviderInterface
/**
* Gets cart by cart identifier.
*
* @param mixed $identifier
* @param mixed $identifier
* @return CartInterface|null
*/
protected function getCartByIdentifier($identifier)
{
return $this->cartManager->findCart($identifier);
return $this->cartManager->find($identifier);
}
}

View file

@ -27,7 +27,7 @@ interface CartProviderInterface
*
* @return CartInterface
*/
function getCart();
public function getCart();
/**
* Sets given cart as current one.
@ -35,10 +35,10 @@ interface CartProviderInterface
*
* @param CartInterface $cart
*/
function setCart(CartInterface $cart);
public function setCart(CartInterface $cart);
/**
* Abandon current cart.
*/
function abandonCart();
public function abandonCart();
}

View file

@ -2,19 +2,7 @@ SyliusCartBundle [![Build status...](https://secure.travis-ci.org/Sylius/SyliusC
================
Flexible cart engine for Symfony2. Allows you to add any object to cart, customize the structure of it and much more.
Considered as base for building solution that fits your exact needs.
Features
--------
* Base support for many different persistence layers. Currently only Doctrine ORM driver is implemented.
* Cart item is simple model and you can make it look whatever you like.
* Sensible default model for cart.
* Flexible item resolver that allows you to build and add items the way you prefer.
* Default cart operator implementation handles most basic cart scenario and can be easily extended.
* Common actions like adding/removing items, updating, clearing and viewing the cart are implemented in controllers shipped with the bundle.
* Flushing expired carts.
* Thanks to awesome [Symfony2](http://symfony.com) everything is configurable and extensible.
Should be considered as base for building solution that fits your exact needs.
Sylius
------
@ -26,7 +14,7 @@ Please visit [Sylius.org](http://sylius.org) for more details.
Testing and build status
------------------------
This bundle uses [travis-ci.org](http://travis-ci.org/Sylius/SyliusCartBundle) for CI.
This bundle uses [travis-ci.org](http://travis-ci.org/Sylius/SyliusCartBundle).
[![Build status...](https://secure.travis-ci.org/Sylius/SyliusCartBundle.png)](http://travis-ci.org/Sylius/SyliusCartBundle)
Before running tests, load the dependencies using [Composer](http://packagist.org).

View file

@ -11,7 +11,7 @@
namespace Sylius\Bundle\CartBundle\Resolver;
use Sylius\Bundle\CartBundle\Model\ItemInterface;
use Sylius\Bundle\CartBundle\Model\CartItemInterface;
use Symfony\Component\HttpFoundation\Request;
/**
@ -27,16 +27,16 @@ interface ItemResolverInterface
*
* @param Request $request
*
* @return ItemInterface
* @return CartItemInterface
*/
function resolveItemToAdd(Request $request);
public function resolveItemToAdd(Request $request);
/**
* Returns item to remove.
*
* @param Request $request
*
* @return ItemInterface
* @return CartItemInterface
*/
function resolveItemToRemove(Request $request);
public function resolveItemToRemove(Request $request);
}

View file

@ -1,28 +0,0 @@
<?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
http://symfony.com/schema/dic/services/services-1.0.xsd"
>
<services>
<service id="sylius_cart.controller.frontend.cart" class="%sylius_cart.controller.frontend.cart.class%">
<call method="setContainer">
<argument type="service" id="service_container" />
</call>
</service>
</services>
</container>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8"?>
<!--
@ -14,8 +14,12 @@
<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
http://symfony.com/schema/dic/services/services-1.0.xsd"
>
http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="sylius_cart.manager.cart.class">Sylius\Bundle\ResourceBundle\Manager\Doctrine\ORM\ResourceManager</parameter>
<parameter key="sylius_cart.manager.item.class">Sylius\Bundle\ResourceBundle\Manager\Doctrine\ORM\ResourceManager</parameter>
</parameters>
<services>
<service id="sylius_cart.manager.cart" class="%sylius_cart.manager.cart.class%">

View file

@ -1,20 +0,0 @@
<?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
http://symfony.com/schema/dic/services/services-1.0.xsd"
>
</container>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8"?>
<!--
@ -14,8 +14,7 @@
<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
http://symfony.com/schema/dic/services/services-1.0.xsd"
>
http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="sylius_cart.twig.class">Sylius\Bundle\CartBundle\Twig\SyliusCartExtension</parameter>

View file

@ -1,31 +0,0 @@
<?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
http://symfony.com/schema/dic/services/services-1.0.xsd"
>
<services>
<service id="sylius_cart.form.type.cart" class="%sylius_cart.form.type.cart.class%">
<argument>%sylius_cart.model.cart.class%</argument>
<tag name="form.type" alias="sylius_cart" />
</service>
<service id="sylius_cart.form.type.item" class="%sylius_cart.form.type.item.class%">
<argument>%sylius_cart.model.item.class%</argument>
<tag name="form.type" alias="sylius_cart_item" />
</service>
</services>
</container>

View file

@ -1,27 +0,0 @@
<?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
http://symfony.com/schema/dic/services/services-1.0.xsd"
>
<services>
<service id="sylius_cart.provider" class="%sylius_cart.provider.class%">
<argument type="service" id="sylius_cart.storage" />
<argument type="service" id="sylius_cart.manager.cart" />
</service>
</services>
</container>

View file

@ -0,0 +1,54 @@
<?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
http://symfony.com/schema/dic/services/services-1.0.xsd">
<parameters>
<parameter key="sylius_cart.operator.class">Sylius\Bundle\CartBundle\Operator\CartOperator</parameter>
<parameter key="sylius_cart.storage.session.class">Sylius\Bundle\CartBundle\Storage\SessionCartStorage</parameter>
</parameters>
<services>
<service id="sylius_cart.controller.cart" class="%sylius_cart.controller.cart.class%">
<call method="setContainer">
<argument type="service" id="service_container" />
</call>
</service>
<service id="sylius_cart.form.type.cart" class="%sylius_cart.form.type.cart.class%">
<argument>%sylius_cart.model.cart.class%</argument>
<tag name="form.type" alias="sylius_cart" />
</service>
<service id="sylius_cart.form.type.item" class="%sylius_cart.form.type.item.class%">
<argument>%sylius_cart.model.item.class%</argument>
<tag name="form.type" alias="sylius_cart_item" />
</service>
<service id="sylius_cart.operator" class="%sylius_cart.operator.class%">
<argument type="service" id="sylius_cart.manager.cart" />
</service>
<service id="sylius_cart.provider" class="%sylius_cart.provider.class%">
<argument type="service" id="sylius_cart.storage" />
<argument type="service" id="sylius_cart.manager.cart" />
</service>
<service id="sylius_cart.storage.session" class="%sylius_cart.storage.session.class%">
<argument type="service" id="session" />
</service>
</services>
</container>

View file

@ -1,30 +0,0 @@
<?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
http://symfony.com/schema/dic/services/services-1.0.xsd"
>
<parameters>
<parameter key="sylius_cart.storage.session.class">Sylius\Bundle\CartBundle\Storage\SessionCartStorage</parameter>
</parameters>
<services>
<service id="sylius_cart.storage.session" class="%sylius_cart.storage.session.class%">
<argument type="service" id="session" />
</service>
</services>
</container>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8"?>
<!--
@ -14,12 +14,12 @@
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"
>
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<mapped-superclass name="Sylius\Bundle\CartBundle\Entity\Cart" table="sylius_cart">
<field name="locked" column="locked" type="boolean" />
<field name="totalItems" column="total_items" type="integer" />
<field name="total" column="total" type="decimal" precision="10" scale="2" />
<field name="expiresAt" column="expires_at" type="datetime" />
</mapped-superclass>

View file

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8"?>
<!--
@ -14,11 +14,12 @@
<doctrine-mapping xmlns="http://doctrine-project.org/schemas/orm/doctrine-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://doctrine-project.org/schemas/orm/doctrine-mapping
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd"
>
http://doctrine-project.org/schemas/orm/doctrine-mapping.xsd">
<mapped-superclass name="Sylius\Bundle\CartBundle\Entity\Item" table="sylius_cart_item">
<mapped-superclass name="Sylius\Bundle\CartBundle\Entity\CartItem" table="sylius_cart_item">
<field name="quantity" column="quantity" type="integer" />
<field name="unitPrice" column="unit_price" type="decimal" precision="10" scale="2" />
<field name="total" column="total" type="decimal" precision="10" scale="2" />
</mapped-superclass>
</doctrine-mapping>

View file

@ -0,0 +1,22 @@
# This file is part of the Sylius package.
# (c) Paweł Jędrzejewski
sylius_cart_show:
pattern: /
defaults: { _controller: sylius_cart.controller.cart:showAction }
sylius_cart_save:
pattern: /save
defaults: { _controller: sylius_cart.controller.cart:saveAction }
sylius_cart_clear:
pattern: /clear
defaults: { _controller: sylius_cart.controller.cart:clearAction }
sylius_cart_item_add:
pattern: /item/add
defaults: { _controller: sylius_cart.controller.cart:addItemAction }
sylius_cart_item_remove:
pattern: /item/remove
defaults: { _controller: sylius_cart.controller.cart:removeItemAction }

View file

@ -1,22 +0,0 @@
# This file is part of the Sylius package.
# (c) Paweł Jędrzejewski
sylius_cart_show:
pattern: /
defaults: { _controller: sylius_cart.controller.frontend.cart:showAction }
sylius_cart_save:
pattern: /save
defaults: { _controller: sylius_cart.controller.frontend.cart:saveAction }
sylius_cart_clear:
pattern: /clear
defaults: { _controller: sylius_cart.controller.frontend.cart:clearAction }
sylius_cart_item_add:
pattern: /item/add
defaults: { _controller: sylius_cart.controller.frontend.cart:addItemAction }
sylius_cart_item_remove:
pattern: /item/remove
defaults: { _controller: sylius_cart.controller.frontend.cart:removeItemAction }

View file

@ -1,4 +1,4 @@
<?xml version="1.0" ?>
<?xml version="1.0"?>
<!--
@ -14,15 +14,14 @@
<constraint-mapping xmlns="http://symfony.com/schema/dic/constraint-mapping"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://symfony.com/schema/dic/constraint-mapping
http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd"
>
http://symfony.com/schema/dic/constraint-mapping/constraint-mapping-1.0.xsd">
<class name="Sylius\Bundle\CartBundle\Model\Cart">
<property name="items">
<constraint name="Valid" />
</property>
</class>
<class name="Sylius\Bundle\CartBundle\Model\Item">
<class name="Sylius\Bundle\CartBundle\Model\CartItem">
<property name="quantity">
<constraint name="NotBlank" />
<constraint name="Type">

View file

@ -25,18 +25,18 @@ interface CartStorageInterface
*
* @return mixed
*/
function getCurrentCartIdentifier();
public function getCurrentCartIdentifier();
/**
* Sets current cart id and persists it.
*
* @param CartInterface $cart
*/
function setCurrentCartIdentifier(CartInterface $cart);
public function setCurrentCartIdentifier(CartInterface $cart);
/**
* Resets current cart identifier.
* Basically, it means abandoning current cart.
*/
function resetCurrentCartIdentifier();
public function resetCurrentCartIdentifier();
}

View file

@ -11,31 +11,25 @@
namespace Sylius\Bundle\CartBundle;
use Sylius\Bundle\ResourceBundle\SyliusResourceBundle;
use Symfony\Component\HttpKernel\Bundle\Bundle;
/**
* Easy and flexible cart system bundle.
* Clean and consistent architecture.
* Simple and flexible cart system.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class SyliusCartBundle extends Bundle
{
// Bundle driver list.
const DRIVER_DOCTRINE_ORM = 'doctrine/orm';
const DRIVER_DOCTRINE_MONGODB_ODM = 'doctrine/mongodb-odm';
const DRIVER_DOCTRINE_COUCHDB_ODM = 'doctrine/couchdb-odm';
const DRIVER_PROPEL = 'propel';
/**
* Return array of currently supported drivers.
*
* @return array
*/
static public function getSupportedDrivers()
public static function getSupportedDrivers()
{
return array(
self::DRIVER_DOCTRINE_ORM
SyliusResourceBundle::DRIVER_DOCTRINE_ORM
);
}
}

View file

@ -1,124 +0,0 @@
<?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\Bundle\CartBundle\Tests\DependencyInjection;
use Sylius\Bundle\CartBundle\DependencyInjection\SyliusCartExtension;
use Symfony\Component\DependencyInjection\ContainerBuilder;
use Symfony\Component\Yaml\Parser;
/**
* DIC extension test.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class SyliusCartExtensionTest extends \PHPUnit_Framework_TestCase
{
/**
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
*/
public function testLoadThrowsExceptionUnlessDriverSet()
{
$loader = new SyliusCartExtension();
$config = $this->getEmptyConfig();
unset($config['driver']);
$loader->load(array($config), new ContainerBuilder());
}
/**
* @expectedException \InvalidArgumentException
*/
public function testLoadThrowsExceptionUnlessDriverIsValid()
{
$loader = new SyliusCartExtension();
$config = $this->getEmptyConfig();
$config['driver'] = 'foo';
$loader->load(array($config), new ContainerBuilder());
}
/**
* @expectedException \InvalidArgumentException
*/
public function testLoadThrowsExceptionUnlessEngineIsValid()
{
$loader = new SyliusCartExtension();
$config = $this->getEmptyConfig();
$config['engine'] = 'foo';
$loader->load(array($config), new ContainerBuilder());
}
/**
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
*/
public function testLoadThrowsExceptionUnlessOperatorSet()
{
$loader = new SyliusCartExtension();
$config = $this->getEmptyConfig();
unset($config['operator']);
$loader->load(array($config), new ContainerBuilder());
}
/**
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
*/
public function testLoadThrowsExceptionUnlessResolverSet()
{
$loader = new SyliusCartExtension();
$config = $this->getEmptyConfig();
unset($config['resolver']);
$loader->load(array($config), new ContainerBuilder());
}
/**
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
*/
public function testLoadThrowsExceptionUnlessCartModelClassSet()
{
$loader = new SyliusCartExtension();
$config = $this->getEmptyConfig();
unset($config['classes']['model']['cart']);
$loader->load(array($config), new ContainerBuilder());
}
/**
* @expectedException \Symfony\Component\Config\Definition\Exception\InvalidConfigurationException
*/
public function testLoadThrowsExceptionUnlessItemModelClassSet()
{
$loader = new SyliusCartExtension();
$config = $this->getEmptyConfig();
unset($config['classes']['model']['item']);
$loader->load(array($config), new ContainerBuilder());
}
/**
* Get testing config.
*
* @return array
*/
protected function getEmptyConfig()
{
$yaml =
<<<EOF
driver: doctrine/orm
operator: test_cart.operator
resolver: test_cart.resolver
classes:
model:
cart: Acme\\Bundle\\CartBundle\\Entity\\Cart
item: Acme\\Bundle\\CartBundle\\Entity\\Item
EOF;
$parser = new Parser();
return $parser->parse($yaml);
}
}

View file

@ -1,71 +0,0 @@
<?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\Bundle\CartBundle\Tests\Entity;
use Sylius\Bundle\CartBundle\Entity\CartManager;
/**
* Cart manager test for doctrine/orm driver.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class CartManagerTest extends \PHPUnit_Framework_TestCase
{
public function testPersistCart()
{
$cart = $this->getMockCart();
$entityManager = $this->getMockEntityManager();
$entityManager->expects($this->once())
->method('persist')
->with($this->equalTo($cart))
;
$entityManager->expects($this->once())
->method('flush')
;
$cartManager = new CartManager($entityManager, 'Foo\Bar');
$cartManager->persistCart($cart);
}
public function testRemoveCart()
{
$cart = $this->getMockCart();
$entityManager = $this->getMockEntityManager();
$entityManager->expects($this->once())
->method('remove')
->with($this->equalTo($cart))
;
$entityManager->expects($this->once())
->method('flush')
;
$cartManager = new CartManager($entityManager, 'Foo\Bar');
$cartManager->removeCart($cart);
}
private function getMockCart()
{
return $this->getMock('Sylius\Bundle\CartBundle\Model\CartInterface');
}
private function getMockEntityManager()
{
$entityManager = $this->getMockBuilder('Doctrine\ORM\EntityManager')
->disableOriginalConstructor()
->getMock()
;
return $entityManager;
}
}

View file

@ -1,72 +0,0 @@
<?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\Bundle\CartBundle\Tests\Entity;
use Sylius\Bundle\CartBundle\Entity\ItemManager;
/**
* Item manager test for doctrine/orm driver.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class ItemManagerTest extends \PHPUnit_Framework_TestCase
{
public function testPersistItem()
{
$item = $this->getMockItem();
$entityManager = $this->getMockEntityManager();
$entityManager->expects($this->once())
->method('persist')
->with($this->equalTo($item))
;
$entityManager->expects($this->once())
->method('flush')
;
$itemManager = new ItemManager($entityManager, 'Foo\Bar');
$itemManager->persistItem($item);
}
public function testRemoveItem()
{
$item = $this->getMockItem();
$entityManager = $this->getMockEntityManager();
$entityManager->expects($this->once())
->method('remove')
->with($this->equalTo($item))
;
$entityManager->expects($this->once())
->method('flush')
;
$itemManager = new ItemManager($entityManager, 'Foo\Bar');
$itemManager->removeItem($item);
}
private function getMockItem()
{
return $this->getMock('Sylius\Bundle\CartBundle\Model\ItemInterface');
}
private function getMockEntityManager()
{
$entityManager = $this->getMockBuilder('Doctrine\ORM\EntityManager')
->disableOriginalConstructor()
->getMock()
;
return $entityManager;
}
}

View file

@ -1,33 +0,0 @@
<?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\Bundle\CartBundle\Tests\EventDispatcher\Event;
use Sylius\Bundle\CartBundle\EventDispatcher\Event\CartOperationEvent;
/**
* Cart operation event test.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class CartOperationEventTest extends \PHPUnit_Framework_TestCase
{
public function testConstructor()
{
$cart = $this->getMock('Sylius\Bundle\CartBundle\Model\CartInterface');
$item = $this->getMock('Sylius\Bundle\CartBundle\Model\ItemInterface');
$event = new CartOperationEvent($cart, $item);
$this->assertEquals($cart, $event->getCart());
$this->assertEquals($item, $event->getItem());
}
}

View file

@ -1,29 +0,0 @@
<?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\Bundle\CartBundle\Tests\EventDispatcher\Event;
use Sylius\Bundle\CartBundle\EventDispatcher\Event\FilterCartEvent;
/**
* Cart filtering event test.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class FilterCartEventTest extends \PHPUnit_Framework_TestCase
{
public function testConstructor()
{
$cart = $this->getMock('Sylius\Bundle\CartBundle\Model\CartInterface');
$event = new FilterCartEvent($cart);
$this->assertEquals($cart, $event->getCart());
}
}

View file

@ -1,83 +0,0 @@
<?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\Bundle\CartBundle\Tests\Model;
/**
* Cart model test.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class CartTest extends \PHPUnit_Framework_TestCase
{
public function testConstructor()
{
$cart = $this->getCart();
$this->assertTrue($cart->isEmpty());
$this->assertFalse($cart->isLocked());
$this->assertInstanceOf('DateTime', $cart->getExpiresAt());
}
public function testGetSetId()
{
$cart = $this->getCart();
$this->assertNull($cart->getId());
$cart->setId(5);
$this->assertEquals(5, $cart->getId());
}
public function testGetSetTotalItems()
{
$cart = $this->getCart();
$cart->setTotalItems(3);
$this->assertEquals(3, $cart->getTotalItems());
}
public function testIsSetLocked()
{
$cart = $this->getCart();
$cart->setLocked(true);
$this->assertTrue($cart->isLocked());
}
public function testGetSetExpiresAt()
{
$cart = $this->getCart();
$expiresAt = $cart->getExpiresAt();
sleep(1);
$this->assertEquals($expiresAt, $cart->getExpiresAt());
}
public function testIncrementExpiresAt()
{
$cart = $this->getCart();
$expiresAt = $cart->getExpiresAt();
sleep(1);
$cart->incrementExpiresAt();
$this->assertGreaterThan($expiresAt, $cart->getExpiresAt());
}
/**
* @return \Sylius\Bundle\CartBundle\Model\Cart
*/
private function getCart()
{
return $this->getMockForAbstractClass('Sylius\Bundle\CartBundle\Model\Cart');
}
}

View file

@ -1,102 +0,0 @@
<?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\Bundle\CartBundle\Tests\Model;
/**
* Item model test.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class ItemTest extends \PHPUnit_Framework_TestCase
{
public function testConstructor()
{
$item = $this->getItem();
$this->assertEquals(1, $item->getQuantity());
}
public function testGetSetId()
{
$item = $this->getItem();
$this->assertNull($item->getId());
$item->setId(5);
$this->assertEquals(5, $item->getId());
}
public function testGetSetCart()
{
$item = $this->getItem();
$this->assertNull($item->getCart());
$cart = $this->getMockCart();
$item->setCart($cart);
$this->assertEquals($cart, $item->getCart());
}
public function testEquals()
{
$item = $this->getItem();
$item->setId(1);
$duplicatedItem = clone $item;
$this->assertTrue($item->equals($duplicatedItem));
$duplicatedItem->setQuantity(2);
$this->assertTrue($item->equals($duplicatedItem));
$this->assertNotEquals($duplicatedItem->getQuantity(), $item->getQuantity());
$duplicatedItem->setId(2);
$this->assertFalse($item->equals($duplicatedItem));
}
public function testQuantityManagement()
{
$item = $this->getItem();
$item->setQuantity(5);
$this->assertEquals(5, $item->getQuantity());
$item->incrementQuantity(5);
$this->assertEquals(10, $item->getQuantity());
$item->incrementQuantity(-10);
$this->assertEquals(1, $item->getQuantity());
}
/**
* @expectedException \OutOfRangeException
*/
public function testQuantityMustBeBiggerThanZero()
{
$item = $this->getItem();
$item->setQuantity(0);
}
/**
* @return \Sylius\Bundle\CartBundle\Model\Item
*/
private function getItem()
{
return $this->getMockForAbstractClass('Sylius\Bundle\CartBundle\Model\Item');
}
/**
* @return \Sylius\Bundle\CartBundle\Model\CartInterface
*/
private function getMockCart()
{
return $this->getMock('Sylius\Bundle\CartBundle\Model\CartInterface');
}
}

View file

@ -1,169 +0,0 @@
<?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\Bundle\CartBundle\Tests\Operator;
/**
* Simple default operator test.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class CartOperatorTest extends \PHPUnit_Framework_TestCase
{
public function testAddItemAddsItemToCart()
{
$item = $this->getMockItem();
$cart = $this->getMockCart();
$cart->expects($this->once())
->method('addItem')
->with($item)
;
$cartOperator = $this->getCartOperator();
$cartOperator->addItem($cart, $item);
}
public function testAddItemIncreasesQuantityIfThereAreItemsThatAreEqual()
{
$item = $this->getItem();
$item->setId(1);
$item->setQuantity(3);
$cart = $this->getCart();
$cartOperator = $this->getCartOperator();
$cartOperator->addItem($cart, $item);
$duplicatedItem = clone $item;
$duplicatedItem->setQuantity(2);
$cartOperator->addItem($cart, $duplicatedItem);
$this->assertEquals(1, $cart->countItems());
$this->assertEquals(5, $item->getQuantity());
}
public function testRefreshSetsTotalItems()
{
$cart = $this->getMockCart();
$cart->expects($this->once())
->method('countItems')
->will($this->returnValue(6))
;
$cart->expects($this->once())
->method('setTotalItems')
->with($this->equalTo(6))
;
$cartOperator = $this->getCartOperator();
$cartOperator->refresh($cart);
}
public function testClearRemovesCart()
{
$cart = $this->getMockCart();
$cartManager = $this->getMockCartManager();
$cartManager->expects($this->once())
->method('removeCart')
->with($this->equalTo($cart))
;
$cartOperator = $this->getCartOperator($cartManager);
$cartOperator->clear($cart);
}
public function testSavePersistsCart()
{
$cart = $this->getMockCart();
$cartManager = $this->getMockCartManager();
$cartManager->expects($this->once())
->method('persistCart')
->with($this->equalTo($cart))
;
$cartOperator = $this->getCartOperator($cartManager);
$cartOperator->save($cart);
}
public function testRemoveItemRemovesItemFromCart()
{
$item = $this->getMockItem();
$cart = $this->getMockCart();
$cart->expects($this->once())
->method('removeItem')
->with($item)
;
$cartOperator = $this->getCartOperator();
$cartOperator->removeItem($cart, $item);
}
/**
* @param object|null $cartManager
*
* @return \Sylius\Bundle\CartBundle\Operator\CartOperator
*/
private function getCartOperator($cartManager = null)
{
if (null === $cartManager) {
$cartManager = $this->getMockCartManager();
}
return $this->getMockBuilder('Sylius\Bundle\CartBundle\Operator\CartOperator')
->setConstructorArgs(array($cartManager))
->getMockForAbstractClass()
;
}
/**
* @return \Sylius\Bundle\CartBundle\Model\Cart
*/
private function getCart()
{
return $this->getMockForAbstractClass('Sylius\Bundle\CartBundle\Model\Cart');
}
/**
* @return \Sylius\Bundle\CartBundle\Model\Item
*/
private function getItem()
{
return $this->getMockForAbstractClass('Sylius\Bundle\CartBundle\Model\Item');
}
/**
* @return \Sylius\Bundle\CartBundle\Model\CartManagerInterface
*/
private function getMockCartManager()
{
return $this->getMock('Sylius\Bundle\CartBundle\Model\CartManagerInterface');
}
/**
* @return \Sylius\Bundle\CartBundle\Model\CartInterface
*/
private function getMockCart()
{
return $this->getMock('Sylius\Bundle\CartBundle\Model\CartInterface');
}
/**
* @return \Sylius\Bundle\CartBundle\Model\ItemInterface
*/
private function getMockItem()
{
return $this->getMock('Sylius\Bundle\CartBundle\Model\ItemInterface');
}
}

View file

@ -1,110 +0,0 @@
<?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\Bundle\CartBundle\Tests\Provider;
use Sylius\Bundle\CartBundle\Provider\CartProvider;
/**
* Default cart provider test.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class CartOperatorTest extends \PHPUnit_Framework_TestCase
{
public function testGetCartReturnsNewCartWhenCartStorageReturnsNullIdentifier()
{
$cart = $this->getMockCart();
$cartStorage = $this->getMockCartStorage();
$cartStorage->expects($this->once())
->method('getCurrentCartIdentifier')
->will($this->returnValue(null))
;
$cartStorage->expects($this->once())
->method('setCurrentCartIdentifier')
->with($this->equalTo($cart))
;
$cartManager = $this->getMockCartManager();
$cartManager->expects($this->once())
->method('createCart')
->will($this->returnValue($cart))
;
$cartManager->expects($this->once())
->method('persistCart')
->with($this->equalTo($cart))
;
$cartProvider = new CartProvider($cartStorage, $cartManager);
$this->assertEquals($cart, $cartProvider->getCart());
}
public function testGetCartReturnsExistingCartBasedOnCartStorage()
{
$cartStorage = $this->getMockCartStorage();
$cartStorage->expects($this->once())
->method('getCurrentCartIdentifier')
->will($this->returnValue(123))
;
$cart = $this->getMockCart();
$cartManager = $this->getMockCartManager();
$cartManager->expects($this->once())
->method('findCart')
->with($this->equalTo(123))
->will($this->returnValue($cart))
;
$cartProvider = new CartProvider($cartStorage, $cartManager);
$this->assertEquals($cart, $cartProvider->getCart());
}
public function testSimpleGetSetCart()
{
$cart = $this->getMockCart();
$cartProvider = new CartProvider($this->getMockCartStorage(), $this->getMockCartManager());
$cartProvider->setCart($cart);
$this->assertEquals($cart, $cartProvider->getCart());
}
public function testAbandonCart()
{
$storage = $this->getMockCartStorage();
$storage->expects($this->once())
->method('resetCurrentCartIdentifier')
;
$cartProvider = new CartProvider($storage, $this->getMockCartManager());
$cartProvider->abandonCart();
}
private function getMockCartStorage()
{
return $this->getMock('Sylius\Bundle\CartBundle\Storage\CartStorageInterface');
}
private function getMockCartManager()
{
return $this->getMock('Sylius\Bundle\CartBundle\Model\CartManagerInterface');
}
private function getMockCart()
{
return $this->getMock('Sylius\Bundle\CartBundle\Model\CartInterface');
}
}

View file

@ -1,79 +0,0 @@
<?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\Bundle\CartBundle\Tests\Storage;
use Sylius\Bundle\CartBundle\Storage\SessionCartStorage;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpFoundation\Session\Storage\MockArraySessionStorage;
/**
* Session storage test.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class SessionCartStorageTest extends \PHPUnit_Framework_TestCase
{
public function testGetCurrentCartIdentifier()
{
$session = $this->getMockSession();
$session->expects($this->once())
->method('get')
->will($this->returnValue(123))
;
$storage = new SessionCartStorage($session);
$this->assertEquals(123, $storage->getCurrentCartIdentifier());
}
public function testSetCurrentCartIdentifier()
{
$cart = $this->getMockCart();
$cart->expects($this->once())
->method('getId')
->will($this->returnValue(123))
;
$storage = new SessionCartStorage($this->getSession());
$storage->setCurrentCartIdentifier($cart);
$this->assertEquals(123, $storage->getCurrentCartIdentifier());
return $storage;
}
/**
* @depends testSetCurrentCartIdentifier
*/
public function testResetCurrentCartIdentifier(SessionCartStorage $storage)
{
$storage->resetCurrentCartIdentifier();
$this->assertNull($storage->getCurrentCartIdentifier());
}
private function getSession()
{
return new Session(new MockArraySessionStorage());
}
private function getMockSession()
{
return $this->getMock('Symfony\Component\HttpFoundation\Session\SessionInterface');
}
private function getMockCart()
{
return $this->getMock('Sylius\Bundle\CartBundle\Model\CartInterface');
}
}

View file

@ -1,27 +0,0 @@
<?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.
*/
if (file_exists($file = __DIR__.'/../vendor/autoload.php')) {
$autoload = require_once $file;
} else {
throw new RuntimeException('Install dependencies to run test suite.');
}
spl_autoload_register(function($class) {
if (0 === strpos($class, 'Sylius\\Bundle\\CartBundle\\')) {
$path = __DIR__.'/../'.implode('/', array_slice(explode('\\', $class), 3)).'.php';
if (!stream_resolve_include_path($path)) {
return false;
}
require_once $path;
return true;
}
});

View file

@ -1,16 +0,0 @@
<?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.
*/
if (file_exists($file = __DIR__.'/autoload.php')) {
require_once $file;
} elseif (file_exists($file = __DIR__.'/autoload.php.dist')) {
require_once $file;
}

View file

@ -11,8 +11,8 @@
namespace Sylius\Bundle\CartBundle\Twig;
use Sylius\Bundle\CartBundle\Model\ItemManagerInterface;
use Sylius\Bundle\CartBundle\Provider\CartProviderInterface;
use Sylius\Bundle\ResourceBundle\Manager\ResourceManagerInterface;
use Symfony\Component\Form\FormFactory;
use Twig_Extension;
use Twig_Function_Method;
@ -32,11 +32,11 @@ class SyliusCartExtension extends Twig_Extension
private $cartProvider;
/**
* Item manager.
* Cart item manager.
*
* @var ItemManagerInterface
* @var ResourceManagerInterface
*/
private $itemManager;
private $cartItemManager;
/**
* Form factory.
@ -48,14 +48,14 @@ class SyliusCartExtension extends Twig_Extension
/**
* Constructor.
*
* @param CartProviderInterface $cartProvider
* @param ItemManagerInterface $itemManager
* @param FormFactory $formFactory
* @param CartProviderInterface $cartProvider
* @param ResourceManagerInterface $cartItemManager
* @param FormFactory $formFactory
*/
public function __construct(CartProviderInterface $cartProvider, ItemManagerInterface $itemManager, FormFactory $formFactory)
public function __construct(CartProviderInterface $cartProvider, ResourceManagerInterface $cartItemManager, FormFactory $formFactory)
{
$this->cartProvider = $cartProvider;
$this->itemManager = $itemManager;
$this->cartItemManager = $cartItemManager;
$this->formFactory = $formFactory;
}
@ -89,8 +89,7 @@ class SyliusCartExtension extends Twig_Extension
*/
public function getItemFormView(array $options = array())
{
$item = $this->itemManager->createItem();
$item = $this->cartItemManager->create();
$form = $this->formFactory->create('sylius_cart_item', $item, $options);
return $form->createView();

View file

@ -1,8 +1,8 @@
{
"name": "sylius/cart-bundle",
"type": "symfony-bundle",
"description": "Carts feature for your next Symfony2 application. Clean architecture and simple usage.",
"keywords": ["shop", "ecommerce", "cart", "carts"],
"description": "Cart feature for your next Symfony2 application.",
"keywords": ["shop", "ecommerce", "cart", "carts", "sylius"],
"homepage": "http://sylius.org",
"license": "MIT",
"authors": [
@ -16,13 +16,19 @@
"homepage": "https://github.com/Sylius/SyliusCartBundle/contributors"
}
],
"minimum-stability": "dev",
"require": {
"php": ">=5.3.2",
"symfony/symfony": "2.1.*"
"doctrine/common": "*",
"sylius/resource-bundle": "*",
"symfony/framework-bundle": ">=2.1.0,<2.2.0"
},
"require-dev": {
"doctrine/orm": "*"
"phpspec/phpspec2": "*"
},
"config": {
"bin-dir": "bin"
},
"autoload": {
"psr-0": { "Sylius\\Bundle\\CartBundle": "" }

View file

@ -1,20 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<phpunit bootstrap="./Tests/bootstrap.php" colors="true">
<testsuites>
<testsuite name="SyliusCartBundle test suite">
<directory suffix="Test.php">./Tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory>./</directory>
<exclude>
<directory>./Resources</directory>
<directory>./Tests</directory>
<directory>./vendor</directory>
</exclude>
</whitelist>
</filter>
</phpunit>

View file

@ -0,0 +1,134 @@
<?php
namespace spec\Sylius\Bundle\CartBundle\Model;
use PHPSpec2\ObjectBehavior;
/**
* Cart spec.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class Cart extends ObjectBehavior
{
function it_should_be_initializable()
{
$this->shouldHaveType('Sylius\Bundle\CartBundle\Model\Cart');
}
function it_should_have_proper_default_values()
{
$this->getItems()->shouldHaveType('Doctrine\\Common\\Collections\\Collection');
$this->getTotalItems()->shouldReturn(0);
$this->getTotal()->shouldReturn(0);
$this->shouldNotBeLocked();
$this->getExpiresAt()->shouldHaveType('DateTime');
}
/**
* @param Sylius\Bundle\CartBundle\Model\CartItemInterface $item
*/
function it_should_have_fluid_interface($item)
{
$this->addItem($item)->shouldReturn($this);
$this->removeItem($item)->shouldReturn($this);
$this->clearItems()->shouldReturn($this);
}
function it_should_complain_when_total_items_is_less_than_0()
{
$this
->shouldThrow(new \OutOfRangeException('Total items must not be less than 0'))
->duringSetTotalItems(-1)
;
}
function it_should_reset_total_items_to_0_if_change_is_bigger_than_current_amount()
{
$this->setTotalItems(5);
$this->changeTotalItems(-10);
$this->getTotalItems()->shouldReturn(0);
}
/**
* @param Sylius\Bundle\CartBundle\Model\CartItemInterface $item1
* @param Sylius\Bundle\CartBundle\Model\CartItemInterface $item2
* @param Sylius\Bundle\CartBundle\Model\CartItemInterface $item3
*/
function it_should_calculate_correct_total($item1, $item2, $item3)
{
$item1->getTotal()->willReturn(299.99);
$item2->getTotal()->willReturn(450);
$item3->getTotal()->willReturn(2.50);
$item1->equals($item2)->willReturn(false);
$item1->equals($item3)->willReturn(false);
$item2->equals($item3)->willReturn(false);
$this
->addItem($item1)
->addItem($item2)
->addItem($item3)
;
$this->calculateTotal();
$this->getTotal()->shouldReturn(752.49);
}
function it_should_be_empty_if_no_items_inside()
{
$this->shouldBeEmpty();
}
/**
* @param Sylius\Bundle\CartBundle\Model\CartItemInterface $item
*/
function it_should_add_and_remove_items_properly($item)
{
$this->hasItem($item)->shouldReturn(false);
$this->addItem($item);
$this->hasItem($item)->shouldReturn(true);
$this->removeItem($item);
$this->hasItem($item)->shouldReturn(false);
$this->shouldBeEmpty();
}
/**
* @param Sylius\Bundle\CartBundle\Model\CartItemInterface $item1
* @param Sylius\Bundle\CartBundle\Model\CartItemInterface $item2
*/
function it_should_sum_the_quantities_of_equal_items($item1, $item2)
{
$item1->getQuantity()->willReturn(3);
$item2->getQuantity()->willReturn(7);
$item1->equals($item2)->willReturn(true);
$this
->addItem($item1)
->addItem($item2)
;
$this->countItems()->shouldReturn(1);
}
function it_should_be_not_expired_by_default()
{
$this->shouldNotBeExpired();
}
function it_should_be_expired_if_the_expiration_time_is_in_past()
{
$expiresAt = new \DateTime('-1 hour');
$this->setExpiresAt($expiresAt);
$this->shouldBeExpired();
}
}

View file

@ -0,0 +1,53 @@
<?php
namespace spec\Sylius\Bundle\CartBundle\Model;
use PHPSpec2\ObjectBehavior;
/**
* Cart item spec.
*
* @author Paweł Jędrzejewski <pjedrzejewski@diweb.pl>
*/
class CartItem extends ObjectBehavior
{
function it_should_be_initializable()
{
$this->shouldHaveType('Sylius\Bundle\CartBundle\Model\CartItem');
}
function it_should_have_proper_default_values()
{
$this->getQuantity()->shouldReturn(1);
$this->getUnitPrice()->shouldReturn(0);
$this->getTotal()->shouldReturn(0);
}
function it_should_complain_when_quantity_is_less_than_1()
{
$this
->shouldThrow(new \OutOfRangeException('Quantity must be greater than 0'))
->duringSetQuantity(-5)
;
}
function it_should_calculate_correct_total()
{
$this->setQuantity(13);
$this->setUnitPrice(14.99);
$this->calculateTotal();
$this->getTotal()->shouldReturn(194.87);
}
/**
* @param Sylius\Bundle\CartBundle\Model\CartItemInterface $otherCartItem
*/
function it_should_not_recognize_items_as_equal_if_they_do_not_have_the_same_id($otherCartItem)
{
$otherCartItem->getId()->willReturn(1);
$this->equals($otherCartItem)->shouldReturn(false);
}
}