commit fa7e90e48ab3d8dcc42dd6130f4c8b70d6f95a7c Author: Rob Gloudemans Date: Wed May 22 20:12:34 2013 +0200 Initial commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..2c1fc0c --- /dev/null +++ b/.gitignore @@ -0,0 +1,4 @@ +/vendor +composer.phar +composer.lock +.DS_Store \ No newline at end of file diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..0edb59c --- /dev/null +++ b/.travis.yml @@ -0,0 +1,11 @@ +language: php + +php: + - 5.3 + - 5.4 + +before_script: + - curl -s http://getcomposer.org/installer | php + - php composer.phar install --dev + +script: phpunit \ No newline at end of file diff --git a/composer.json b/composer.json new file mode 100644 index 0000000..e79b31e --- /dev/null +++ b/composer.json @@ -0,0 +1,21 @@ +{ + "name": "gloudemans/shoppingcart", + "description": "", + "authors": [ + { + "name": "Rob Gloudemans", + "email": "Rob_Gloudemans@hotmail.com" + } + ], + "require": { + "php": ">=5.3.0", + "illuminate/support": "4.0.x", + "mathiasverraes/money": "dev-zero-equality" + }, + "autoload": { + "psr-0": { + "Gloudemans\\Shoppingcart": "src/" + } + }, + "minimum-stability": "dev" +} \ No newline at end of file diff --git a/phpunit.xml b/phpunit.xml new file mode 100644 index 0000000..12bee7a --- /dev/null +++ b/phpunit.xml @@ -0,0 +1,18 @@ + + + + + ./tests/ + + + \ No newline at end of file diff --git a/src/Gloudemans/Shoppingcart/Cart.php b/src/Gloudemans/Shoppingcart/Cart.php new file mode 100644 index 0000000..35d8c96 --- /dev/null +++ b/src/Gloudemans/Shoppingcart/Cart.php @@ -0,0 +1,251 @@ +session = $session; + } + + /** + * Add a row to the cart + * + * @param string $id Unique ID of the item + * @param string $name Name of the item + * @param int $qty Item qty to add to the cart + * @param float $price Price of one item + * @param Array $options Array of additional options, such as 'size' or 'color' + */ + public function add($id, $name, $qty, $price, $options = array()) + { + $cart = $this->getContent(); + + $rowId = $this->generateRowId($id, $options); + + if($cart->has($rowId)) + { + $row = $cart->get($rowId); + $cart = $this->updateRow($rowId, $row->qty + $qty); + } + else + { + $cart = $this->createRow($rowId, $id, $name, $qty, $price, $options); + } + + return $this->updateCart($cart); + } + + /** + * Update the quantity of one row of the cart + * @param string $rowId The rowid of the item you want to update + * @param integer $qty New quantity of the item + * @return boolean + */ + public function update($rowId, $qty) + { + if($qty == 0) + { + return $this->remove($rowId); + } + + return $this->updateRow($rowId, $qty); + } + + /** + * Remove a row from the cart + * + * @param string $rowId The rowid of the item + * @return boolean + */ + public function remove($rowId) + { + $cart = $this->getContent(); + + $cart->forget($rowId); + + return $this->updateCart($cart); + } + + /** + * Get a row of the cart by its ID + * + * @param string $rowId The ID of the row to fetch + * @return Array + */ + public function get($rowId) + { + $cart = $this->getContent(); + + return ($cart->has($rowId)) ? $cart->get($rowId) : NULL; + } + + /** + * Get the cart content + * + * @return Array + */ + public function content() + { + $cart = $this->getContent(); + + return (empty($cart)) ? NULL : $cart; + } + + /** + * Empty the cart + * + * @return boolean + */ + public function destroy() + { + return $this->updateCart(NULL); + } + + /** + * Get the price total + * + * @return float + */ + public function total() + { + $total = 0; + $cart = $this->getContent(); + + if(empty($cart)) + { + return $total; + } + + foreach($cart AS $row) + { + $total += $row->subtotal; + } + + return $total; + } + + /** + * Get the number of items in the cart + * + * @return int + */ + public function count($totalItems = TRUE) + { + $cart = $this->getContent(); + + if( ! $totalItems) + { + return $cart->count(); + } + + $count = 0; + + foreach($cart AS $row) + { + $count += $row->qty; + } + + return $count; + } + + /** + * Generate a unique id for the new row + * + * @param string $id Unique ID of the item + * @param Array $options Array of additional options, such as 'size' or 'color' + * @return boolean + */ + protected function generateRowId($id, $options) + { + return md5($id . serialize($options)); + } + + /** + * Update the cart + * @param Array $cart The new cart content + * @return void + */ + protected function updateCart($cart) + { + return $this->session->put('cart', $cart); + } + + /** + * Get the carts content, if there is no cart content set yet, return a new empty Collection + * + * @return Illuminate\Support\Collection + */ + protected function getContent() + { + $content = ($this->session->has('cart')) ? $this->session->get('cart') : new CartCollection; + + return $content; + } + + /** + * Update a row if the rowId already exists + * + * @param string $rowId The ID of the row to update + * @param integer $qty The quantity to add to the row + * @return Collection + */ + protected function updateRow($rowId, $qty) + { + $cart = $this->getContent(); + + $row = $cart->get($rowId); + + $row->qty = $qty; + $row->subtotal = $row->qty * $row->price; + + $cart->put($rowId, $row); + + return $cart; + } + + /** + * Create a new row Object + * + * @param string $rowId The ID of the new row + * @param string $id Unique ID of the item + * @param string $name Name of the item + * @param int $qty Item qty to add to the cart + * @param float $price Price of one item + * @param Array $options Array of additional options, such as 'size' or 'color' + * @return Collection + */ + protected function createRow($rowId, $id, $name, $qty, $price, $options) + { + $cart = $this->getContent(); + + $newRow = new CartRowCollection([ + 'rowid' => $rowId, + 'id' => $id, + 'name' => $name, + 'qty' => $qty, + 'price' => $price, + 'options' => new CartRowOptionsCollection($options), + 'subtotal' => $qty * $price + ]); + + $cart->put($rowId, $newRow); + + return $cart; + } + +} \ No newline at end of file diff --git a/src/Gloudemans/Shoppingcart/CartCollection.php b/src/Gloudemans/Shoppingcart/CartCollection.php new file mode 100644 index 0000000..c825aca --- /dev/null +++ b/src/Gloudemans/Shoppingcart/CartCollection.php @@ -0,0 +1,7 @@ +has($arg)) + { + return $this->get($arg); + } + + return NULL; + } + +} \ No newline at end of file diff --git a/src/Gloudemans/Shoppingcart/CartRowOptionsCollection.php b/src/Gloudemans/Shoppingcart/CartRowOptionsCollection.php new file mode 100644 index 0000000..8b7a3c7 --- /dev/null +++ b/src/Gloudemans/Shoppingcart/CartRowOptionsCollection.php @@ -0,0 +1,22 @@ +has($arg)) + { + return $this->get($arg); + } + + return NULL; + } + +} \ No newline at end of file diff --git a/src/Gloudemans/Shoppingcart/Facades/Cart.php b/src/Gloudemans/Shoppingcart/Facades/Cart.php new file mode 100644 index 0000000..00c3d2c --- /dev/null +++ b/src/Gloudemans/Shoppingcart/Facades/Cart.php @@ -0,0 +1,14 @@ +app['cart'] = $this->app->share(function($app) + { + $session = $this->app['session']; + return new Cart($session); + }); + } +} \ No newline at end of file diff --git a/tests/.gitkeep b/tests/.gitkeep new file mode 100644 index 0000000..e69de29 diff --git a/tests/CartTest.php b/tests/CartTest.php new file mode 100644 index 0000000..5872764 --- /dev/null +++ b/tests/CartTest.php @@ -0,0 +1,126 @@ + 'L']); + + $this->assertEquals(Cart::count(), 1); + $this->assertInstanceOf('Gloudemans\Shoppingcart\CartCollection', Cart::content()); + } + + public function testCartCanAddToExisting() + { + Cart::add(1, 'test', 1, 10.00, ['size' => 'L']); + Cart::add(1, 'test', 1, 10.00, ['size' => 'L']); + + $rowId = Cart::content()->first()->rowid; + + $this->assertEquals(Cart::get($rowId)->qty, 2); + $this->assertInstanceOf('Gloudemans\Shoppingcart\CartCollection', Cart::content()); + } + + public function testCartCanUpdate() + { + Cart::add(1, 'test', 1, 10.00, ['size' => 'L']); + + $rowId = Cart::content()->first()->rowid; + + Cart::update($rowId, 2); + + $this->assertEquals(Cart::get($rowId)->qty, 2); + $this->assertInstanceOf('Gloudemans\Shoppingcart\CartCollection', Cart::content()); + } + + public function testCartCanRemove() + { + Cart::add(1, 'test', 1, 10.00, ['size' => 'L']); + Cart::add(2, 'test', 1, 10.00, ['size' => 'L']); + + $rowId = Cart::content()->first()->rowid; + + Cart::remove($rowId); + + $this->assertEquals(Cart::count(), 1); + $this->assertNull(Cart::get($rowId)); + $this->assertInstanceOf('Gloudemans\Shoppingcart\CartCollection', Cart::content()); + } + + public function testCartCanRemoveOnUpdate() + { + Cart::add(1, 'test', 1, 10.00, ['size' => 'L']); + + $rowId = Cart::content()->first()->rowid; + + Cart::update($rowId, 0); + + $this->assertEquals(Cart::count(), 0); + $this->assertNull(Cart::get($rowId)); + $this->assertInstanceOf('Gloudemans\Shoppingcart\CartCollection', Cart::content()); + } + + public function testCartCanGet() + { + Cart::add(1, 'test', 1, 10.00, ['size' => 'L']); + + $rowId = Cart::content()->first()->rowid; + + $row = Cart::get($rowId); + + $this->assertEquals($row->id, 1); + $this->assertEquals($row->name, 'test'); + $this->assertEquals($row->qty, 1); + $this->assertEquals($row->price, 10.00); + $this->assertInstanceOf('Gloudemans\Shoppingcart\CartRowCollection', $row); + $this->assertInstanceOf('Gloudemans\Shoppingcart\CartRowOptionsCollection', $row->options); + $this->assertEquals($row, Cart::content()->first()); + $this->assertInstanceOf('Gloudemans\Shoppingcart\CartCollection', Cart::content()); + } + + public function testCartCanGetContent() + { + Cart::add(1, 'test', 1, 10.00, ['size' => 'L']); + + $this->assertEquals(Cart::content()->count(), 1); + $this->assertInstanceOf('Gloudemans\Shoppingcart\CartCollection', Cart::content()); + } + + public function testCartCanDestroy() + { + Cart::add(1, 'test', 1, 10.00, ['size' => 'L']); + + Cart::destroy(); + + $this->assertEquals(Cart::count(), 0); + $this->assertInstanceOf('Gloudemans\Shoppingcart\CartCollection', Cart::content()); + } + + public function testCartCanGetTotal() + { + Cart::add(1, 'test', 1, 10.00, ['size' => 'L']); + Cart::add(2, 'test', 1, 10.00, ['size' => 'L']); + + $total = Cart::total(); + + $this->assertTrue(is_float($total)); + $this->assertEquals($total, 20.00); + } + + public function testCartCanGetCount() + { + Cart::add(1, 'test', 1, 10.00, ['size' => 'L']); + Cart::add(2, 'test', 2, 10.00, ['size' => 'L']); + + $count = Cart::count(false); + + $this->assertTrue(is_integer($count)); + $this->assertEquals($count, 2); + + $count = Cart::count(); + + $this->assertTrue(is_integer($count)); + $this->assertEquals($count, 3); + } + +} \ No newline at end of file