/src/classes/XLite/Model/OrderModifier/Shipping.php

https://github.com/inhale/core · PHP · 440 lines · 171 code · 67 blank · 202 comment · 27 complexity · b8e24e09704ed7110a698ee68f96ebc8 MD5 · raw file

  1. <?php
  2. // vim: set ts=4 sw=4 sts=4 et:
  3. /**
  4. * LiteCommerce
  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.txt.
  10. * It is also available through the world-wide-web at this URL:
  11. * http://opensource.org/licenses/osl-3.0.php
  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 licensing@litecommerce.com so we can send you a copy immediately.
  15. *
  16. * @category LiteCommerce
  17. * @package XLite
  18. * @subpackage Model
  19. * @author Creative Development LLC <info@cdev.ru>
  20. * @copyright Copyright (c) 2011 Creative Development LLC <info@cdev.ru>. All rights reserved
  21. * @license http://opensource.org/licenses/osl-3.0.php Open Software License (OSL 3.0)
  22. * @version GIT: $Id: abd3881753e69af232d95057d1f455a946859382 $
  23. * @link http://www.litecommerce.com/
  24. * @see ____file_see____
  25. * @since 3.0.0
  26. */
  27. namespace XLite\Model\OrderModifier;
  28. /**
  29. * Shipping order modifier
  30. *
  31. * @package XLite
  32. * @see ____class_see____
  33. * @since 3.0.0
  34. */
  35. abstract class Shipping extends \XLite\Model\Order implements \XLite\Base\IDecorator
  36. {
  37. /**
  38. * Modifier name definition
  39. */
  40. const MODIFIER_SHIPPING = 'shipping';
  41. /**
  42. * shippingRate
  43. *
  44. * @var \XLite\Model\Shipping\Rate
  45. * @access protected
  46. * @see ____var_see____
  47. * @since 3.0.0
  48. */
  49. protected $selectedRate;
  50. /**
  51. * Define order modifiers
  52. *
  53. * @return array
  54. * @access protected
  55. * @see ____func_see____
  56. * @since 3.0.0
  57. */
  58. protected function defineModifiers()
  59. {
  60. $list = parent::defineModifiers();
  61. $list[10] = self::MODIFIER_SHIPPING;
  62. return $list;
  63. }
  64. /**
  65. * Calculate shipping
  66. *
  67. * @return void
  68. * @access protected
  69. * @see ____func_see____
  70. * @since 3.0.0
  71. */
  72. protected function calculateShipping()
  73. {
  74. $cost = 0;
  75. if (!$this->isShippingEnabled()) {
  76. $this->unsetModifier(self::MODIFIER_SHIPPING);
  77. } else {
  78. if ($this->isShipped()) {
  79. $rate = $this->getSelectedRate();
  80. if (is_object($rate)) {
  81. $cost = $rate->getTotalRate();
  82. }
  83. }
  84. $this->saveModifier(self::MODIFIER_SHIPPING, $cost);
  85. }
  86. }
  87. /**
  88. * Get shipping cost row name
  89. *
  90. * @return string
  91. * @access protected
  92. * @see ____func_see____
  93. * @since 3.0.0
  94. */
  95. protected function getShippingName()
  96. {
  97. return 'Shipping cost';
  98. }
  99. /**
  100. * Calculate shipping rates
  101. *
  102. * @return array(\XLite\Model\Shipping\Rate)
  103. * @access protected
  104. * @see ____func_see____
  105. * @since 3.0.0
  106. */
  107. protected function calculateShippingRates()
  108. {
  109. $rates = array();
  110. if ($this->isShipped()) {
  111. $rates = \XLite\Model\Shipping::getInstance()->getRates($this);
  112. uasort($rates, array($this, 'compareShippingRates'));
  113. }
  114. return $rates;
  115. }
  116. /**
  117. * Shipping rates sorting callback
  118. *
  119. * @param \XLite\Model\Shipping\Rate $a First shipping rate
  120. * @param \XLite\Model\Shipping\Rate $b Second shipping rate
  121. *
  122. * @return integer
  123. * @access protected
  124. * @see ____func_see____
  125. * @since 3.0.0
  126. */
  127. protected function compareShippingRates(\XLite\Model\Shipping\Rate $a, \XLite\Model\Shipping\Rate $b)
  128. {
  129. $result = 0;
  130. $sa = $a->getMethod();
  131. $sb = $b->getMethod();
  132. if (isset($sa) && isset($sb)) {
  133. if ($sa->getPosition() > $sb->getPosition()) {
  134. $result = 1;
  135. } elseif ($sa->getPosition() < $sb->getPosition()) {
  136. $result = -1;
  137. }
  138. }
  139. return $result;
  140. }
  141. /**
  142. * Get shipping rates
  143. * TODO: add checking if rates should be recalculated else get rates from cache
  144. *
  145. * @return array(\XLite\Model\Shipping\Rate)
  146. * @access public
  147. * @since 3.0.0
  148. */
  149. public function getShippingRates()
  150. {
  151. return $this->calculateShippingRates();
  152. }
  153. /**
  154. * Get selected shipping rate
  155. *
  156. * @return \XLite\Model\Shipping\Rate
  157. * @access public
  158. * @see ____func_see____
  159. * @since 3.0.0
  160. */
  161. public function getSelectedRate()
  162. {
  163. if (
  164. !isset($this->selectedRate)
  165. || $this->selectedRate->getMethodId() != $this->getShippingId()
  166. ) {
  167. // Get shipping rates
  168. $rates = $this->getShippingRates();
  169. $selectedRate = null;
  170. if (!empty($rates)) {
  171. if (!$this->getShippingId() && $this->getProfile() && $this->getProfile()->getLastShippingId()) {
  172. // Remember last shipping id
  173. $this->setShippingId($this->getProfile()->getLastShippingId());
  174. }
  175. if (0 < intval($this->getShippingId())) {
  176. // Set selected rate from the rates list if shipping_id is already assigned
  177. foreach ($rates as $rate) {
  178. if ($this->getShippingId() == $rate->getMethodId()) {
  179. $selectedRate = $rate;
  180. break;
  181. }
  182. }
  183. }
  184. }
  185. $this->setSelectedRate($selectedRate);
  186. }
  187. return $this->selectedRate;
  188. }
  189. /**
  190. * Set shipping rate and shipping method id
  191. *
  192. * @param \XLite\Model\Shipping\Rate $rate Shipping rate object
  193. *
  194. * @return void
  195. * @access public
  196. * @see ____func_see____
  197. * @since 3.0.0
  198. */
  199. public function setSelectedRate(\XLite\Model\Shipping\Rate $rate = null)
  200. {
  201. $newShippingId = $this->getShippingId();
  202. $this->selectedRate = $rate;
  203. $newShippingId = $rate ? $rate->getMethodId() : 0;
  204. if ($this->getShippingId() != $newShippingId) {
  205. $this->setShippingId($newShippingId);
  206. \XLite\Core\Database::getEM()->flush();
  207. }
  208. }
  209. /**
  210. * Service method: check if shipping is visible or not at the moment of saveModifier() call
  211. *
  212. * @return boolean
  213. * @access public
  214. * @see ____func_see____
  215. * @since 3.0.0
  216. */
  217. public function isShippingVisible()
  218. {
  219. return $this->isShippingEnabled();
  220. }
  221. /**
  222. * Service method: check if shipping rate selected and should be displayed
  223. * Method is used by isAvailable() (\XLite\Model\OrderModifier class)
  224. *
  225. * @return boolean
  226. * @access public
  227. * @see ____func_see____
  228. * @since 3.0.0
  229. */
  230. public function isShippingAvailable()
  231. {
  232. return $this->isDeliveryAvailable();
  233. }
  234. /**
  235. * Check if shipping enabled and available for calculation
  236. *
  237. * @return boolean
  238. * @access public
  239. * @see ____func_see____
  240. * @since 3.0.0
  241. */
  242. public function isShippingEnabled()
  243. {
  244. return 'Y' == \XLite\Base::getInstance()->config->Shipping->shipping_enabled;
  245. }
  246. /**
  247. * Check if shipping rate has been selected
  248. *
  249. * @return boolean
  250. * @access public
  251. * @see ____func_see____
  252. * @since 3.0.0
  253. */
  254. public function isShippingSelected()
  255. {
  256. return is_object($this->getSelectedRate());
  257. }
  258. /**
  259. * Check - shipping is available for this order or not
  260. *
  261. * @return boolean
  262. * @access public
  263. * @since 3.0.0
  264. */
  265. public function isDeliveryAvailable()
  266. {
  267. return $this->isShippingVisible() && $this->isShipped() && 0 < count($this->getShippingRates());
  268. }
  269. /**
  270. * Get shipped items
  271. *
  272. * @return array
  273. * @access public
  274. * @see ____func_see____
  275. * @since 3.0.0
  276. */
  277. public function getShippedItems()
  278. {
  279. $result = array();
  280. foreach ($this->getItems() as $item) {
  281. if ($item->isShipped()) {
  282. $result[] = $item;
  283. }
  284. }
  285. return $result;
  286. }
  287. /**
  288. * Get order weight
  289. *
  290. * @return float
  291. * @access public
  292. * @see ____func_see____
  293. * @since 3.0.0
  294. */
  295. public function getWeight()
  296. {
  297. $weight = 0;
  298. foreach ($this->getShippedItems() as $item) {
  299. $weight += $item->getWeight();
  300. }
  301. return $weight;
  302. }
  303. /**
  304. * Count shipped items quantity
  305. *
  306. * @return integer
  307. * @access public
  308. * @see ____func_see____
  309. * @since 3.0.0
  310. */
  311. public function countShippedItems()
  312. {
  313. $result = 0;
  314. foreach ($this->getShippedItems() as $item) {
  315. $result += $item->getAmount();
  316. }
  317. return $result;
  318. }
  319. /**
  320. * Get shipping method
  321. *
  322. * @return \XLite\Model\Shipping\Method
  323. * @access public
  324. * @see ____func_see____
  325. * @since 3.0.0
  326. */
  327. public function getShippingMethod()
  328. {
  329. $result = null;
  330. $rate = $this->getSelectedRate();
  331. if (isset($rate)) {
  332. $result = $rate->getMethod();
  333. }
  334. return $result;
  335. }
  336. /**
  337. * Returns true if any of order items are shipped
  338. *
  339. * @return boolean
  340. * @access public
  341. * @since 3.0.0
  342. */
  343. public function isShipped()
  344. {
  345. $result = false;
  346. foreach ($this->getItems() as $item) {
  347. if ($item->isShipped()) {
  348. $result = true;
  349. break;
  350. }
  351. }
  352. return $result;
  353. }
  354. /**
  355. * Get order subtotal only for shipped items
  356. *
  357. * @return float
  358. * @access public
  359. * @see ____func_see____
  360. * @since 3.0.0
  361. */
  362. public function getShippedSubtotal()
  363. {
  364. $this->calculateSubtotal();
  365. $subtotal = 0;
  366. foreach ($this->getItems() as $item) {
  367. if ($item->isShipped()) {
  368. $subtotal += $item->getTotal();
  369. }
  370. }
  371. return $subtotal;
  372. }
  373. }