diff --git a/src/Foundation/Factories/OrderFactory.php b/src/Foundation/Factories/OrderFactory.php index b5e44f329..5b414f576 100644 --- a/src/Foundation/Factories/OrderFactory.php +++ b/src/Foundation/Factories/OrderFactory.php @@ -21,6 +21,7 @@ use Vanilo\Contracts\CheckoutSubject; use Vanilo\Contracts\Configurable; use Vanilo\Order\Contracts\Order; +use Vanilo\Order\Contracts\OrderItem; use Vanilo\Order\Factories\OrderFactory as BaseOrderFactory; class OrderFactory extends BaseOrderFactory @@ -40,7 +41,7 @@ public function createFromCheckout(Checkout $checkout) $this->sourceAdjustments = $checkout->getCart()->adjustments(); - return $this->createFromDataArray($orderData, $items, \Closure::fromCallable([$this, 'copyAdjustmentsHook'])); + return $this->createFromDataArray($orderData, $items, $this->copyAdjustmentsHook(...), $this->copyItemAdjustmentsHook(...)); } protected function copyAdjustmentsHook(Order $order): void @@ -57,6 +58,18 @@ protected function copyAdjustmentsHook(Order $order): void } } + protected function copyItemAdjustmentsHook(OrderItem $item, Order $order, array $sourceItems, array $sourceItem): void + { + foreach (($sourceItem['adjustments'] ?? []) as $adjustment) { + $clone = $adjustment->newInstance( + Arr::except($adjustment->getAttributes(), ['id', 'adjustable_type', 'adjustable_id', 'created_at', 'updated_at']) + ); + $clone->data = $adjustment->data; + $item->adjustments()->add($clone); + $clone->lock(); + } + } + protected function convertCartItemsToDataArray(CheckoutSubject $cart) { return $cart->getItems()->map(function ($item) { @@ -64,6 +77,7 @@ protected function convertCartItemsToDataArray(CheckoutSubject $cart) 'product' => $item->getBuyable(), 'quantity' => $item->getQuantity(), 'configuration' => $item->getBuyable() instanceof Configurable ? $item->configuration() : null, + 'adjustments' => $item instanceof Adjustable ? $item->adjustments() : [], ]; })->all(); } diff --git a/src/Order/Changelog.md b/src/Order/Changelog.md index 202f7f110..002caa160 100644 --- a/src/Order/Changelog.md +++ b/src/Order/Changelog.md @@ -13,6 +13,7 @@ - Changed minimal Enum requirement to v4.2 - Upgraded to Konekt Address and User modules to v3 - Added the `currency` field to the orders table +- BC: Added the `$hooks` and `$itemHooks` parameters to the `OrderFactory` interface - BC: Changed the `OrderItem` interface into Configurable - BC: Added 7 methods to the `OrderItem` interface - BC: Added the `getLanguage()`, `getFulfillmentStatus()` and `itemsTotal()` methods to the `Order` interface diff --git a/src/Order/Contracts/OrderFactory.php b/src/Order/Contracts/OrderFactory.php index 2e15dbaba..6f3b82537 100644 --- a/src/Order/Contracts/OrderFactory.php +++ b/src/Order/Contracts/OrderFactory.php @@ -19,11 +19,6 @@ interface OrderFactory { /** * Creates a new order from simple data arrays - * - * @param array $data - * @param array $items - * - * @return Order */ - public function createFromDataArray(array $data, array $items): Order; + public function createFromDataArray(array $data, array $items, array|callable $hooks = null, array|callable $itemHooks = null): Order; } diff --git a/src/Order/Factories/OrderFactory.php b/src/Order/Factories/OrderFactory.php index fd9a77054..c2a882cdf 100644 --- a/src/Order/Factories/OrderFactory.php +++ b/src/Order/Factories/OrderFactory.php @@ -40,10 +40,7 @@ public function __construct(OrderNumberGenerator $generator) $this->orderNumberGenerator = $generator; } - /** - * @inheritDoc - */ - public function createFromDataArray(array $data, array $items, callable ...$hooks): Order + public function createFromDataArray(array $data, array $items, array|callable $hooks = null, array|callable $itemHooks = null): Order { if (empty($items)) { throw new CreateOrderException(__('Can not create an order without items')); @@ -62,17 +59,9 @@ public function createFromDataArray(array $data, array $items, callable ...$hook $this->createBillpayer($order, $data); $this->createShippingAddress($order, $data); - $this->createItems( - $order, - array_map(function ($item) { - // Default quantity is 1 if unspecified - $item['quantity'] = $item['quantity'] ?? 1; - - return $item; - }, $items) - ); + $this->createItems($order, array_map(fn ($item) => $item + ['quantity' => 1], $items), ...Arr::wrap($itemHooks)); - foreach ($hooks as $hook) { + foreach (Arr::wrap($hooks) as $hook) { $this->callHook($hook, $order, $data, $items); } @@ -115,24 +104,10 @@ protected function createBillpayer(Order $order, array $data) protected function createItems(Order $order, array $items, callable ...$hooks) { - $that = $this; - $hasBuyables = collect($items)->contains(function ($item) use ($that) { - return $that->itemContainsABuyable($item); - }); - - if (!$hasBuyables) { // This is faster - $order->items()->createMany($items); - foreach ($order->getItems() as $createdOrderItem) { - foreach ($hooks as $hook) { - $this->callItemHook($hook, $createdOrderItem, $order, $items); - } - } - } else { - foreach ($items as $item) { - $createdOrderItem = $this->createItem($order, $item); - foreach ($hooks as $hook) { - $this->callItemHook($hook, $createdOrderItem, $order, $items); - } + foreach ($items as $item) { + $createdOrderItem = $this->createItem($order, $item); + foreach ($hooks as $hook) { + $this->callItemHook($hook, $createdOrderItem, $order, $items, $item); } } } @@ -177,14 +152,15 @@ protected function callHook(callable $hook, mixed $order, array $data, array $it /** * @throws \ReflectionException */ - protected function callItemHook(callable $hook, OrderItem $orderItem, Order $order, array $sourceItems): void + protected function callItemHook(callable $hook, OrderItem $orderItem, Order $order, array $sourceItems, array $sourceItem): void { $ref = new ReflectionFunction($hook); match ($ref->getNumberOfParameters()) { 0 => $hook(), 1 => $hook($orderItem), 2 => $hook($orderItem, $order), - default => $hook($orderItem, $order, $sourceItems), + 3 => $hook($orderItem, $order, $sourceItems), + default => $hook($orderItem, $order, $sourceItems, $sourceItem), }; }