1<?php 2/** 3 * Copyright since 2007 PrestaShop SA and Contributors 4 * PrestaShop is an International Registered Trademark & Property of PrestaShop SA 5 * 6 * NOTICE OF LICENSE 7 * 8 * This source file is subject to the Open Software License (OSL 3.0) 9 * that is bundled with this package in the file LICENSE.md. 10 * It is also available through the world-wide-web at this URL: 11 * https://opensource.org/licenses/OSL-3.0 12 * If you did not receive a copy of the license and are unable to 13 * obtain it through the world-wide-web, please send an email 14 * to license@prestashop.com so we can send you a copy immediately. 15 * 16 * DISCLAIMER 17 * 18 * Do not edit or add to this file if you wish to upgrade PrestaShop to newer 19 * versions in the future. If you wish to customize PrestaShop for your 20 * needs please refer to https://devdocs.prestashop.com/ for more information. 21 * 22 * @author PrestaShop SA and Contributors <contact@prestashop.com> 23 * @copyright Since 2007 PrestaShop SA and Contributors 24 * @license https://opensource.org/licenses/OSL-3.0 Open Software License (OSL 3.0) 25 */ 26 27namespace PrestaShop\PrestaShop\Adapter\Cart\CommandHandler; 28 29use Cart; 30use CartRule; 31use PrestaShop\PrestaShop\Adapter\Cart\AbstractCartHandler; 32use PrestaShop\PrestaShop\Core\ConfigurationInterface; 33use PrestaShop\PrestaShop\Core\Domain\Cart\Command\UpdateCartDeliverySettingsCommand; 34use PrestaShop\PrestaShop\Core\Domain\Cart\CommandHandler\UpdateCartDeliverySettingsHandlerInterface; 35use PrestaShop\PrestaShop\Core\Domain\Cart\Exception\CartException; 36use PrestaShop\PrestaShop\Core\Domain\Cart\Exception\InvalidGiftMessageException; 37use PrestaShop\PrestaShop\Core\Domain\CartRule\Exception\CannotDeleteCartRuleException; 38use PrestaShop\PrestaShop\Core\Domain\CartRule\Exception\CartRuleException; 39use PrestaShopException; 40use Symfony\Component\Translation\TranslatorInterface; 41use Validate; 42 43/** 44 * @internal 45 */ 46final class UpdateCartDeliverySettingsHandler extends AbstractCartHandler implements UpdateCartDeliverySettingsHandlerInterface 47{ 48 /** 49 * @var TranslatorInterface 50 */ 51 private $translator; 52 53 /** 54 * @var ConfigurationInterface 55 */ 56 private $configuration; 57 58 /** 59 * @param TranslatorInterface $translator 60 * @param ConfigurationInterface $configuration 61 */ 62 public function __construct(TranslatorInterface $translator, ConfigurationInterface $configuration) 63 { 64 $this->translator = $translator; 65 $this->configuration = $configuration; 66 } 67 68 /** 69 * {@inheritdoc} 70 */ 71 public function handle(UpdateCartDeliverySettingsCommand $command): void 72 { 73 $cart = $this->getCart($command->getCartId()); 74 75 if (($command->getGiftMessage() !== null) && (!Validate::isMessage($command->getGiftMessage()))) { 76 throw new InvalidGiftMessageException(); 77 } 78 79 $this->handleFreeShippingOption($cart, $command); 80 $shouldSaveCartAfterGiftOption = $this->handleGiftOption($cart, $command); 81 $shouldSaveCartAfterWrappingOption = $this->handleRecycledWrappingOption($cart, $command); 82 $shouldSaveCartAfterGiftMessageOption = $this->handleGiftMessageOption($cart, $command); 83 84 $shouldSaveCart = ($shouldSaveCartAfterGiftOption 85 || $shouldSaveCartAfterWrappingOption 86 || $shouldSaveCartAfterGiftMessageOption); 87 88 if ($shouldSaveCart) { 89 try { 90 if (false === $cart->update()) { 91 throw new CartException('Failed to update cart delivery settings'); 92 } 93 } catch (PrestaShopException $e) { 94 throw new CartException(sprintf('An error occurred while trying to update delivery settings for cart with id "%d"', $cart->id)); 95 } 96 } 97 } 98 99 /** 100 * Sometimes, the cart rule to enable 'free shipping' exists 101 * but is not linked to the cart. We look for this cart rule 102 * to avoid creating duplicates. 103 * 104 * @param string $code 105 * 106 * @return CartRule|null 107 * 108 * @throws PrestaShopException 109 */ 110 private function getCartRuleForBackOfficeFreeShipping($code): ?CartRule 111 { 112 $cartRuleId = CartRule::getIdByCode($code); 113 114 if (!$cartRuleId) { 115 return null; 116 } 117 118 return new CartRule((int) $cartRuleId); 119 } 120 121 /** 122 * @param Cart $cart 123 * @param string $backOfficeOrderCode 124 * 125 * @return CartRule 126 */ 127 private function createCartRule(Cart $cart, string $backOfficeOrderCode): CartRule 128 { 129 $freeShippingCartRule = new CartRule(); 130 $freeShippingCartRule->code = $backOfficeOrderCode; 131 $freeShippingCartRule->name = [ 132 $this->configuration->get('PS_LANG_DEFAULT') => $this->translator->trans( 133 'Free Shipping', 134 [], 135 'Admin.Orderscustomers.Feature' 136 ), 137 ]; 138 $freeShippingCartRule->id_customer = (int) $cart->id_customer; 139 $freeShippingCartRule->free_shipping = true; 140 $freeShippingCartRule->quantity = 1; 141 $freeShippingCartRule->quantity_per_user = 1; 142 $freeShippingCartRule->minimum_amount_currency = (int) $cart->id_currency; 143 $freeShippingCartRule->reduction_currency = (int) $cart->id_currency; 144 $freeShippingCartRule->date_from = date('Y-m-d H:i:s'); 145 $freeShippingCartRule->date_to = date('Y-m-d H:i:s', time() + 24 * 36000); 146 $freeShippingCartRule->active = true; 147 $freeShippingCartRule->add(); 148 149 return $freeShippingCartRule; 150 } 151 152 /** 153 * This method works as follows: 154 * 1. if free shipping should be enabled, enable it 155 * 2. if free shipping should not be enabled and cart already does not have free shipping, do nothing 156 * 3.if free shipping should not be enabled and cart has free shipping, disable it 157 * 158 * @param Cart $cart 159 * @param UpdateCartDeliverySettingsCommand $command 160 * 161 * @throws CannotDeleteCartRuleException 162 */ 163 protected function handleFreeShippingOption(Cart $cart, UpdateCartDeliverySettingsCommand $command): void 164 { 165 $backOfficeOrderCode = sprintf('%s%s', CartRule::BO_ORDER_CODE_PREFIX, $cart->id); 166 167 $freeShippingCartRule = $this->getCartRuleForBackOfficeFreeShipping($backOfficeOrderCode); 168 169 $freeShippingShouldBeEnabled = $command->allowFreeShipping(); 170 171 // Step 1 172 if ($freeShippingShouldBeEnabled) { 173 if (null === $freeShippingCartRule) { 174 // there is not yet a 'free shipping' cart rule available in the system so we create it 175 $freeShippingCartRule = $this->createCartRule($cart, $backOfficeOrderCode); 176 } 177 $cart->addCartRule((int) $freeShippingCartRule->id); 178 179 return; 180 } 181 182 if (null === $freeShippingCartRule) { 183 return; 184 } 185 186 $cart->removeCartRule((int) $freeShippingCartRule->id); 187 188 try { 189 if (false === $freeShippingCartRule->delete()) { 190 throw new CannotDeleteCartRuleException(sprintf('Failed deleting cart rule #%s', $freeShippingCartRule->id)); 191 } 192 } catch (PrestaShopException $e) { 193 throw new CartRuleException(sprintf('An error occurred when trying to delete cart rule #%s', $freeShippingCartRule->id)); 194 } 195 } 196 197 /** 198 * @param Cart $cart 199 * @param UpdateCartDeliverySettingsCommand $command 200 * 201 * @return bool should save the cart or not 202 * 203 * @throws CartException 204 * @throws PrestaShopException 205 */ 206 private function handleGiftOption(Cart $cart, UpdateCartDeliverySettingsCommand $command): bool 207 { 208 if ($command->isAGift() === null) { 209 return false; 210 } 211 212 $cart->gift = $command->isAGift(); 213 214 return true; 215 } 216 217 /** 218 * @param Cart $cart 219 * @param UpdateCartDeliverySettingsCommand $command 220 * 221 * @return bool should save the cart or not 222 */ 223 private function handleRecycledWrappingOption(Cart $cart, UpdateCartDeliverySettingsCommand $command): bool 224 { 225 if ($command->useRecycledPackaging() === null) { 226 return false; 227 } 228 229 $cart->recyclable = $command->useRecycledPackaging(); 230 231 return true; 232 } 233 234 /** 235 * @param Cart $cart 236 * @param UpdateCartDeliverySettingsCommand $command 237 * 238 * @return bool should save the cart or not 239 */ 240 private function handleGiftMessageOption(Cart $cart, UpdateCartDeliverySettingsCommand $command): bool 241 { 242 if ($command->getGiftMessage() === null) { 243 return false; 244 } 245 246 $cart->gift_message = $command->getGiftMessage(); 247 248 return true; 249 } 250} 251