$catalogItems */ public function attach(Collection $catalogItems, ?int $userId): void { $remaining = $this->purchaseLimits->remainingByCatalogItem($catalogItems, $userId); foreach ($catalogItems as $catalogItem) { $catalogItem->setAttribute( 'remaining_user_quota', $remaining->get($catalogItem->getKey()), ); } } public function maximumAddableQuantity(?int $availableStock, ?int $remainingUserQuota): ?int { if ($availableStock === null) { return $remainingUserQuota; } if ($remainingUserQuota === null) { return $availableStock; } return min($availableStock, $remainingUserQuota); } /** * @return array{ * maximum_quantity: int|null, * restrictions: list, * capabilities: array{select_variant: bool, change_quantity: bool, add_to_cart: bool, buy_now: bool} * } */ public function availability( ?int $availableStock, ?int $remainingUserQuota, string $scope = 'product', ): array { $restrictions = []; if ($remainingUserQuota !== null && $remainingUserQuota <= 0) { $restrictions[] = [ 'code' => 'user_quota_reached', 'message' => self::USER_QUOTA_REACHED_MESSAGE, 'scope' => $scope, ]; } if ($availableStock !== null && $availableStock <= 0) { $restrictions[] = [ 'code' => 'out_of_stock', 'message' => self::OUT_OF_STOCK_MESSAGE, 'scope' => $scope, ]; } $capabilities = [ 'select_variant' => true, 'change_quantity' => true, 'add_to_cart' => true, 'buy_now' => true, ]; foreach ($restrictions as $restriction) { /** @var array $policy */ $policy = config("catalog.availability_policies.{$restriction['code']}", []); foreach ($capabilities as $capability => $allowed) { $capabilities[$capability] = $allowed && ($policy[$capability] ?? true); } } return [ 'maximum_quantity' => $this->maximumAddableQuantity( $availableStock, $remainingUserQuota, ), 'restrictions' => $restrictions, 'capabilities' => $capabilities, ]; } /** @return array */ public function purchaseLimitExceededAvailability(int $maximumQuantity, string $message): array { $availability = $this->availability(null, $maximumQuantity); if ($maximumQuantity > 0) { $availability['restrictions'][] = [ 'code' => 'requested_quantity_exceeds_user_quota', 'message' => $message, 'scope' => 'product', ]; } return $availability; } }