Compare commits

..
27 Commits
Author SHA1 Message Date
Joel Male 4a312a37e2 1.0.7 2024-08-30 09:44:40 +10:00
github-actions[bot] 274a8504af Merge pull request #10 from wearepixel/dependabot/composer/master/pestphp/pest-2.35.1
Bump pestphp/pest from 2.35.0 to 2.35.1
2024-08-26 12:56:01 +00:00
dependabot[bot] 4f22672ca5 Bump pestphp/pest from 2.35.0 to 2.35.1
Bumps [pestphp/pest](https://github.com/pestphp/pest) from 2.35.0 to 2.35.1.
- [Release notes](https://github.com/pestphp/pest/releases)
- [Changelog](https://github.com/pestphp/pest/blob/2.x/RELEASE.md)
- [Commits](https://github.com/pestphp/pest/compare/v2.35.0...v2.35.1)

---
updated-dependencies:
- dependency-name: pestphp/pest
  dependency-type: direct:development
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-26 12:55:45 +00:00
Joel Male 61475a7060 1.0.6 2024-08-26 10:58:14 +10:00
Joel Male 6604cf984d fix tests & validation errors 2024-08-26 10:57:02 +10:00
Joel Male 7d955d722c Merge pull request #9 from wearepixel/task/add-items-with-no-price
Add items with no price
2024-08-26 10:49:47 +10:00
Joel Male 54d94d8d12 Add items with no price 2024-08-26 10:38:20 +10:00
Joel Male e49ebe02e0 1.0.4 2024-08-20 16:58:57 +10:00
Joel Male 28b451583d Merge pull request #8 from wearepixel/issue/cart-conditions-break-if-one-makes-the-subtotal-free-and-another-adds-to-the-subtotal
Cart conditions break if one makes the subtotal free and another adds to the subtotal
2024-08-20 16:58:24 +10:00
Joel Male 3673f360b7 feat: fix tests 2024-08-20 16:57:11 +10:00
Joel Male f6447ad4d9 feat: add failing tests 2024-08-20 16:57:06 +10:00
Joel Male b102dd2356 1.0.3 2024-08-19 10:35:54 +10:00
Joel Male 25fc662c05 formatting 2024-08-16 19:23:01 +10:00
Joel Male 57328c2f64 legal jargon 2024-08-16 19:23:01 +10:00
github-actions[bot] 4d19211f2c Merge pull request #5 from wearepixel/dependabot/composer/master/pestphp/pest-2.35.0
Bump pestphp/pest from 2.34.4 to 2.35.0
2024-08-16 09:20:37 +00:00
dependabot[bot] 8cee4f6208 Bump pestphp/pest from 2.34.4 to 2.35.0
Bumps [pestphp/pest](https://github.com/pestphp/pest) from 2.34.4 to 2.35.0.
- [Release notes](https://github.com/pestphp/pest/releases)
- [Changelog](https://github.com/pestphp/pest/blob/2.x/RELEASE.md)
- [Commits](https://github.com/pestphp/pest/compare/v2.34.4...v2.35.0)

---
updated-dependencies:
- dependency-name: pestphp/pest
  dependency-type: direct:development
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <support@github.com>
2024-08-16 09:20:26 +00:00
Joel Male 0ec0668bcf code cleanup 2024-08-16 19:19:14 +10:00
Joel Male 9a4b5382bd 1.0.2 2024-08-16 16:55:10 +10:00
Joel Male 95054f41a4 feature: quantities now support decimals
Merge pull request #4 from wearepixel/feature/quantities-now-support-decimals
2024-08-16 16:52:13 +10:00
Joel Male 0a9bcc2832 quantities now support decimals (so adding 1.1, or setting it to 1.1) 2024-08-16 16:49:59 +10:00
Joel Male 8c8c90c170 Feature: Cart item orders never change
Merge pull request #2 from wearepixel/feature/cart-item-orders-never-change
2024-08-16 16:33:26 +10:00
Pixel Tech 18c753f39b Apply Laravel Pint
Signed-off-by: Pixel Tech <tech@wearepixel.com.au>
2024-08-16 06:33:03 +00:00
Joel Male d12a566366 cart item orders never change 2024-08-16 16:29:46 +10:00
Joel Male 66fd4c9099 v1.0.1 2024-08-16 15:30:57 +10:00
Joel Male d48f54cf16 move to round() instead of number_format() 2024-08-16 15:06:33 +10:00
Joel Male 24f64e712c code cleanup 2024-08-16 14:55:54 +10:00
Joel Male 85ae0c30c5 test updates & working on calculating condition values based on orders 2024-08-15 17:21:19 +10:00
35 changed files with 2365 additions and 1271 deletions
+4 -4
View File
@@ -3,15 +3,15 @@ version: 2
updates: updates:
- package-ecosystem: "github-actions" - package-ecosystem: "github-actions"
directory: "/" directory: "/"
target-branch: "develop" target-branch: "master"
schedule: schedule:
interval: "weekly" interval: "weekly"
labels: labels:
- "dependencies" - "deps"
- package-ecosystem: "composer" - package-ecosystem: "composer"
directory: "/" directory: "/"
target-branch: "develop" target-branch: "master"
schedule: schedule:
interval: "weekly" interval: "weekly"
labels: labels:
- "dependencies" - "deps"
+1
View File
@@ -3,3 +3,4 @@
.idea .idea
.phpunit.result.cache .phpunit.result.cache
READMETODO.md READMETODO.md
build
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) Pixel <hello@wearepixel.com.au> Copyright (c) Pixel Digital Pty Ltd <hello@wearepixel.com.au>
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal
+90 -9
View File
@@ -33,14 +33,47 @@ ## Installing
Install the package through [Composer](http://getcomposer.org/). Install the package through [Composer](http://getcomposer.org/).
`composer require "wearepixel/laravel-cart"` `composer require "pixeldigital/laravel-cart"`
## Configuration ## Configuration
You can publish the configuration file to customize various options. You can publish the configuration file to customize various options.
```php ```php
php artisan vendor:publish --provider="Wearepixel\Cart\CartServiceProvider" --tag="config" php artisan vendor:publish --provider="Pixeldigital\Cart\CartServiceProvider" --tag="config"
```
### Formatting Numbers
The package by default does not use round to format numbers, and instead returns the number using floatval().
If you'd prefer this number to be rounded, you can customize the formatting in the configuration file.
Defaults to false.
```php
'format_numbers' => env('LARAVEL_CART_FORMAT_VALUES', false),
'round_mode' => env('LARAVEL_CART_ROUND_MODE', 'down'),
```
### Decimals
You can customize the number of decimals in the configuration file.
Defaults to 2.
```php
'decimals' => env('LARAVEL_CART_DECIMALS', 2),
```
### Round Mode
The package uses the `round` function to round the prices. You can customize the rounding mode in the configuration file.
Defaults to `down`.
```php
'round_mode' => env('LARAVEL_CART_ROUND_MODE', 'down'),
``` ```
## HOW TO USE ## HOW TO USE
@@ -269,7 +302,7 @@ #### Adding a condition to the cart: **Cart::condition()**
```php ```php
// Add a single condition to the cart // Add a single condition to the cart
$condition = new \Wearepixel\Cart\CartCondition([ $condition = new \Pixeldigital\Cart\CartCondition([
'name' => 'Tax: 10%', 'name' => 'Tax: 10%',
'type' => 'tax', 'type' => 'tax',
'target' => 'subtotal', // this condition will be applied to cart's subtotal when getSubTotal() is called. 'target' => 'subtotal', // this condition will be applied to cart's subtotal when getSubTotal() is called.
@@ -282,7 +315,7 @@ #### Adding a condition to the cart: **Cart::condition()**
Cart::condition($condition); Cart::condition($condition);
// Add multiple conditions // Add multiple conditions
$tax = new \Wearepixel\Cart\CartCondition([ $tax = new \Pixeldigital\Cart\CartCondition([
'name' => 'Tax: 10%', 'name' => 'Tax: 10%',
'type' => 'tax', 'type' => 'tax',
'target' => 'subtotal', // this condition will be applied to cart's subtotal when getSubTotal() is called. 'target' => 'subtotal', // this condition will be applied to cart's subtotal when getSubTotal() is called.
@@ -290,7 +323,7 @@ #### Adding a condition to the cart: **Cart::condition()**
'order' => 2 'order' => 2
]); ]);
$shipping = new \Wearepixel\Cart\CartCondition([ $shipping = new \Pixeldigital\Cart\CartCondition([
'name' => 'Shipping: $15', 'name' => 'Shipping: $15',
'type' => 'shipping', 'type' => 'shipping',
'target' => 'subtotal', // this condition will be applied to cart's subtotal when getSubTotal() is called. 'target' => 'subtotal', // this condition will be applied to cart's subtotal when getSubTotal() is called.
@@ -305,7 +338,7 @@ #### Adding a condition to the cart: **Cart::condition()**
Cart::condition([$tax, $shipping]); Cart::condition([$tax, $shipping]);
// add condition to only apply on totals, not in subtotal // add condition to only apply on totals, not in subtotal
$shipping = new \Wearepixel\Cart\CartCondition([ $shipping = new \Pixeldigital\Cart\CartCondition([
'name' => 'Express Shipping $15', 'name' => 'Express Shipping $15',
'type' => 'shipping', 'type' => 'shipping',
'target' => 'total', 'target' => 'total',
@@ -341,7 +374,14 @@ #### Getting conditions on the cart: **Cart::getConditions()**
$condition->getAttributes(); // the attributes of the condition, returns an empty [] if no attributes added $condition->getAttributes(); // the attributes of the condition, returns an empty [] if no attributes added
``` ```
### Calculating condition value: **Cart::getCondition('Tax: 10%')->getCalculatedValue($subTotal)** ### Calculating condition value
There are 2 ways to calculate the value of a condition:
1. Using the `getCalculatedValue` method on the condition instance
2. Using the `getCalculatedValueForCondition` method on the cart instance and passing the condition name
#### Using the `getCalculatedValue` method on the condition instance
```php ```php
$subTotal = Cart::getSubTotal(); $subTotal = Cart::getSubTotal();
@@ -349,6 +389,39 @@ ### Calculating condition value: **Cart::getCondition('Tax: 10%')->getCalculated
$conditionCalculatedValue = $condition->getCalculatedValue($subTotal); $conditionCalculatedValue = $condition->getCalculatedValue($subTotal);
``` ```
#### Using the `getCalculatedValueForCondition` method on the cart instance
This method automatically calculates the value of a condition by it's name based on the order of the conditions.
```php
Cart::add([
'id' => 1,
'name' => 'Apple iPhone 15',
'price' => 200,
'quantity' => 1,
'attributes' => [],
]);
$couponDiscount = new CartCondition([
'name' => 'Coupon Discount',
'type' => 'discount',
'target' => 'subtotal',
'value' => '-200',
'order' => 1,
]);
$giftCard = new CartCondition([
'name' => 'Gift Card',
'type' => 'discount',
'target' => 'subtotal',
'value' => '-200',
'order' => 2,
]);
Cart::getCalculatedValueForCondition('Coupon Discount'); // returns 200
Cart::getCalculatedValueForCondition('Gift Card'); // returns 0 as the coupon discount is applied first and brings the subtotal to 0
```
### Condition on items ### Condition on items
Item conditions are useful if you have discounts to be applied specifically on an item and not on the whole cart value. Item conditions are useful if you have discounts to be applied specifically on an item and not on the whole cart value.
@@ -356,7 +429,7 @@ ### Condition on items
```php ```php
// lets create first our condition instance // lets create first our condition instance
$saleCondition = new \Wearepixel\Cart\CartCondition([ $saleCondition = new \Pixeldigital\Cart\CartCondition([
'name' => '50% Off', 'name' => '50% Off',
'type' => 'tax', 'type' => 'tax',
'value' => '-50%', 'value' => '-50%',
@@ -376,7 +449,7 @@ ### Condition on items
Cart::add($product); Cart::add($product);
// You can of course also do multiple conditions on an item // You can of course also do multiple conditions on an item
$saleCondition = new \Wearepixel\Cart\CartCondition([ $saleCondition = new \Pixeldigital\Cart\CartCondition([
'name' => 'SALE 5%', 'name' => 'SALE 5%',
'type' => 'sale', 'type' => 'sale',
'value' => '-5%', 'value' => '-5%',
@@ -426,10 +499,18 @@ #### Add condition to existing Item on the cart: **Cart::addItemCondition($produ
### Clearing Cart Conditions: **Cart::clearCartConditions()** ### Clearing Cart Conditions: **Cart::clearCartConditions()**
This clears all cart level conditions, and does not affect item level conditions.
```php ```php
Cart::clearCartConditions() Cart::clearCartConditions()
``` ```
If you wish to clear all conditions from all items and the cart, use **Cart::clearAllConditions()**
```php
Cart::clearAllConditions()
```
### Remove a specific cart condtion: **Cart::removeCartCondition($conditionName)** ### Remove a specific cart condtion: **Cart::removeCartCondition($conditionName)**
```php ```php
+8 -7
View File
@@ -1,6 +1,6 @@
{ {
"name": "wearepixel/laravel-cart", "name": "pixeldigital/laravel-cart",
"version": "1.0.0", "version": "1.0.7",
"description": "A cart implementation for Laravel", "description": "A cart implementation for Laravel",
"keywords": [ "keywords": [
"laravel", "laravel",
@@ -19,7 +19,7 @@
} }
], ],
"require": { "require": {
"php": ">=8.0", "php": ">=8.1",
"illuminate/support": "^9.0|^10.0|^11.0", "illuminate/support": "^9.0|^10.0|^11.0",
"illuminate/validation": "^9.0|^10.0|^11.0", "illuminate/validation": "^9.0|^10.0|^11.0",
"illuminate/translation": "^9.0|^10.0|^11.0" "illuminate/translation": "^9.0|^10.0|^11.0"
@@ -27,21 +27,22 @@
"require-dev": { "require-dev": {
"mockery/mockery": "^1.4.2", "mockery/mockery": "^1.4.2",
"laravel/pint": "dev-main", "laravel/pint": "dev-main",
"pestphp/pest": "2.34.4" "pestphp/pest": "2.35.1",
"larapack/dd": "dev-master"
}, },
"autoload": { "autoload": {
"psr-4": { "psr-4": {
"Wearepixel\\Cart\\": "src/" "Pixeldigital\\Cart\\": "src/"
} }
}, },
"minimum-stability": "dev", "minimum-stability": "dev",
"extra": { "extra": {
"laravel": { "laravel": {
"providers": [ "providers": [
"Wearepixel\\Cart\\CartServiceProvider" "Pixeldigital\\Cart\\CartServiceProvider"
], ],
"aliases": { "aliases": {
"Cart": "Wearepixel\\Cart\\Facades\\CartFacade" "Cart": "Pixeldigital\\Cart\\Facades\\CartFacade"
} }
} }
}, },
Generated
+188 -63
View File
@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically" "This file is @generated automatically"
], ],
"content-hash": "b25e260acd3e7cf87e600ba7103131f4", "content-hash": "726c11e0474359fea45e3d6790b14426",
"packages": [ "packages": [
{ {
"name": "brick/math", "name": "brick/math",
@@ -816,12 +816,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/illuminate/validation.git", "url": "https://github.com/illuminate/validation.git",
"reference": "9398c6e24bf1b0ac12a7160f85bd0cc5e8f4305d" "reference": "60474ce720aab7264ed8d75a344e8a8af911e417"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/illuminate/validation/zipball/9398c6e24bf1b0ac12a7160f85bd0cc5e8f4305d", "url": "https://api.github.com/repos/illuminate/validation/zipball/60474ce720aab7264ed8d75a344e8a8af911e417",
"reference": "9398c6e24bf1b0ac12a7160f85bd0cc5e8f4305d", "reference": "60474ce720aab7264ed8d75a344e8a8af911e417",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -869,7 +869,7 @@
"issues": "https://github.com/laravel/framework/issues", "issues": "https://github.com/laravel/framework/issues",
"source": "https://github.com/laravel/framework" "source": "https://github.com/laravel/framework"
}, },
"time": "2024-08-05T13:45:12+00:00" "time": "2024-08-13T17:23:08+00:00"
}, },
{ {
"name": "nesbot/carbon", "name": "nesbot/carbon",
@@ -1212,12 +1212,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/finder.git", "url": "https://github.com/symfony/finder.git",
"reference": "51c0ff591e6295f21e1789e55a6e57457980895e" "reference": "0470b8dc10ca08d23aeaabbed5b961c928e4d89d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/finder/zipball/51c0ff591e6295f21e1789e55a6e57457980895e", "url": "https://api.github.com/repos/symfony/finder/zipball/0470b8dc10ca08d23aeaabbed5b961c928e4d89d",
"reference": "51c0ff591e6295f21e1789e55a6e57457980895e", "reference": "0470b8dc10ca08d23aeaabbed5b961c928e4d89d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1268,7 +1268,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-08-12T10:26:02+00:00" "time": "2024-08-13T14:29:53+00:00"
}, },
{ {
"name": "symfony/http-foundation", "name": "symfony/http-foundation",
@@ -1276,12 +1276,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-foundation.git", "url": "https://github.com/symfony/http-foundation.git",
"reference": "4187b642a75b3d56ae1bf1461091eedbef2e06d6" "reference": "79d0023c23d92d49c43be47c726e92366b4d3a81"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/4187b642a75b3d56ae1bf1461091eedbef2e06d6", "url": "https://api.github.com/repos/symfony/http-foundation/zipball/79d0023c23d92d49c43be47c726e92366b4d3a81",
"reference": "4187b642a75b3d56ae1bf1461091eedbef2e06d6", "reference": "79d0023c23d92d49c43be47c726e92366b4d3a81",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1345,7 +1345,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-08-06T10:13:58+00:00" "time": "2024-08-13T12:32:31+00:00"
}, },
{ {
"name": "symfony/mime", "name": "symfony/mime",
@@ -1353,12 +1353,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/mime.git", "url": "https://github.com/symfony/mime.git",
"reference": "ab31998ee18185ce4cdea28bb52ffbda575378ee" "reference": "52dc06994d8ee1f97bdc6a80c758c1a6bc482f78"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/mime/zipball/ab31998ee18185ce4cdea28bb52ffbda575378ee", "url": "https://api.github.com/repos/symfony/mime/zipball/52dc06994d8ee1f97bdc6a80c758c1a6bc482f78",
"reference": "ab31998ee18185ce4cdea28bb52ffbda575378ee", "reference": "52dc06994d8ee1f97bdc6a80c758c1a6bc482f78",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1429,7 +1429,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-08-12T12:27:03+00:00" "time": "2024-08-13T14:29:53+00:00"
}, },
{ {
"name": "symfony/polyfill-intl-idn", "name": "symfony/polyfill-intl-idn",
@@ -2465,6 +2465,47 @@
}, },
"time": "2024-08-01T12:14:16+00:00" "time": "2024-08-01T12:14:16+00:00"
}, },
{
"name": "larapack/dd",
"version": "dev-master",
"source": {
"type": "git",
"url": "https://github.com/larapack/dd.git",
"reference": "561b5111a13d0094b59b5c81b1572489485fb948"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/larapack/dd/zipball/561b5111a13d0094b59b5c81b1572489485fb948",
"reference": "561b5111a13d0094b59b5c81b1572489485fb948",
"shasum": ""
},
"require": {
"symfony/var-dumper": "*"
},
"default-branch": true,
"type": "package",
"autoload": {
"files": [
"src/helper.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Mark Topper",
"email": "hi@webman.io"
}
],
"description": "`dd` is a helper method in Laravel. This package will add the `dd` to your application.",
"support": {
"issues": "https://github.com/larapack/dd/issues",
"source": "https://github.com/larapack/dd/tree/v1.1"
},
"time": "2016-12-15T09:34:34+00:00"
},
{ {
"name": "laravel/pint", "name": "laravel/pint",
"version": "dev-main", "version": "dev-main",
@@ -2922,36 +2963,36 @@
}, },
{ {
"name": "pestphp/pest", "name": "pestphp/pest",
"version": "v2.34.4", "version": "v2.35.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/pestphp/pest.git", "url": "https://github.com/pestphp/pest.git",
"reference": "6a1161ead830294ef8e21fab83c0bd118b0df7cc" "reference": "b13acb630df52c06123588d321823c31fc685545"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/pestphp/pest/zipball/6a1161ead830294ef8e21fab83c0bd118b0df7cc", "url": "https://api.github.com/repos/pestphp/pest/zipball/b13acb630df52c06123588d321823c31fc685545",
"reference": "6a1161ead830294ef8e21fab83c0bd118b0df7cc", "reference": "b13acb630df52c06123588d321823c31fc685545",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"brianium/paratest": "^7.3.1", "brianium/paratest": "^7.3.1",
"nunomaduro/collision": "^7.10.0|^8.1.1", "nunomaduro/collision": "^7.10.0|^8.4.0",
"nunomaduro/termwind": "^1.15.1|^2.0.1", "nunomaduro/termwind": "^1.15.1|^2.0.1",
"pestphp/pest-plugin": "^2.1.1", "pestphp/pest-plugin": "^2.1.1",
"pestphp/pest-plugin-arch": "^2.7.0", "pestphp/pest-plugin-arch": "^2.7.0",
"php": "^8.1.0", "php": "^8.1.0",
"phpunit/phpunit": "^10.5.13" "phpunit/phpunit": "^10.5.17"
}, },
"conflict": { "conflict": {
"phpunit/phpunit": ">10.5.13", "phpunit/phpunit": ">10.5.17",
"sebastian/exporter": "<5.1.0", "sebastian/exporter": "<5.1.0",
"webmozart/assert": "<1.11.0" "webmozart/assert": "<1.11.0"
}, },
"require-dev": { "require-dev": {
"pestphp/pest-dev-tools": "^2.16.0", "pestphp/pest-dev-tools": "^2.16.0",
"pestphp/pest-plugin-type-coverage": "^2.8.1", "pestphp/pest-plugin-type-coverage": "^2.8.5",
"symfony/process": "^6.4.0|^7.0.4" "symfony/process": "^6.4.0|^7.1.3"
}, },
"bin": [ "bin": [
"bin/pest" "bin/pest"
@@ -3014,7 +3055,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/pestphp/pest/issues", "issues": "https://github.com/pestphp/pest/issues",
"source": "https://github.com/pestphp/pest/tree/v2.34.4" "source": "https://github.com/pestphp/pest/tree/v2.35.1"
}, },
"funding": [ "funding": [
{ {
@@ -3026,7 +3067,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-03-14T19:44:18+00:00" "time": "2024-08-20T21:41:50+00:00"
}, },
{ {
"name": "pestphp/pest-plugin", "name": "pestphp/pest-plugin",
@@ -3349,12 +3390,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git",
"reference": "aa53f8d4374d1f5bd3fc598548d6272cb5d9bf39" "reference": "60741fe3871f40e44ca10a28ce85d08b7ed841cd"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/aa53f8d4374d1f5bd3fc598548d6272cb5d9bf39", "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/60741fe3871f40e44ca10a28ce85d08b7ed841cd",
"reference": "aa53f8d4374d1f5bd3fc598548d6272cb5d9bf39", "reference": "60741fe3871f40e44ca10a28ce85d08b7ed841cd",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3406,7 +3447,7 @@
"issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues", "issues": "https://github.com/phpDocumentor/ReflectionDocBlock/issues",
"source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.x" "source": "https://github.com/phpDocumentor/ReflectionDocBlock/tree/5.x"
}, },
"time": "2024-05-21T06:14:15+00:00" "time": "2024-08-14T20:00:37+00:00"
}, },
{ {
"name": "phpdocumentor/type-resolver", "name": "phpdocumentor/type-resolver",
@@ -3520,28 +3561,28 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/php-code-coverage.git", "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
"reference": "09d5f55e54c20f2353a790d09772db3ad577b9ac" "reference": "7e308268858ed6baedc8704a304727d20bc07c77"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/09d5f55e54c20f2353a790d09772db3ad577b9ac", "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/7e308268858ed6baedc8704a304727d20bc07c77",
"reference": "09d5f55e54c20f2353a790d09772db3ad577b9ac", "reference": "7e308268858ed6baedc8704a304727d20bc07c77",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"ext-dom": "*", "ext-dom": "*",
"ext-libxml": "*", "ext-libxml": "*",
"ext-xmlwriter": "*", "ext-xmlwriter": "*",
"nikic/php-parser": "^4.18 || ^5.0", "nikic/php-parser": "^4.19.1 || ^5.1.0",
"php": ">=8.1", "php": ">=8.1",
"phpunit/php-file-iterator": "^4.0", "phpunit/php-file-iterator": "^4.1.0",
"phpunit/php-text-template": "^3.0", "phpunit/php-text-template": "^3.0.1",
"sebastian/code-unit-reverse-lookup": "^3.0", "sebastian/code-unit-reverse-lookup": "^3.0.0",
"sebastian/complexity": "^3.0", "sebastian/complexity": "^3.2.0",
"sebastian/environment": "^6.0", "sebastian/environment": "^6.1.0",
"sebastian/lines-of-code": "^2.0", "sebastian/lines-of-code": "^2.0.2",
"sebastian/version": "^4.0", "sebastian/version": "^4.0.1",
"theseer/tokenizer": "^1.2.0" "theseer/tokenizer": "^1.2.3"
}, },
"require-dev": { "require-dev": {
"phpunit/phpunit": "^10.1" "phpunit/phpunit": "^10.1"
@@ -3582,7 +3623,7 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/php-code-coverage/issues", "issues": "https://github.com/sebastianbergmann/php-code-coverage/issues",
"security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy", "security": "https://github.com/sebastianbergmann/php-code-coverage/security/policy",
"source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1" "source": "https://github.com/sebastianbergmann/php-code-coverage/tree/10.1.16"
}, },
"funding": [ "funding": [
{ {
@@ -3590,7 +3631,7 @@
"type": "github" "type": "github"
} }
], ],
"time": "2024-07-17T05:15:22+00:00" "time": "2024-08-22T04:31:57+00:00"
}, },
{ {
"name": "phpunit/php-file-iterator", "name": "phpunit/php-file-iterator",
@@ -3839,16 +3880,16 @@
}, },
{ {
"name": "phpunit/phpunit", "name": "phpunit/phpunit",
"version": "10.5.13", "version": "10.5.17",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/sebastianbergmann/phpunit.git", "url": "https://github.com/sebastianbergmann/phpunit.git",
"reference": "20a63fc1c6db29b15da3bd02d4b6cf59900088a7" "reference": "c1f736a473d21957ead7e94fcc029f571895abf5"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/20a63fc1c6db29b15da3bd02d4b6cf59900088a7", "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/c1f736a473d21957ead7e94fcc029f571895abf5",
"reference": "20a63fc1c6db29b15da3bd02d4b6cf59900088a7", "reference": "c1f736a473d21957ead7e94fcc029f571895abf5",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3920,7 +3961,7 @@
"support": { "support": {
"issues": "https://github.com/sebastianbergmann/phpunit/issues", "issues": "https://github.com/sebastianbergmann/phpunit/issues",
"security": "https://github.com/sebastianbergmann/phpunit/security/policy", "security": "https://github.com/sebastianbergmann/phpunit/security/policy",
"source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.13" "source": "https://github.com/sebastianbergmann/phpunit/tree/10.5.17"
}, },
"funding": [ "funding": [
{ {
@@ -3936,7 +3977,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-03-12T15:37:41+00:00" "time": "2024-04-05T04:39:01+00:00"
}, },
{ {
"name": "psr/log", "name": "psr/log",
@@ -3944,12 +3985,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/php-fig/log.git", "url": "https://github.com/php-fig/log.git",
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001" "reference": "79dff0b268932c640297f5208d6298f71855c03e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/php-fig/log/zipball/fe5ea303b0887d5caefd3d431c3e61ad47037001", "url": "https://api.github.com/repos/php-fig/log/zipball/79dff0b268932c640297f5208d6298f71855c03e",
"reference": "fe5ea303b0887d5caefd3d431c3e61ad47037001", "reference": "79dff0b268932c640297f5208d6298f71855c03e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3985,9 +4026,9 @@
"psr-3" "psr-3"
], ],
"support": { "support": {
"source": "https://github.com/php-fig/log/tree/3.0.0" "source": "https://github.com/php-fig/log/tree/3.0.1"
}, },
"time": "2021-07-14T16:46:02+00:00" "time": "2024-08-21T13:31:24+00:00"
}, },
{ {
"name": "sebastian/cli-parser", "name": "sebastian/cli-parser",
@@ -4918,12 +4959,12 @@
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "2204ca36f39ffe9bc0856123d45fd6cea52a2681" "reference": "cc2dd55c49e04b10cec4aa6e47e099a2d1656845"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/2204ca36f39ffe9bc0856123d45fd6cea52a2681", "url": "https://api.github.com/repos/symfony/console/zipball/cc2dd55c49e04b10cec4aa6e47e099a2d1656845",
"reference": "2204ca36f39ffe9bc0856123d45fd6cea52a2681", "reference": "cc2dd55c49e04b10cec4aa6e47e099a2d1656845",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -5003,7 +5044,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2024-08-12T10:26:02+00:00" "time": "2024-08-15T22:49:18+00:00"
}, },
{ {
"name": "symfony/deprecation-contracts", "name": "symfony/deprecation-contracts",
@@ -5464,6 +5505,89 @@
], ],
"time": "2024-08-12T10:26:02+00:00" "time": "2024-08-12T10:26:02+00:00"
}, },
{
"name": "symfony/var-dumper",
"version": "7.2.x-dev",
"source": {
"type": "git",
"url": "https://github.com/symfony/var-dumper.git",
"reference": "122ba59267fc82caa8f1f509332d4b94a223013b"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/var-dumper/zipball/122ba59267fc82caa8f1f509332d4b94a223013b",
"reference": "122ba59267fc82caa8f1f509332d4b94a223013b",
"shasum": ""
},
"require": {
"php": ">=8.2",
"symfony/polyfill-mbstring": "~1.0"
},
"conflict": {
"symfony/console": "<6.4"
},
"require-dev": {
"ext-iconv": "*",
"symfony/console": "^6.4|^7.0",
"symfony/http-kernel": "^6.4|^7.0",
"symfony/process": "^6.4|^7.0",
"symfony/uid": "^6.4|^7.0",
"twig/twig": "^3.0.4"
},
"bin": [
"Resources/bin/var-dump-server"
],
"type": "library",
"autoload": {
"files": [
"Resources/functions/dump.php"
],
"psr-4": {
"Symfony\\Component\\VarDumper\\": ""
},
"exclude-from-classmap": [
"/Tests/"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Provides mechanisms for walking through any arbitrary PHP variable",
"homepage": "https://symfony.com",
"keywords": [
"debug",
"dump"
],
"support": {
"source": "https://github.com/symfony/var-dumper/tree/7.2"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-08-13T14:29:53+00:00"
},
{ {
"name": "ta-tikoma/phpunit-architecture-test", "name": "ta-tikoma/phpunit-architecture-test",
"version": "0.8.4", "version": "0.8.4",
@@ -5635,12 +5759,13 @@
"aliases": [], "aliases": [],
"minimum-stability": "dev", "minimum-stability": "dev",
"stability-flags": { "stability-flags": {
"laravel/pint": 20 "laravel/pint": 20,
"larapack/dd": 20
}, },
"prefer-stable": false, "prefer-stable": false,
"prefer-lowest": false, "prefer-lowest": false,
"platform": { "platform": {
"php": ">=8.0" "php": ">=8.1"
}, },
"platform-dev": [], "platform-dev": [],
"plugin-api-version": "2.6.0" "plugin-api-version": "2.6.0"
+6 -14
View File
@@ -3,34 +3,26 @@
return [ return [
/* /*
* --------------------------------------------------------------- * ---------------------------------------------------------------
* formatting * Formatting
* --------------------------------------------------------------- * ---------------------------------------------------------------
*
* the formatting of shopping cart values
*/ */
'format_numbers' => env('SHOPPING_FORMAT_VALUES', false), 'format_numbers' => env('LARAVEL_CART_FORMAT_VALUES', false),
'decimals' => env('SHOPPING_DECIMALS', 0), 'decimals' => env('LARAVEL_CART_DECIMALS', 0),
'dec_point' => env('SHOPPING_DEC_POINT', '.'), 'round_mode' => env('LARAVEL_CART_ROUND_MODE', 'down'),
'thousands_sep' => env('SHOPPING_THOUSANDS_SEP', ','),
/* /*
* --------------------------------------------------------------- * ---------------------------------------------------------------
* persistence * Persistence
* --------------------------------------------------------------- * ---------------------------------------------------------------
*
* the configuration for persisting cart
*/ */
'storage' => null, 'storage' => null,
/* /*
* --------------------------------------------------------------- * ---------------------------------------------------------------
* events * Events
* --------------------------------------------------------------- * ---------------------------------------------------------------
*
* the configuration for cart events
*/ */
'events' => null, 'events' => null,
]; ];
+6 -6
View File
@@ -1,17 +1,17 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" <phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="./vendor/phpunit/phpunit/phpunit.xsd"
bootstrap="vendor/autoload.php" bootstrap="vendor/autoload.php"
colors="true" colors="true"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.4/phpunit.xsd"
> >
<testsuites>
<testsuite name="Unit">
<directory suffix="Test.php">./tests/Unit</directory>
</testsuite>
</testsuites>
<source> <source>
<include> <include>
<directory suffix=".php">./src</directory> <directory suffix=".php">./src</directory>
</include> </include>
</source> </source>
<testsuites>
<testsuite name="Laravel Cart Test Suite">
<directory>tests</directory>
</testsuite>
</testsuites>
</phpunit> </phpunit>
+117 -108
View File
@@ -1,12 +1,12 @@
<?php <?php
namespace Wearepixel\Cart; namespace Pixeldigital\Cart;
use Wearepixel\Cart\Helpers\Helpers; use Pixeldigital\Cart\Helpers\Helpers;
use Wearepixel\Cart\Validators\CartItemValidator; use Pixeldigital\Cart\Validators\CartItemValidator;
use Wearepixel\Cart\Exceptions\InvalidItemException; use Pixeldigital\Cart\Exceptions\InvalidItemException;
use Wearepixel\Cart\Exceptions\UnknownModelException; use Pixeldigital\Cart\Exceptions\UnknownModelException;
use Wearepixel\Cart\Exceptions\InvalidConditionException; use Pixeldigital\Cart\Exceptions\InvalidConditionException;
class Cart class Cart
{ {
@@ -131,20 +131,20 @@ public function has($itemId)
* add item to the cart, it can be an array or multi dimensional array * add item to the cart, it can be an array or multi dimensional array
* *
* @param string|array $id * @param string|array $id
* @param string $name
* @param float $price
* @param int $quantity
* @param array $attributes
* @param CartCondition|array $conditions
* @param string $associatedModel
* @return $this * @return $this
* *
* @throws InvalidItemException * @throws InvalidItemException
*/ */
public function add($id, $name = null, $price = null, $quantity = null, $attributes = [], $conditions = [], $associatedModel = null) public function add(
{ string|int|array $id,
// if the first argument is an array, ?string $name = null,
// we will need to call add again ?float $price = null,
int|float|null $quantity = null,
array $attributes = [],
array|CartCondition $conditions = [],
?string $associatedModel = null
): self {
// check if its an array of items
if (is_array($id)) { if (is_array($id)) {
// the first argument is an array, now we will need to check if it is a multi dimensional // the first argument is an array, now we will need to check if it is a multi dimensional
// array, if so, we will iterate through each item and call add again // array, if so, we will iterate through each item and call add again
@@ -153,7 +153,7 @@ public function add($id, $name = null, $price = null, $quantity = null, $attribu
$this->add( $this->add(
$item['id'], $item['id'],
$item['name'], $item['name'],
$item['price'], isset($item['price']) ? $item['price'] : null,
$item['quantity'], $item['quantity'],
Helpers::issetAndHasValueOrAssignDefault($item['attributes'], []), Helpers::issetAndHasValueOrAssignDefault($item['attributes'], []),
Helpers::issetAndHasValueOrAssignDefault($item['conditions'], []), Helpers::issetAndHasValueOrAssignDefault($item['conditions'], []),
@@ -164,7 +164,7 @@ public function add($id, $name = null, $price = null, $quantity = null, $attribu
$this->add( $this->add(
$id['id'], $id['id'],
$id['name'], $id['name'],
$id['price'], isset($id['price']) ? $id['price'] : null,
$id['quantity'], $id['quantity'],
Helpers::issetAndHasValueOrAssignDefault($id['attributes'], []), Helpers::issetAndHasValueOrAssignDefault($id['attributes'], []),
Helpers::issetAndHasValueOrAssignDefault($id['conditions'], []), Helpers::issetAndHasValueOrAssignDefault($id['conditions'], []),
@@ -192,15 +192,13 @@ public function add($id, $name = null, $price = null, $quantity = null, $attribu
$item = $this->validate($data); $item = $this->validate($data);
// get the cart // get the cart
$cart = $this->getContent(); $inCart = $this->get($id);
// if the item is already in the cart we will just update it // if the item is already in the cart we will just update it
if ($cart->has($id)) { if ($inCart) {
$this->update($id, $item); $this->update($id, $item);
} else { } else {
$this->addItem($id, $item);
$this->addRow($id, $item);
} }
$this->currentItemId = $id; $this->currentItemId = $id;
@@ -209,15 +207,9 @@ public function add($id, $name = null, $price = null, $quantity = null, $attribu
} }
/** /**
* update a cart * Update a cart item with whatever data is passed in
*
* @param array $data
*
* the $data will be an associative array, you don't need to pass all the data, only the key value
* of the item you want to update on it
* @return bool
*/ */
public function update($id, $data) public function update(int|string $id, array $data): bool
{ {
if ($this->fireEvent('updating', $data) === false) { if ($this->fireEvent('updating', $data) === false) {
return false; return false;
@@ -225,21 +217,13 @@ public function update($id, $data)
$cart = $this->getContent(); $cart = $this->getContent();
$item = $cart->pull($id); $item = $cart->get($id);
foreach ($data as $key => $value) { foreach ($data as $key => $value) {
// if the key is currently "quantity" we will need to check if an arithmetic
// symbol is present so we can decide if the update of quantity is being added
// or being reduced.
if ($key == 'quantity') { if ($key == 'quantity') {
// we will check if quantity value provided is array,
// if it is, we will need to check if a key "relative" is set
// and we will evaluate its value if true or false,
// this tells us how to treat the quantity value if it should be updated
// relatively to its current quantity value or just totally replace the value
if (is_array($value)) { if (is_array($value)) {
if (isset($value['relative'])) { if (isset($value['relative'])) {
if ((bool) $value['relative']) { if (isset($value['relative']) && $value['relative'] === true) {
$item = $this->updateQuantityRelative($item, $key, $value['value']); $item = $this->updateQuantityRelative($item, $key, $value['value']);
} else { } else {
$item = $this->updateQuantityNotRelative($item, $key, $value['value']); $item = $this->updateQuantityNotRelative($item, $key, $value['value']);
@@ -255,6 +239,7 @@ public function update($id, $data)
} }
} }
// update the item in the cart
$cart->put($id, $item); $cart->put($id, $item);
$this->save($cart); $this->save($cart);
@@ -285,11 +270,11 @@ public function setConfig($config)
public function addItemCondition($productId, $itemCondition) public function addItemCondition($productId, $itemCondition)
{ {
if ($product = $this->get($productId)) { if ($product = $this->get($productId)) {
$conditionInstance = '\\Wearepixel\\Cart\\CartCondition'; $conditionInstance = '\\Pixeldigital\\Cart\\CartCondition';
if ($itemCondition instanceof $conditionInstance) { if ($itemCondition instanceof $conditionInstance) {
// we need to copy first to a temporary variable to hold the conditions // we need to copy first to a temporary variable to hold the conditions
// to avoid hitting this error "Indirect modification of overloaded element of Wearepixel\Cart\ItemCollection has no effect" // to avoid hitting this error "Indirect modification of overloaded element of Pixeldigital\Cart\ItemCollection has no effect"
// this is due to laravel Collection instance that implements Array Access // this is due to laravel Collection instance that implements Array Access
// // see link for more info: http://stackoverflow.com/questions/20053269/indirect-modification-of-overloaded-element-of-splfixedarray-has-no-effect // // see link for more info: http://stackoverflow.com/questions/20053269/indirect-modification-of-overloaded-element-of-splfixedarray-has-no-effect
$itemConditionTempHolder = $product['conditions']; $itemConditionTempHolder = $product['conditions'];
@@ -353,14 +338,11 @@ public function clear()
} }
/** /**
* add a condition on the cart * Adds a condition to the cart
*
* @param CartCondition|array $condition
* @return $this
* *
* @throws InvalidConditionException * @throws InvalidConditionException
*/ */
public function condition($condition) public function condition(array|CartCondition $condition): self
{ {
if (is_array($condition)) { if (is_array($condition)) {
foreach ($condition as $c) { foreach ($condition as $c) {
@@ -371,7 +353,7 @@ public function condition($condition)
} }
if (! $condition instanceof CartCondition) { if (! $condition instanceof CartCondition) {
throw new InvalidConditionException('Argument 1 must be an instance of \'Wearepixel\Cart\CartCondition\''); throw new InvalidConditionException('Argument 1 must be an instance of \'Pixeldigital\Cart\CartCondition\'');
} }
$conditions = $this->getConditions(); $conditions = $this->getConditions();
@@ -497,7 +479,7 @@ public function removeItemCondition($itemId, $conditionName)
// on the given condition name the user wants to remove, if so, // on the given condition name the user wants to remove, if so,
// lets just make $item['conditions'] an empty array as there's just 1 condition on it anyway // lets just make $item['conditions'] an empty array as there's just 1 condition on it anyway
else { else {
$conditionInstance = 'Wearepixel\\Cart\\CartCondition'; $conditionInstance = 'Pixeldigital\\Cart\\CartCondition';
if ($item['conditions'] instanceof $conditionInstance) { if ($item['conditions'] instanceof $conditionInstance) {
if ($tempConditionsHolder->getName() == $conditionName) { if ($tempConditionsHolder->getName() == $conditionName) {
@@ -533,13 +515,9 @@ public function clearItemConditions($itemId)
} }
/** /**
* clears all conditions on a cart, * Clear cart conditions (this does not clear item conditions)
* this does not remove conditions that has been added specifically to an item/product.
* If you wish to remove a specific condition to a product, you may use the method: removeItemCondition($itemId, $conditionName)
*
* @return void
*/ */
public function clearCartConditions() public function clearCartConditions(): void
{ {
$this->session->put( $this->session->put(
$this->sessionKeyCartConditions, $this->sessionKeyCartConditions,
@@ -547,6 +525,20 @@ public function clearCartConditions()
); );
} }
/**
* Clear all conditions from all items and the cart
*/
public function clearAllConditions(): void
{
$cart = $this->getContent();
$cart->each(function ($item) {
$this->clearItemConditions($item->id);
});
$this->clearCartConditions();
}
/** /**
* get cart sub total without conditions * get cart sub total without conditions
* *
@@ -568,81 +560,89 @@ public function getSubTotalWithoutConditions($formatted = true)
* get cart sub total * get cart sub total
* *
* @param bool $formatted * @param bool $formatted
* @return float
*/ */
public function getSubTotal($formatted = true) public function getSubTotal($formatted = true): int|float|string
{ {
$cart = $this->getContent(); $subTotal = 0.00;
// add all the items together with conditions applied
$sum = $cart->sum(function (ItemCollection $item) { $subTotalSum = $this->getContent()->sum(function (ItemCollection $item) {
return $item->getPriceSumWithConditions(false); return $item->getPriceSumWithConditions(false);
}); });
// get the conditions that are meant to be applied // get the conditions that are meant to be applied
// on the subtotal and apply it here before returning the subtotal // on the subtotal and apply it here before returning the subtotal
$conditions = $this $conditionsForSubtotal = $this->getConditions()
->getConditions() ->filter(function (CartCondition $condition) {
->filter(function (CartCondition $cond) { return $condition->getTarget() === 'subtotal';
return $cond->getTarget() === 'subtotal'; })
->sortBy(function (CartCondition $condition) {
return $condition->getOrder();
}); });
// if there is no conditions, lets just return the sum if ($conditionsForSubtotal->isEmpty()) {
if (! $conditions->count()) { return Helpers::formatValue($subTotalSum, $formatted, $this->config);
return Helpers::formatValue($sum, $formatted, $this->config);
} }
// there are conditions, lets apply it $index = 0;
$newTotal = 0.00;
$process = 0;
$conditions->each(function (CartCondition $cond) use ($sum, &$newTotal, &$process) { $conditionsForSubtotal->each(function (CartCondition $condition) use ($subTotalSum, &$subTotal, &$index) {
$toBeCalculated = $index > 0 ? $subTotal : $subTotalSum;
// if this is the first iteration, the toBeCalculated $subTotal = $condition->applyCondition($toBeCalculated);
// should be the sum as initial point of value.
$toBeCalculated = ($process > 0) ? $newTotal : $sum;
$newTotal = $cond->applyCondition($toBeCalculated); $index++;
$process++;
}); });
return Helpers::formatValue((float) $newTotal, $formatted, $this->config); return Helpers::formatValue($subTotal, $formatted, $this->config);
} }
/** /**
* the new total in which conditions are already applied * Get the total of the cart with conditions applied
*
* @return float
*/ */
public function getTotal() public function getTotal(): int|float
{ {
$total = 0.00;
$subTotal = $this->getSubTotal(false); $subTotal = $this->getSubTotal(false);
$newTotal = 0.00; $conditionsForTotal = $this->getConditions()
->filter(function (CartCondition $condition) {
$process = 0; return $condition->getTarget() === 'total';
$conditions = $this
->getConditions()
->filter(function (CartCondition $cond) {
return $cond->getTarget() === 'total';
}); });
// if no conditions were added, just return the sub total // if no conditions were added, just return the sub total
if (! $conditions->count()) { if (! $conditionsForTotal->count()) {
return Helpers::formatValue($subTotal, $this->config['format_numbers'], $this->config); return Helpers::formatValue($subTotal, $this->config['format_numbers'], $this->config);
} }
$conditions $conditionsForTotal->each(function (CartCondition $condition) use ($subTotal, &$total) {
->each(function (CartCondition $cond) use ($subTotal, &$newTotal, &$process) { $toBeCalculated = $total > 0 ? $total : $subTotal;
$toBeCalculated = ($process > 0) ? $newTotal : $subTotal;
$newTotal = $cond->applyCondition($toBeCalculated); $total = $condition->applyCondition($toBeCalculated);
$process++;
}); });
return Helpers::formatValue($newTotal, $this->config['format_numbers'], $this->config); return Helpers::formatValue($total, $this->config['format_numbers'], $this->config);
}
/**
* Get the calculated value for a condition by it's name
*/
public function getCalculatedValueForCondition(string $conditionName): int|float
{
$conditions = $this->getConditions();
$subTotal = $this->getSubTotalWithoutConditions(false);
foreach ($conditions as $condition) {
$conditionValue = $condition->getCalculatedValue($subTotal);
if ($condition->getName() === $conditionName) {
return $conditionValue;
}
$subTotal -= $conditionValue;
}
return 0;
} }
/** /**
@@ -698,15 +698,24 @@ protected function validate($item)
{ {
$rules = [ $rules = [
'id' => 'required', 'id' => 'required',
'price' => 'required|numeric',
'quantity' => 'required|numeric|min:0.1',
'name' => 'required', 'name' => 'required',
'quantity' => 'required|numeric|min:0.1',
]; ];
$validator = CartItemValidator::make($item, $rules); $validator = CartItemValidator::make($item, $rules);
if ($validator->fails()) { if ($validator->fails()) {
throw new InvalidItemException($validator->messages()->first()); if ($validator->errors()->first('id') === 'validation.required') {
throw new InvalidItemException('The id field is required.');
}
if ($validator->errors()->first('name') === 'validation.required') {
throw new InvalidItemException('The name field is required.');
}
if ($validator->errors()->first('quantity') === 'validation.min.numeric') {
throw new InvalidItemException('The quantity must be at least 0.1.');
}
} }
return $item; return $item;
@@ -717,7 +726,7 @@ protected function validate($item)
* *
* @return bool * @return bool
*/ */
protected function addRow($id, $item) protected function addItem($id, $item)
{ {
if ($this->fireEvent('adding', $item) === false) { if ($this->fireEvent('adding', $item) === false) {
return false; return false;
@@ -767,7 +776,7 @@ protected function itemHasConditions($item)
return count($item['conditions']) > 0; return count($item['conditions']) > 0;
} }
$conditionInstance = 'Wearepixel\\Cart\\CartCondition'; $conditionInstance = 'Pixeldigital\\Cart\\CartCondition';
if ($item['conditions'] instanceof $conditionInstance) { if ($item['conditions'] instanceof $conditionInstance) {
return true; return true;
@@ -784,7 +793,7 @@ protected function itemHasConditions($item)
protected function updateQuantityRelative($item, $key, $value) protected function updateQuantityRelative($item, $key, $value)
{ {
if (preg_match('/\-/', $value) == 1) { if (preg_match('/\-/', $value) == 1) {
$value = (int) str_replace('-', '', $value); $value = (float) str_replace('-', '', $value);
// we will not allowed to reduced quantity to 0, so if the given value // we will not allowed to reduced quantity to 0, so if the given value
// would result to item quantity of 0, we will not do it. // would result to item quantity of 0, we will not do it.
@@ -792,9 +801,9 @@ protected function updateQuantityRelative($item, $key, $value)
$item[$key] -= $value; $item[$key] -= $value;
} }
} elseif (preg_match('/\+/', $value) == 1) { } elseif (preg_match('/\+/', $value) == 1) {
$item[$key] += (int) str_replace('+', '', $value); $item[$key] += (float) str_replace('+', '', $value);
} else { } else {
$item[$key] += (int) $value; $item[$key] += (float) $value;
} }
return $item; return $item;
@@ -807,7 +816,7 @@ protected function updateQuantityRelative($item, $key, $value)
*/ */
protected function updateQuantityNotRelative($item, $key, $value) protected function updateQuantityNotRelative($item, $key, $value)
{ {
$item[$key] = (int) $value; $item[$key] = (float) $value;
return $item; return $item;
} }
+2 -4
View File
@@ -1,9 +1,7 @@
<?php <?php
namespace Wearepixel\Cart; namespace Pixeldigital\Cart;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
class CartCollection extends Collection class CartCollection extends Collection {}
{
}
+17 -9
View File
@@ -1,10 +1,10 @@
<?php <?php
namespace Wearepixel\Cart; namespace Pixeldigital\Cart;
use Wearepixel\Cart\Helpers\Helpers; use Pixeldigital\Cart\Helpers\Helpers;
use Wearepixel\Cart\Validators\CartConditionValidator; use Pixeldigital\Cart\Validators\CartConditionValidator;
use Wearepixel\Cart\Exceptions\InvalidConditionException; use Pixeldigital\Cart\Exceptions\InvalidConditionException;
class CartCondition class CartCondition
{ {
@@ -16,7 +16,7 @@ class CartCondition
/** /**
* the parsed raw value of the condition * the parsed raw value of the condition
*/ */
public $parsedRawValue; public $parsedRawValue = 0;
/** /**
* @param array $args (name, type, target, value) * @param array $args (name, type, target, value)
@@ -77,14 +77,20 @@ public function getAttributes()
/** /**
* the value of this the condition * the value of this the condition
*
* @return mixed
*/ */
public function getValue() public function getValue(): int|float|string
{ {
return $this->args['value']; return $this->args['value'];
} }
/**
* Set the value of this condition
*/
public function setValue($value): void
{
$this->args['value'] = $value;
}
/** /**
* Set the order to apply this condition. If no argument order is applied we return 0 as * Set the order to apply this condition. If no argument order is applied we return 0 as
* indicator that no assignment has been made * indicator that no assignment has been made
@@ -123,9 +129,11 @@ public function applyCondition($totalOrSubTotalOrPrice)
* *
* @return mixed * @return mixed
*/ */
public function getCalculatedValue($totalOrSubTotalOrPrice) public function getCalculatedValue($totalOrSubTotalOrPrice = null): int|float
{ {
if ($totalOrSubTotalOrPrice) {
$this->apply($totalOrSubTotalOrPrice, $this->getValue()); $this->apply($totalOrSubTotalOrPrice, $this->getValue());
}
return $this->parsedRawValue; return $this->parsedRawValue;
} }
+1 -1
View File
@@ -1,6 +1,6 @@
<?php <?php
namespace Wearepixel\Cart; namespace Pixeldigital\Cart;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
+1 -1
View File
@@ -1,6 +1,6 @@
<?php <?php
namespace Wearepixel\Cart; namespace Pixeldigital\Cart;
use Illuminate\Support\ServiceProvider; use Illuminate\Support\ServiceProvider;
+1 -1
View File
@@ -1,5 +1,5 @@
<?php <?php
namespace Wearepixel\Cart\Exceptions; namespace Pixeldigital\Cart\Exceptions;
class InvalidConditionException extends \Exception {} class InvalidConditionException extends \Exception {}
+1 -1
View File
@@ -1,5 +1,5 @@
<?php <?php
namespace Wearepixel\Cart\Exceptions; namespace Pixeldigital\Cart\Exceptions;
class InvalidItemException extends \Exception {} class InvalidItemException extends \Exception {}
+2 -4
View File
@@ -1,7 +1,5 @@
<?php <?php
namespace Wearepixel\Cart\Exceptions; namespace Pixeldigital\Cart\Exceptions;
class UnknownModelException extends \Exception class UnknownModelException extends \Exception {}
{
}
+1 -1
View File
@@ -1,6 +1,6 @@
<?php <?php
namespace Wearepixel\Cart\Facades; namespace Pixeldigital\Cart\Facades;
use Illuminate\Support\Facades\Facade; use Illuminate\Support\Facades\Facade;
+26 -16
View File
@@ -1,29 +1,34 @@
<?php <?php
namespace Wearepixel\Cart\Helpers; namespace Pixeldigital\Cart\Helpers;
class Helpers class Helpers
{ {
/** /**
* normalize price * Normalize prices
*
* @return float
*/ */
public static function normalizePrice($price) public static function normalizePrice($price): ?float
{ {
return (is_string($price)) ? floatval($price) : $price; return (is_string($price)) ? floatval($price) : $price;
} }
/** /**
* check if array is multi dimensional array * Get the rounding mode
* This will only check the first element of the array if it is still an array
* to decide that it is a multi dimensional, if you want to check the array strictly
* with all on its element, flag the second argument as true
*
* @param bool $recursive
* @return bool
*/ */
public static function isMultiArray($array, $recursive = false) public static function roundMode($config): int
{
if (isset($config['round_mode']) && $config['round_mode'] == 'up') {
return PHP_ROUND_HALF_UP;
}
return PHP_ROUND_HALF_DOWN;
}
/**
* Check if array is multi dimensional array
* This will only check if the first element of the array is an array
*/
public static function isMultiArray(array $array, bool $recursive = false): bool
{ {
if ($recursive) { if ($recursive) {
return (count($array) == count($array, COUNT_RECURSIVE)) ? false : true; return (count($array) == count($array, COUNT_RECURSIVE)) ? false : true;
@@ -35,8 +40,9 @@ public static function isMultiArray($array, $recursive = false)
return false; return false;
} }
} }
} }
return false;
} }
/** /**
@@ -56,10 +62,14 @@ public static function issetAndHasValueOrAssignDefault(&$var, $default = false)
public static function formatValue($value, $formatNumber, $config) public static function formatValue($value, $formatNumber, $config)
{ {
if (! $value) {
return 0;
}
if ($formatNumber || $config['format_numbers']) { if ($formatNumber || $config['format_numbers']) {
return floatval(number_format($value, $config['decimals'], $config['dec_point'], $config['thousands_sep'])); return round($value, $config['decimals'], self::roundMode($config));
} else { } else {
return $value; return floatval($value);
} }
} }
} }
+1 -1
View File
@@ -1,6 +1,6 @@
<?php <?php
namespace Wearepixel\Cart; namespace Pixeldigital\Cart;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
+3 -3
View File
@@ -1,9 +1,9 @@
<?php <?php
namespace Wearepixel\Cart; namespace Pixeldigital\Cart;
use Illuminate\Support\Collection; use Illuminate\Support\Collection;
use Wearepixel\Cart\Helpers\Helpers; use Pixeldigital\Cart\Helpers\Helpers;
class ItemCollection extends Collection class ItemCollection extends Collection
{ {
@@ -72,7 +72,7 @@ public function hasConditions()
if (is_array($this['conditions'])) { if (is_array($this['conditions'])) {
return count($this['conditions']) > 0; return count($this['conditions']) > 0;
} }
$conditionInstance = 'Wearepixel\\Cart\\CartCondition'; $conditionInstance = 'Pixeldigital\\Cart\\CartCondition';
if ($this['conditions'] instanceof $conditionInstance) { if ($this['conditions'] instanceof $conditionInstance) {
return true; return true;
} }
+1 -1
View File
@@ -1,5 +1,5 @@
<?php <?php
namespace Wearepixel\Cart\Validators; namespace Pixeldigital\Cart\Validators;
class CartConditionValidator extends Validator {} class CartConditionValidator extends Validator {}
+1 -1
View File
@@ -1,5 +1,5 @@
<?php <?php
namespace Wearepixel\Cart\Validators; namespace Pixeldigital\Cart\Validators;
class CartItemValidator extends Validator {} class CartItemValidator extends Validator {}
+1 -1
View File
@@ -1,6 +1,6 @@
<?php <?php
namespace Wearepixel\Cart\Validators; namespace Pixeldigital\Cart\Validators;
use Illuminate\Validation\Factory; use Illuminate\Validation\Factory;
use Illuminate\Filesystem\Filesystem; use Illuminate\Filesystem\Filesystem;
+9
View File
@@ -0,0 +1,9 @@
<?php
return [
'format_numbers' => true,
'decimals' => 2,
'dec_point' => '.',
'thousands_sep' => ',',
'use_cents' => false,
];
+2 -3
View File
@@ -1,8 +1,7 @@
<?php <?php
return [ return [
'format_numbers' => false, 'format_numbers' => true,
'decimals' => 2, 'decimals' => 2,
'dec_point' => '.', 'round_mode' => 'up',
'thousands_sep' => ',',
]; ];
+1 -1
View File
@@ -1,6 +1,6 @@
<?php <?php
namespace Wearepixel\Cart\Tests\Helpers; namespace Pixeldigital\Cart\Tests\Helpers;
use Illuminate\Contracts\Database\ModelIdentifier; use Illuminate\Contracts\Database\ModelIdentifier;
+1 -1
View File
@@ -1,6 +1,6 @@
<?php <?php
namespace Wearepixel\Cart\Tests\Helpers; namespace Pixeldigital\Cart\Tests\Helpers;
class SessionMock class SessionMock
{ {
-40
View File
@@ -27,43 +27,3 @@
expect()->extend('toBeOne', function () { expect()->extend('toBeOne', function () {
return $this->toBe(1); return $this->toBe(1);
}); });
/*
|--------------------------------------------------------------------------
| Functions
|--------------------------------------------------------------------------
|
| While Pest is very powerful out-of-the-box, you may have some testing code specific to your
| project that you don't want to repeat in every file. Here you can also expose helpers as
| global functions to help you to reduce the number of lines of code in your test files.
|
*/
function fillCart()
{
$items = [
[
'id' => 456,
'name' => 'Sample Item 1',
'price' => 67.99,
'quantity' => 1,
'attributes' => [],
],
[
'id' => 568,
'name' => 'Sample Item 2',
'price' => 69.25,
'quantity' => 1,
'attributes' => [],
],
[
'id' => 856,
'name' => 'Sample Item 3',
'price' => 50.25,
'quantity' => 1,
'attributes' => [],
],
];
$this->cart->add($items);
}
File diff suppressed because it is too large Load Diff
+226 -66
View File
@@ -1,8 +1,8 @@
<?php <?php
use Wearepixel\Cart\Cart; use Pixeldigital\Cart\Cart;
use Wearepixel\Cart\Tests\Helpers\MockProduct; use Pixeldigital\Cart\Tests\Helpers\MockProduct;
use Wearepixel\Cart\Tests\Helpers\SessionMock; use Pixeldigital\Cart\Tests\Helpers\SessionMock;
beforeEach(function () { beforeEach(function () {
$events = Mockery::mock('Illuminate\Contracts\Events\Dispatcher'); $events = Mockery::mock('Illuminate\Contracts\Events\Dispatcher');
@@ -21,16 +21,26 @@
Mockery::close(); Mockery::close();
}); });
test('cart can add item', function () { describe('cart', function () {
$this->cart->add(455, 'Sample Item', 100.99, 2, []); test('can add an item', function () {
$this->cart->add(1, 'Sample Item', 100.99, 2, []);
expect($this->cart->isEmpty())->toBeFalse('Cart should not be empty'); expect($this->cart->isEmpty())->toBeFalse('Cart should not be empty');
expect($this->cart->getContent()->count())->toEqual(1, 'Cart content should be 1'); expect($this->cart->getContent()->count())->toEqual(1, 'Cart content should be 1');
expect($this->cart->getContent()->first()['id'])->toEqual(455, 'Item added has ID of 455 so first content ID should be 455'); expect($this->cart->getContent()->first()['id'])->toEqual(1, 'Item added has ID of 1 so first content ID should be 1');
expect($this->cart->getContent()->first()['price'])->toEqual(100.99, 'Item added has price of 100.99 so first content price should be 100.99'); expect($this->cart->getContent()->first()['price'])->toEqual(100.99, 'Item added has price of 100.99 so first content price should be 100.99');
}); });
test('cart can add item with no price', function () { test('can add an item in cents', function () {
$this->cart->add(1, 'Sample Item', 10099, 2, []);
expect($this->cart->isEmpty())->toBeFalse('Cart should not be empty');
expect($this->cart->getContent()->count())->toEqual(1, 'Cart content should be 1');
expect($this->cart->getContent()->first()['id'])->toEqual(1, 'Item added has ID of 1 so first content ID should be 1');
expect($this->cart->getContent()->first()['price'])->toEqual(10099, 'Item added has price of 100.99 so first content price should be 100.99');
});
test('can add an item with no price', function () {
$this->cart->add(455, 'Sample Item', 0, 2, []); $this->cart->add(455, 'Sample Item', 0, 2, []);
expect($this->cart->isEmpty())->toBeFalse('Cart should not be empty'); expect($this->cart->isEmpty())->toBeFalse('Cart should not be empty');
@@ -39,7 +49,35 @@
expect($this->cart->getTotal())->toEqual(0, 'Total should be 0'); expect($this->cart->getTotal())->toEqual(0, 'Total should be 0');
}); });
test('cart can add items as array', function () { test('can add an item an array with no price', function () {
$this->cart->add([
'id' => 455,
'name' => 'Sample Item',
'quantity' => 2,
]);
expect($this->cart->isEmpty())->toBeFalse('Cart should not be empty');
expect($this->cart->getContent()->count())->toEqual(1, 'Cart content should be 1');
expect($this->cart->getContent()->first()['id'])->toEqual(455, 'Item added has ID of 455 so first content ID should be 455');
expect($this->cart->getTotal())->toEqual(0, 'Total should be 0');
});
test('can add an item without attributes', function () {
$item = [
'id' => 1,
'name' => 'Pocket Shorts',
'price' => 67.99,
'quantity' => 2,
];
$this->cart->add($item);
expect($this->cart->isEmpty())->toBeFalse('Cart should not be empty');
expect($this->cart->getContent()->count())->toEqual(1, 'Cart content should be 1');
expect($this->cart->getTotal())->toEqual(135.98, 'Cart total should be 135.98');
});
test('can add items as array', function () {
$item = [ $item = [
'id' => 456, 'id' => 456,
'name' => 'Sample Item', 'name' => 'Sample Item',
@@ -56,27 +94,27 @@
expect($this->cart->getContent()->first()['name'])->toEqual('Sample Item', 'The first content must have name of "Sample Item"'); expect($this->cart->getContent()->first()['name'])->toEqual('Sample Item', 'The first content must have name of "Sample Item"');
}); });
test('cart can add items with multidimensional array', function () { test('can add multiple items with an array', function () {
$items = [ $items = [
[ [
'id' => 456, 'id' => 1,
'name' => 'Sample Item 1', 'name' => 'Half Button Open Collar',
'price' => 67.99, 'price' => 71.99,
'quantity' => 4, 'quantity' => 1,
'attributes' => [], 'attributes' => [],
], ],
[ [
'id' => 568, 'id' => 2,
'name' => 'Sample Item 2', 'name' => 'Oli Crew Neck',
'price' => 69.25, 'price' => 59.99,
'quantity' => 4, 'quantity' => 1,
'attributes' => [], 'attributes' => [],
], ],
[ [
'id' => 856, 'id' => 3,
'name' => 'Sample Item 3', 'name' => 'Denim Shorts',
'price' => 50.25, 'price' => 69.99,
'quantity' => 4, 'quantity' => 3,
'attributes' => [], 'attributes' => [],
], ],
]; ];
@@ -85,25 +123,20 @@
expect($this->cart->isEmpty())->toBeFalse('Cart should not be empty'); expect($this->cart->isEmpty())->toBeFalse('Cart should not be empty');
expect($this->cart->getContent()->toArray())->toHaveCount(3, 'Cart should have 3 items'); expect($this->cart->getContent()->toArray())->toHaveCount(3, 'Cart should have 3 items');
expect($this->cart->getTotal())->toEqual(341.95, 'Cart should have a total of 341.95');
}); });
test('cart can add item without attributes', function () { test('cart item prices should be normalized when added to cart', function () {
$item = [ // add a price in a string format should be converted to float
'id' => 456, $this->cart->add(1, 'Book of Languages Item', '100.99', 2, []);
'name' => 'Sample Item 1',
'price' => 67.99,
'quantity' => 4,
];
$this->cart->add($item); expect($this->cart->getContent()->first()['price'])->toBeFloat('Cart price should be a float');
expect($this->cart->isEmpty())->toBeFalse('Cart should not be empty');
}); });
test('cart update with attribute then attributes should be still instance of item attribute collection', function () { test('can update a cart item with new attributes and it should be still instance of item attribute collection', function () {
$item = [ $item = [
'id' => 456, 'id' => 1,
'name' => 'Sample Item 1', 'name' => 'Leather Shows',
'price' => 67.99, 'price' => 67.99,
'quantity' => 4, 'quantity' => 4,
'attributes' => [ 'attributes' => [
@@ -111,13 +144,12 @@
'color' => 'red', 'color' => 'red',
], ],
]; ];
$this->cart->add($item); $this->cart->add($item);
// lets get the attribute and prove first its an instance of $item = $this->cart->get(1);
// ItemAttributeCollection
$item = $this->cart->get(456);
expect($item->attributes)->toBeInstanceOf('Wearepixel\Cart\ItemAttributeCollection'); expect($item->attributes)->toBeInstanceOf('Pixeldigital\\Cart\\ItemAttributeCollection');
// now lets update the item with its new attributes // now lets update the item with its new attributes
// when we get that item from cart, it should still be an instance of ItemAttributeCollection // when we get that item from cart, it should still be an instance of ItemAttributeCollection
@@ -127,9 +159,161 @@
'color' => 'red', 'color' => 'red',
], ],
]; ];
$this->cart->update(456, $updatedItem);
expect($item->attributes)->toBeInstanceOf('Wearepixel\Cart\ItemAttributeCollection'); $this->cart->update(1, $updatedItem);
expect($item->attributes)->toBeInstanceOf('Pixeldigital\\Cart\\ItemAttributeCollection');
});
test('item orders are preserved by the order they are added', function () {
$items = [
[
'id' => 50,
'name' => 'Leather Shows',
'price' => 67.99,
'quantity' => 4,
'attributes' => [
'product_id' => '145',
'color' => 'red',
],
],
[
'id' => 2,
'name' => 'Oli Crew Neck',
'price' => 59.99,
'quantity' => 1,
'attributes' => [],
],
];
$this->cart->add($items);
$items = $this->cart->getContent();
expect($items->toArray())->toHaveCount(2, 'Cart should have 2 items');
expect($items->first()->id)->toEqual(50, 'First item should have ID of 1');
expect($items->last()->id)->toEqual(2, 'Last item should have ID of 2');
});
test('item orders are preserved by the order they are added even when items are updated', function () {
$items = [
[
'id' => 50,
'name' => 'Leather Shows',
'price' => 67.99,
'quantity' => 4,
'attributes' => [
'product_id' => '145',
'color' => 'red',
],
],
[
'id' => 2,
'name' => 'Oli Crew Neck',
'price' => 59.99,
'quantity' => 1,
'attributes' => [],
],
];
$this->cart->add($items);
$this->cart->update(50, ['name' => 'Updated Name']);
$items = $this->cart->getContent();
expect($items->toArray())->toHaveCount(2, 'Cart should have 2 items');
expect($items->first()->id)->toEqual(50, 'First item should have ID of 1');
expect($items->last()->id)->toEqual(2, 'Last item should have ID of 2');
});
test('can update existing items', function () {
$items = [
[
'id' => 1,
'name' => 'Magic The Gathering Card Pack',
'price' => 12.99,
'quantity' => 3,
'attributes' => [],
],
[
'id' => 2,
'name' => 'Magic The Gathering Card Case',
'price' => 39.99,
'quantity' => 1,
'attributes' => [],
],
];
$this->cart->add($items);
$item = $this->cart->get(1);
expect($item['name'])->toEqual('Magic The Gathering Card Pack', 'Item name should be "Magic The Gathering Card Pack"');
expect($item['price'])->toEqual(12.99, 'Item price should be "12.99"');
expect($item['quantity'])->toEqual(3, 'Item quantity should be 3');
// when cart's item quantity is updated, the subtotal should be updated as well
$this->cart->update(1, [
'name' => 'Magic The Gathering Card Packs',
'quantity' => 2,
'price' => 10.20,
]);
$item = $this->cart->get(1);
expect($item['name'])->toEqual('Magic The Gathering Card Packs', 'Item name should be "Magic The Gathering Card Packs"');
expect($item['price'])->toEqual(10.20, 'Item price should be 10.20');
expect($item['quantity'])->toEqual(5, 'Item quantity should be 2');
});
test('can update existing item quanties with decimals', function () {
$items = [
'id' => 1,
'name' => 'Fertilizer',
'price' => 30,
'quantity' => 7.8,
'attributes' => [
'unit' => 'kilogram',
],
];
$this->cart->add($items);
$item = $this->cart->get(1);
expect($item['quantity'])->toEqual(7.8, 'Item quantity should be 7.8');
// when cart's item quantity is updated, the subtotal should be updated as well
$this->cart->update(1, [
'quantity' => [
'relative' => true,
'value' => 2.1,
],
]);
$item = $this->cart->get(1);
expect($item['quantity'])->toEqual(9.9, 'Item quantity should be 9.9');
});
test('should throw an exception when no quantity is provided', function () {
$this->expectException('Pixeldigital\Cart\Exceptions\InvalidItemException');
$this->expectExceptionMessage('The quantity must be at least 0.1.');
$this->cart->add(455, 'Sample Item', 100.99, 0, []);
});
test('should throw an exception when no id is provided', function () {
$this->expectException('Pixeldigital\Cart\Exceptions\InvalidItemException');
$this->expectExceptionMessage('The id field is required.');
$this->cart->add('', 'Sample Item', 100.99, 2, []);
});
test('should throw an exception when no name is provided', function () {
$this->expectException('Pixeldigital\Cart\Exceptions\InvalidItemException');
$this->expectExceptionMessage('The name field is required.');
$this->cart->add(523, '', 100.99, 2, []);
});
}); });
test('cart items attributes', function () { test('cart items attributes', function () {
@@ -222,13 +406,6 @@
expect($item['quantity'])->toEqual(5, 'Item quantity should be 5'); expect($item['quantity'])->toEqual(5, 'Item quantity should be 5');
}); });
test('item price should be normalized when added to cart', function () {
// add a price in a string format should be converted to float
$this->cart->add(455, 'Sample Item', '100.99', 2, []);
expect($this->cart->getContent()->first()['price'])->toBeFloat('Cart price should be a float');
});
test('it removes an item on cart by item id', function () { test('it removes an item on cart by item id', function () {
$items = [ $items = [
[ [
@@ -331,8 +508,6 @@
}); });
test('sub total when item quantity is updated by reduced', function () { test('sub total when item quantity is updated by reduced', function () {
// $this->cart->setConfig(['format_numbers' => true, 'decimals' => 2, 'dec_point' => '.', 'thousands_sep' => ',']);
$items = [ $items = [
[ [
'id' => 456, 'id' => 456,
@@ -398,21 +573,6 @@
expect($item['quantity'])->toEqual(3, 'Item quantity of with item ID of 456 should now be reduced to 2'); expect($item['quantity'])->toEqual(3, 'Item quantity of with item ID of 456 should now be reduced to 2');
}); });
test('should throw exception when provided invalid values scenario one', function () {
$this->expectException('Wearepixel\Cart\Exceptions\InvalidItemException');
$this->cart->add(455, 'Sample Item', 100.99, 0, []);
});
test('should throw exception when provided invalid values scenario two', function () {
$this->expectException('Wearepixel\Cart\Exceptions\InvalidItemException');
$this->cart->add('', 'Sample Item', 100.99, 2, []);
});
test('should throw exception when provided invalid values scenario three', function () {
$this->expectException('Wearepixel\Cart\Exceptions\InvalidItemException');
$this->cart->add(523, '', 100.99, 2, []);
});
test('clearing cart', function () { test('clearing cart', function () {
$items = [ $items = [
[ [
@@ -486,7 +646,7 @@
expect($this->cart->getContent()->count())->toEqual(1, 'Cart should have 1 item on it'); expect($this->cart->getContent()->count())->toEqual(1, 'Cart should have 1 item on it');
expect($this->cart->getContent()->first()['id'])->toEqual(456, 'The first content must have ID of 456'); expect($this->cart->getContent()->first()['id'])->toEqual(456, 'The first content must have ID of 456');
expect($this->cart->getContent()->first()['name'])->toEqual('Sample Item', 'The first content must have name of "Sample Item"'); expect($this->cart->getContent()->first()['name'])->toEqual('Sample Item', 'The first content must have name of "Sample Item"');
expect($addedItem->model)->toBeInstanceOf('Wearepixel\Cart\Tests\Helpers\MockProduct'); expect($addedItem->model)->toBeInstanceOf('Pixeldigital\Cart\Tests\Helpers\MockProduct');
}); });
test('cart can add items with multidimensional array with associated model', function () { test('cart can add items with multidimensional array with associated model', function () {
@@ -521,7 +681,7 @@
$content = $this->cart->getContent(); $content = $this->cart->getContent();
foreach ($content as $item) { foreach ($content as $item) {
expect($item->model)->toBeInstanceOf('Wearepixel\Cart\Tests\Helpers\MockProduct'); expect($item->model)->toBeInstanceOf('Pixeldigital\Cart\Tests\Helpers\MockProduct');
} }
expect($this->cart->isEmpty())->toBeFalse('Cart should not be empty'); expect($this->cart->isEmpty())->toBeFalse('Cart should not be empty');
+2 -2
View File
@@ -1,7 +1,7 @@
<?php <?php
use Wearepixel\Cart\Cart; use Pixeldigital\Cart\Cart;
use Wearepixel\Cart\Tests\Helpers\SessionMock; use Pixeldigital\Cart\Tests\Helpers\SessionMock;
beforeEach(function () {}); beforeEach(function () {});
+2 -2
View File
@@ -1,7 +1,7 @@
<?php <?php
use Wearepixel\Cart\Cart; use Pixeldigital\Cart\Cart;
use Wearepixel\Cart\Tests\Helpers\SessionMock; use Pixeldigital\Cart\Tests\Helpers\SessionMock;
beforeEach(function () { beforeEach(function () {
$events = Mockery::mock('Illuminate\Contracts\Events\Dispatcher'); $events = Mockery::mock('Illuminate\Contracts\Events\Dispatcher');
+6 -6
View File
@@ -1,9 +1,9 @@
<?php <?php
use Wearepixel\Cart\Cart; use Pixeldigital\Cart\Cart;
use Wearepixel\Cart\CartCondition; use Pixeldigital\Cart\CartCondition;
use Wearepixel\Cart\Tests\Helpers\MockProduct; use Pixeldigital\Cart\Tests\Helpers\MockProduct;
use Wearepixel\Cart\Tests\Helpers\SessionMock; use Pixeldigital\Cart\Tests\Helpers\SessionMock;
beforeEach(function () { beforeEach(function () {
$events = Mockery::mock('Illuminate\Contracts\Events\Dispatcher'); $events = Mockery::mock('Illuminate\Contracts\Events\Dispatcher');
@@ -47,7 +47,7 @@
}); });
test('item get conditions with conditions', function () { test('item get conditions with conditions', function () {
$itemCondition1 = new \Wearepixel\Cart\CartCondition([ $itemCondition1 = new \Pixeldigital\Cart\CartCondition([
'name' => 'SALE 5%', 'name' => 'SALE 5%',
'type' => 'sale', 'type' => 'sale',
'target' => 'item', 'target' => 'item',
@@ -77,7 +77,7 @@
}); });
test('it will throw an exception when a non existing model is being associated', function () { test('it will throw an exception when a non existing model is being associated', function () {
$this->expectException(\Wearepixel\Cart\Exceptions\UnknownModelException::class); $this->expectException(\Pixeldigital\Cart\Exceptions\UnknownModelException::class);
$this->expectExceptionMessage('The supplied model SomeModel does not exist.'); $this->expectExceptionMessage('The supplied model SomeModel does not exist.');
$this->cart->add(1, 'Test item', 1, 10.00)->associate('SomeModel'); $this->cart->add(1, 'Test item', 1, 10.00)->associate('SomeModel');
+2 -2
View File
@@ -1,7 +1,7 @@
<?php <?php
use Wearepixel\Cart\Cart; use Pixeldigital\Cart\Cart;
use Wearepixel\Cart\Tests\Helpers\SessionMock; use Pixeldigital\Cart\Tests\Helpers\SessionMock;
beforeEach(function () { beforeEach(function () {
$events = Mockery::mock('Illuminate\Contracts\Events\Dispatcher'); $events = Mockery::mock('Illuminate\Contracts\Events\Dispatcher');