Commit ecba15e1 authored by Thorsten Buss's avatar Thorsten Buss

* add CurrencyCart for items with MoneyObje with currency as ItemPrice

* optimize and add some tests and documentation for autocompletition
parent eadec7e1
......@@ -701,6 +701,7 @@ $items->each(function($item)
- rename some functions (items() instead of getItems()) and classes (Item instead of ItemCollection) for better usage (more laravel style)
- change the namespace to BNet
- make item_rules customizable (preparing for own CartClass with additional custom item fields)
- add CurrencyCart for use a cart with Money() prices instead of int
**2.4.0
- added new method on a condition: $condition->getAttributes(); (Please see [Conditions](#conditions) section)
......
......@@ -12,7 +12,8 @@
"require": {
"php": ">=5.4.0",
"illuminate/support": "5.0.x|5.1.x|5.2.x",
"illuminate/validation": "5.0.x|5.1.x|5.2.x"
"illuminate/validation": "5.0.x|5.1.x|5.2.x",
"bnet/money-datatype": "^0.1.0"
},
"require-dev": {
"mockery/mockery": "~0.9",
......
......@@ -48,7 +48,7 @@ class Cart {
protected $item_rules = array(
'id' => 'required',
'price' => 'required|numeric',
// 'price' => 'required|numeric',
'quantity' => 'required|numeric|min:1',
'name' => 'required',
);
......@@ -56,10 +56,10 @@ class Cart {
/**
* our object constructor
*
* @param $session
* @param $events
* @param $instanceName
* @param $session_key
* @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session
* @param \Illuminate\Contracts\Events\Dispatcher $events
* @param string $instanceName
* @param string $session_key
* @param array $custom_item_rules overwrite existing item_rules
*/
public function __construct($session, $events, $instanceName, $session_key, $custom_item_rules=[]) {
......@@ -470,7 +470,7 @@ class Cart {
public function subTotal() {
$cart = $this->items();
$sum = $cart->sum(function ($item) {
$sum = $cart->sum(function (Item $item) {
return $item->priceSumWithConditions();
});
......@@ -539,9 +539,7 @@ class Cart {
* @return bool
*/
public function isEmpty() {
$cart = new Items($this->session->get($this->sessionKeyCartItems));
return $cart->isEmpty();
return $this->items()->isEmpty();
}
/**
......@@ -570,15 +568,24 @@ class Cart {
protected function addRow($id, $item) {
$this->events->fire($this->getInstanceName() . '.adding', array($item, $this));
$cart = $this->items();
$items = $this->items();
$cart->put($id, new Item($item));
$items->put($id, $this->createCartItem($item));
$this->save($cart);
$this->save($items);
$this->events->fire($this->getInstanceName() . '.added', array($item, $this));
}
/**
* create the object for an cart item
* @param $data
* @return Item
*/
protected function createCartItem($data) {
return new Item($data);
}
/**
* save the cart
*
......
<?php
/**
* User: thorsten
* Date: 13.07.16
* Time: 22:48
*/
namespace Bnet\Cart;
use Bnet\Money\Currency;
use Bnet\Money\Money;
/**
* Class CurrencyCart - same as Cart, but work with Money Objects with Currency as pricees
* @package Bnet\Cart
*/
class CurrencyCart extends Cart {
/**
* @var string Alpha ISo Code of the default currency for this cart
*/
protected $currency;
/**
* our object constructor
*
* @param \Symfony\Component\HttpFoundation\Session\SessionInterface $session
* @param \Illuminate\Contracts\Events\Dispatcher $events
* @param string $instanceName
* @param string $session_key
* @param string|Currency $currency Alpha IsoCode of the Currency of this Cart - only items with this currency are allowed and items without currency get this currency
* @param array $custom_item_rules overwrite existing item_rules
*/
public function __construct(\Symfony\Component\HttpFoundation\Session\SessionInterface $session, \Illuminate\Contracts\Events\Dispatcher $events, $instanceName, $session_key, $currency='EUR', $custom_item_rules = []) {
$this->currency = $currency instanceof Currency ? $currency : new Currency($currency);
parent::__construct($session, $events, $instanceName, $session_key, $custom_item_rules);
}
/**
* get cart sub total
*
* @return Money
*/
public function subTotal() {
$sum = $this->items()->sum(function (CurrencyItem $item) {
return $item->priceSumWithConditions()->amount();
});
return new Money($sum, $this->currency);
}
/**
* the new total in which conditions are already applied
*
* @return Money
*/
public function total() {
if ($this->getConditions()->isEmpty())
return $this->subTotal();
$subTotal = $this->subTotal()->amount();
$newTotal = 0;
$process = 0;
$this->getConditions()->each(function ($cond) use ($subTotal, &$newTotal, &$process) {
if ($cond->getTarget() === 'subtotal') {
($process > 0) ? $toBeCalculated = $newTotal : $toBeCalculated = $subTotal;
$newTotal = $cond->applyCondition($toBeCalculated);
$process++;
}
});
return new Money((int)$newTotal, $this->currency);
}
/**
* get the cart
*
* @return CurrencyItems
*/
public function items() {
return (new CurrencyItems($this->session->get($this->sessionKeyCartItems)));
}
/**
* add row to cart collection
*
* @param $id
* @param $item
*/
protected function addRow($id, $item) {
if (!$item['price'] instanceof Money)
$item['price'] = new Money($item['price'], @$item['currency'] ?: $this->currency);
parent::addRow($id, $item);
}
/**
* add item to the cart, it can be an array or multi dimensional array
*
* @param string|array $id
* @param string $name
* @param Money $price
* @param int $quantity
* @param array $attributes
* @param Condition|array $conditions
* @return $this
* @throws \Bnet\Cart\Exceptions\InvalidItemException
*/
public function add($id, $name = null, Money $price = null, $quantity = 1, $attributes = array(), $conditions = array()) {
if (!is_null($price) && !$price->currency()->equals($this->currency))
throw new \Bnet\Cart\Exceptions\CurrencyNotMachedException('given item-currency ['.$price->currency()->code.'] does not match to cart currency ['.$this->currency->code.']' );
return parent::add($id, $name, $price, $quantity, $attributes, $conditions);
}
/**
* create the object for an cart item
* @param $data
* @return Item
*/
protected function createCartItem($data) {
return new CurrencyItem($data, $this->currency);
}
/**
* get an item on a cart by item ID
*
* @param $itemId
* @return CurrencyItem
*/
public function get($itemId) {
$item = parent::get($itemId);
if (!$item['price'] instanceof Money)
$item['price'] = new Money($item['price'], @$item['currency'] ?: $this->currency);
return $item;
}
}
\ No newline at end of file
<?php
/**
* User: thorsten
* Date: 13.07.16
* Time: 23:20
*/
namespace Bnet\Cart;
use Bnet\Money\Currency;
use Bnet\Money\Money;
/**
* Class CurrencyItem
* @package Bnet\Cart
* @inheritdoc
* @property Money|null price
*/
class CurrencyItem extends Item {
/**
* @var Currency|string the currency for this Item for generating Sum Money Objects
*/
protected $currency;
/**
* Create a new collection.
*
* @param mixed $items
* @return void
*/
public function __construct($items, $currency) {
$this->currency = $currency;
parent::__construct($items);
}
/**
* return the price amount for this item
* @return int|null
*/
public function price() {
return $this->price->amount();
$price = $this->price;
return $price instanceOf Money ? $price->amount() : $price;
}
/**
* get the sum of price
*
* @return Money
*/
public function priceSum() {
return new Money(parent::priceSum(), $this->currency);
}
/**
* get the single price in which conditions are already applied
*
* @return Money
*/
public function priceWithConditions() {
return new Money((int)parent::priceWithConditions(), $this->currency);
}
/**
* get the sum of price in which conditions are already applied
*
* @return Money
*/
public function priceSumWithConditions() {
$sum = $this->priceWithConditions()->amount() * $this->quantity;
return new Money((int)$sum, $this->currency);
}
}
\ No newline at end of file
<?php
/**
* User: thorsten
* Date: 13.07.16
* Time: 23:48
*/
namespace Bnet\Cart;
/**
* Class CurrencyItems
* @package Bnet\Cart
* @method CurrencyItem first() first(callable $callback = null, $default = null)
* @method CurrencyItem get() get($key, $default = null)
* @method CurrencyItem last() last(callable $callback = null, $default = null)
* @method CurrencyItem[] all()
*/
class CurrencyItems extends Items {
}
\ No newline at end of file
<?php
/**
* User: thorsten
* Date: 14.07.16
* Time: 00:31
*/
namespace Bnet\Cart\Exceptions;
class CurrencyNotMachedException extends InvalidItemException{
}
\ No newline at end of file
<?php namespace Bnet\Cart\Helpers;
use Bnet\Money\Money;
/**
* Created by PhpStorm.
......@@ -23,6 +24,8 @@ class Helpers {
* @return int
*/
public static function normalizePrice($price) {
if ($price instanceof Money)
return $price;
return (is_string($price)) ? intval($price) : $price;
}
......@@ -31,6 +34,8 @@ class Helpers {
* @param int $mode
*/
public static function intval($value, $mode = self::DEFAULT_ROUND_MODE) {
if ($value instanceof Money)
return $value;
return self::round($value, 0, $mode);
}
......@@ -40,6 +45,8 @@ class Helpers {
* @param int $mode
*/
public static function round($value, $precision = 0, $mode = self::DEFAULT_ROUND_MODE) {
if ($value instanceof Money)
return $value;
return round($value, $precision, $mode);
}
......
......@@ -25,7 +25,7 @@ class Item extends Collection {
* @return mixed|null
*/
public function priceSum() {
return $this->price * $this->quantity;
return $this->price() * $this->quantity;
}
public function __get($name) {
......@@ -48,13 +48,21 @@ class Item extends Collection {
return $this['conditions'] instanceof Condition;
}
/**
* return the price amount for this item
* @return int
*/
public function price() {
return $this->price;
}
/**
* get the single price in which conditions are already applied
*
* @return mixed|null
*/
public function priceWithConditions() {
$originalPrice = $this->price;
$originalPrice = $this->price();
$newPrice = 0;
$processed = 0;
......
......@@ -2,6 +2,14 @@
use Illuminate\Support\Collection;
/**
* Class Items
* @package Bnet\Cart
* @method Item first() first(callable $callback = null, $default = null)
* @method Item get() get($key, $default = null)
* @method Item last() last(callable $callback = null, $default = null)
* @method Item[] all()
*/
class Items extends Collection {
}
\ No newline at end of file
This diff is collapsed.
This diff is collapsed.
<?php
use Symfony\Component\HttpFoundation\Session\SessionInterface;
/**
* Created by PhpStorm.
......@@ -6,7 +7,7 @@
* Date: 1/12/2015
* Time: 10:23 PM
*/
class SessionMock {
class SessionMock implements SessionInterface{
protected $session = array();
......@@ -14,11 +15,196 @@ class SessionMock {
return isset($this->session[$key]);
}
public function get($key) {
return (isset($this->session[$key])) ? $this->session[$key] : null;
/**
* Returns an attribute.
*
* @param string $name The attribute name
* @param mixed $default The default value if not found
*
* @return mixed
*/
public function get($name, $default = null) {
return (isset($this->session[$name])) ? $this->session[$name] : null;
}
public function put($key, $value) {
$this->session[$key] = $value;
}
/**
* Starts the session storage.
*
* @return bool True if session started
*
* @throws \RuntimeException If session fails to start.
*/
public function start() {
// TODO: Implement start() method.
}
/**
* Returns the session ID.
*
* @return string The session ID
*/
public function getId() {
// TODO: Implement getId() method.
}
/**
* Sets the session ID.
*
* @param string $id
*/
public function setId($id) {
// TODO: Implement setId() method.
}
/**
* Returns the session name.
*
* @return mixed The session name
*/
public function getName() {
// TODO: Implement getName() method.
}
/**
* Sets the session name.
*
* @param string $name
*/
public function setName($name) {
// TODO: Implement setName() method.
}
/**
* Invalidates the current session.
*
* Clears all session attributes and flashes and regenerates the
* session and deletes the old session from persistence.
*
* @param int $lifetime Sets the cookie lifetime for the session cookie. A null value
* will leave the system settings unchanged, 0 sets the cookie
* to expire with browser session. Time is in seconds, and is
* not a Unix timestamp.
*
* @return bool True if session invalidated, false if error
*/
public function invalidate($lifetime = null) {
// TODO: Implement invalidate() method.
}
/**
* Migrates the current session to a new session id while maintaining all
* session attributes.
*
* @param bool $destroy Whether to delete the old session or leave it to garbage collection
* @param int $lifetime Sets the cookie lifetime for the session cookie. A null value
* will leave the system settings unchanged, 0 sets the cookie
* to expire with browser session. Time is in seconds, and is
* not a Unix timestamp.
*
* @return bool True if session migrated, false if error
*/
public function migrate($destroy = false, $lifetime = null) {
// TODO: Implement migrate() method.
}
/**
* Force the session to be saved and closed.
*
* This method is generally not required for real sessions as
* the session will be automatically saved at the end of
* code execution.
*/
public function save() {
// TODO: Implement save() method.
}
/**
* Sets an attribute.
*
* @param string $name
* @param mixed $value
*/
public function set($name, $value) {
// TODO: Implement set() method.
}
/**
* Returns attributes.
*
* @return array Attributes
*/
public function all() {
// TODO: Implement all() method.
}
/**
* Sets attributes.
*
* @param array $attributes Attributes
*/
public function replace(array $attributes) {
// TODO: Implement replace() method.
}
/**
* Removes an attribute.
*
* @param string $name
*
* @return mixed The removed value or null when it does not exist
*/
public function remove($name) {
// TODO: Implement remove() method.
}
/**
* Clears all attributes.
*/
public function clear() {
// TODO: Implement clear() method.
}
/**
* Checks if the session was started.
*
* @return bool
*/
public function isStarted() {
// TODO: Implement isStarted() method.
}
/**
* Registers a SessionBagInterface with the session.
*
* @param \Symfony\Component\HttpFoundation\Session\SessionBagInterface $bag
*/
public function registerBag(\Symfony\Component\HttpFoundation\Session\SessionBagInterface $bag) {
// TODO: Implement registerBag() method.
}
/**
* Gets a bag instance by name.
*
* @param string $name
*
* @return \Symfony\Component\HttpFoundation\Session\SessionBagInterface
*/
public function getBag($name) {
// TODO: Implement getBag() method.
}
/**
* Gets session meta.
*
* @return \Symfony\Component\HttpFoundation\Session\Storage\MetadataBag
*/
public function getMetadataBag() {
// TODO: Implement getMetadataBag() method.
}
}
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment