From b92dce9ca447dedaf05143ca74e6e0c3761759d5 Mon Sep 17 00:00:00 2001 From: Joel Male Date: Tue, 25 Feb 2025 11:47:10 +1000 Subject: [PATCH] wip: initial working database support --- composer.json | 3 +- composer.lock | 131 +++++++++++++++++++++++++++++- config/config.php | 3 + src/Cart.php | 71 ++++++---------- src/CartSession.php | 103 +++++++++++++++++++++++ tests/Helpers/SessionMock.php | 5 ++ tests/Unit/CartConditionsTest.php | 4 +- 7 files changed, 267 insertions(+), 53 deletions(-) create mode 100644 src/CartSession.php diff --git a/composer.json b/composer.json index 1188ca6..3816788 100644 --- a/composer.json +++ b/composer.json @@ -27,7 +27,8 @@ "require-dev": { "mockery/mockery": "^1.4.2", "laravel/pint": "^1.21", - "pestphp/pest": "^3.0" + "pestphp/pest": "^3.0", + "larapack/dd": "dev-master" }, "autoload": { "psr-4": { diff --git a/composer.lock b/composer.lock index 34df18a..a2d2864 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "3672e97ffb5cb3bbc7081868046fec07", + "content-hash": "3177332c8f53e0104abe4aa29e537ce4", "packages": [ { "name": "brick/math", @@ -2462,6 +2462,47 @@ }, "time": "2024-11-18T16:19:46+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", "version": "v1.21.0", @@ -5528,6 +5569,90 @@ ], "time": "2025-02-24T14:05:52+00:00" }, + { + "name": "symfony/var-dumper", + "version": "7.3.x-dev", + "source": { + "type": "git", + "url": "https://github.com/symfony/var-dumper.git", + "reference": "9b59e65b4b07c04d4a33f209ec9347352ca7b0e7" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/var-dumper/zipball/9b59e65b4b07c04d4a33f209ec9347352ca7b0e7", + "reference": "9b59e65b4b07c04d4a33f209ec9347352ca7b0e7", + "shasum": "" + }, + "require": { + "php": ">=8.2", + "symfony/deprecation-contracts": "^2.5|^3", + "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.12" + }, + "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.3" + }, + "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": "2025-01-19T13:07:55+00:00" + }, { "name": "ta-tikoma/phpunit-architecture-test", "version": "0.8.4", @@ -5698,7 +5823,9 @@ ], "aliases": [], "minimum-stability": "dev", - "stability-flags": {}, + "stability-flags": { + "larapack/dd": 20 + }, "prefer-stable": false, "prefer-lowest": false, "platform": { diff --git a/config/config.php b/config/config.php index 49ff845..56412ae 100644 --- a/config/config.php +++ b/config/config.php @@ -18,6 +18,9 @@ * --------------------------------------------------------------- */ 'storage' => null, + 'storage_id' => null, + 'storage_items' => null, + 'storage_conditions' => null, /* * --------------------------------------------------------------- diff --git a/src/Cart.php b/src/Cart.php index f0b6f1e..71bd7dd 100644 --- a/src/Cart.php +++ b/src/Cart.php @@ -15,6 +15,7 @@ class Cart protected $instanceName; + protected $customStorage = false; protected $sessionKey; protected $sessionKeyCartItems; protected $sessionKeyCartConditions; @@ -26,41 +27,17 @@ class Cart protected $decimals; protected $decPoint; - public function __construct($session, $events, $instanceName, $session_key, $config) + public function __construct($session, $events, $instanceName, $sessionKey, $config) { $this->events = $events; - $this->session = $session; + $this->session = new CartSession($session, $sessionKey, $config); $this->instanceName = $instanceName; - $this->sessionKey = $session_key; - $this->sessionKeyCartItems = $this->sessionKey . '_cart_items'; - $this->sessionKeyCartConditions = $this->sessionKey . '_cart_conditions'; $this->config = $config; $this->currentItemId = null; $this->fireEvent('created'); } - /** - * sets the session key - * - * @param string $sessionKey the session key or identifier - * @return $this|bool - * - * @throws \Exception - */ - public function session($sessionKey) - { - if (! $sessionKey) { - throw new \Exception('Session key is required.'); - } - - $this->sessionKey = $sessionKey; - $this->sessionKeyCartItems = $this->sessionKey . '_cart_items'; - $this->sessionKeyCartConditions = $this->sessionKey . '_cart_conditions'; - - return $this; - } - /** * get instance name of the cart * @@ -284,10 +261,7 @@ public function clear() return false; } - $this->session->put( - $this->sessionKeyCartItems, - [] - ); + $this->session->putItems([]); $this->fireEvent('cleared'); @@ -326,7 +300,9 @@ public function condition(array|CartCondition $condition): self $conditions->put($condition->getName(), $condition); - $conditions = $conditions->sortBy(function ($condition, $key) { + $conditions = $conditions->reject(function ($condition) { + return empty($condition); + })->sortBy(function ($condition, $key) { return $condition->getOrder(); }); @@ -342,9 +318,14 @@ public function condition(array|CartCondition $condition): self */ public function getConditions(bool $array = false, bool $active = false): CartConditionCollection|array { - $conditions = new CartConditionCollection( - $this->session->get($this->sessionKeyCartConditions) - ); + $conditions = new CartConditionCollection($this->session->getConditions()); + + $conditions = $conditions->reject(function ($condition) { + return empty($condition); + }) + ->transform(function ($condition) { + return $condition instanceof CartCondition ? $condition : new CartCondition($condition); + }); if ($active) { return $conditions->filter(function (CartCondition $condition) { @@ -488,10 +469,7 @@ public function clearItemConditions($itemId) */ public function clearCartConditions(): void { - $this->session->put( - $this->sessionKeyCartConditions, - [] - ); + $this->session->putConditions([]); } /** @@ -653,14 +631,11 @@ public function getTotalQuantity() return $count; } - /** - * get the cart - * - * @return CartCollection - */ - public function getContent() + public function getContent(): CartCollection { - return (new CartCollection($this->session->get($this->sessionKeyCartItems)))->reject(function ($item) { + return (new CartCollection($this->session->getItems()))->transform(function ($item) { + return $item instanceof ItemCollection ? $item : new ItemCollection($item, $this->config); + })->reject(function ($item) { return ! ($item instanceof ItemCollection); }); } @@ -734,11 +709,11 @@ protected function addItem($id, $item) /** * save the cart * - * @param $cart CartCollection + * @param $cart CartCollection */ protected function save($cart) { - $this->session->put($this->sessionKeyCartItems, $cart); + $this->session->putItems($cart); } /** @@ -746,7 +721,7 @@ protected function save($cart) */ protected function saveConditions($conditions) { - $this->session->put($this->sessionKeyCartConditions, $conditions); + $this->session->putConditions($conditions); } /** diff --git a/src/CartSession.php b/src/CartSession.php new file mode 100644 index 0000000..8946ee4 --- /dev/null +++ b/src/CartSession.php @@ -0,0 +1,103 @@ +isInternalSession($session)) { + $this->customStorage = false; + $this->session = $session; + $this->itemsKey = $sessionKey . '_cart_items'; + $this->conditionsKey = $sessionKey . '_cart_conditions'; + } else { + $this->customStorage = true; + + // @TODO validate these 3 exist + $this->sessionId = $config['storage_id']; + $this->itemsKey = $config['storage_items']; + $this->conditionsKey = $config['storage_conditions']; + + // get the base class to do findOrCreate + $this->session = $config['storage']; + $this->session = (new $this->session)->firstOrNew([$this->sessionId => $sessionKey]); + + $this->session[$this->itemsKey] = $this->session[$this->itemsKey] ?? []; + $this->session[$this->conditionsKey] = $this->session[$this->conditionsKey] ?? []; + } + } + + public function isInternalSession($session) + { + return in_array(is_object($session) ? get_class($session) : $session, [ + 'Illuminate\Session\SessionManager', + 'Joelwmale\Cart\Tests\Helpers\SessionMock', + ]); + } + + public function has($key) + { + return $this->session->has($key) ?? $this->session; + } + + public function getItems() + { + return ! $this->customStorage ? $this->session->get($this->itemsKey) : $this->session[$this->itemsKey]; + } + + public function getConditions() + { + return ! $this->customStorage ? $this->session->get($this->conditionsKey) : $this->session[$this->conditionsKey]; + } + + public function putItems($value) + { + if (! $this->customStorage) { + return $this->session->put($this->itemsKey, $value); + } + + $this->session[$this->itemsKey] = $value; + $this->session->save(); + + return $this->session; + } + + public function putConditions($value) + { + if (! $this->customStorage) { + return $this->session->put($this->conditionsKey, $value); + } + + if (! empty($value)) { + $value = $value->mapWithKeys(function ($condition) { + return [$condition->getName() => $condition->toArray()]; + }); + } + + $this->session[$this->conditionsKey] = $value; + $this->session->save(); + + return $this->session; + } + + public function clear() + { + if ($this->customStorage) { + return $this->session->delete(); + } + + $this->session->forget($this->itemsKey); + $this->session->forget($this->conditionsKey); + + return true; + } +} diff --git a/tests/Helpers/SessionMock.php b/tests/Helpers/SessionMock.php index 6ef6d64..5120aa4 100644 --- a/tests/Helpers/SessionMock.php +++ b/tests/Helpers/SessionMock.php @@ -20,4 +20,9 @@ public function put($key, $value) { $this->session[$key] = $value; } + + public function forget($key) + { + unset($this->session[$key]); + } } diff --git a/tests/Unit/CartConditionsTest.php b/tests/Unit/CartConditionsTest.php index b4a17a6..aef51d4 100644 --- a/tests/Unit/CartConditionsTest.php +++ b/tests/Unit/CartConditionsTest.php @@ -10,11 +10,11 @@ $events->shouldReceive('dispatch'); $this->cart = new Cart( - new SessionMock(), + new SessionMock, $events, 'cart', 'SAMPLESESSIONKEY', - require(__DIR__ . '/../Helpers/ConfigConditionsMock.php') + require (__DIR__ . '/../Helpers/ConfigConditionsMock.php') ); });