Renderer.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Checkout\Block\Cart\Item;
  7. use Magento\Catalog\Pricing\Price\ConfiguredPriceInterface;
  8. use Magento\Checkout\Block\Cart\Item\Renderer\Actions;
  9. use Magento\Framework\Pricing\PriceCurrencyInterface;
  10. use Magento\Framework\View\Element\AbstractBlock;
  11. use Magento\Framework\View\Element\Message\InterpretationStrategyInterface;
  12. use Magento\Quote\Model\Quote\Item\AbstractItem;
  13. use Magento\Framework\App\ObjectManager;
  14. use Magento\Catalog\Model\Product\Configuration\Item\ItemResolverInterface;
  15. /**
  16. * Shopping cart item render block
  17. *
  18. * @api
  19. * @author Magento Core Team <core@magentocommerce.com>
  20. *
  21. * @method \Magento\Checkout\Block\Cart\Item\Renderer setProductName(string)
  22. * @method \Magento\Checkout\Block\Cart\Item\Renderer setDeleteUrl(string)
  23. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  24. * @SuppressWarnings(PHPMD.ExcessiveClassComplexity)
  25. * @since 100.0.2
  26. */
  27. class Renderer extends \Magento\Framework\View\Element\Template implements
  28. \Magento\Framework\DataObject\IdentityInterface
  29. {
  30. /**
  31. * @var \Magento\Checkout\Model\Session
  32. */
  33. protected $_checkoutSession;
  34. /**
  35. * @var AbstractItem
  36. */
  37. protected $_item;
  38. /**
  39. * @var string
  40. */
  41. protected $_productUrl;
  42. /**
  43. * Whether qty will be converted to number
  44. *
  45. * @var bool
  46. */
  47. protected $_strictQtyMode = true;
  48. /**
  49. * Check, whether product URL rendering should be ignored
  50. *
  51. * @var bool
  52. */
  53. protected $_ignoreProductUrl = false;
  54. /**
  55. * Catalog product configuration
  56. *
  57. * @var \Magento\Catalog\Helper\Product\Configuration
  58. */
  59. protected $_productConfig = null;
  60. /**
  61. * @var \Magento\Framework\Url\Helper\Data
  62. */
  63. protected $_urlHelper;
  64. /**
  65. * @var \Magento\Framework\Message\ManagerInterface
  66. */
  67. protected $messageManager;
  68. /**
  69. * @var \Magento\Catalog\Block\Product\ImageBuilder
  70. */
  71. protected $imageBuilder;
  72. /**
  73. * @var PriceCurrencyInterface
  74. */
  75. protected $priceCurrency;
  76. /**
  77. * @var \Magento\Framework\Module\Manager
  78. */
  79. public $moduleManager;
  80. /**
  81. * @var InterpretationStrategyInterface
  82. */
  83. private $messageInterpretationStrategy;
  84. /** @var ItemResolverInterface */
  85. private $itemResolver;
  86. /**
  87. * @param \Magento\Framework\View\Element\Template\Context $context
  88. * @param \Magento\Catalog\Helper\Product\Configuration $productConfig
  89. * @param \Magento\Checkout\Model\Session $checkoutSession
  90. * @param \Magento\Catalog\Block\Product\ImageBuilder $imageBuilder
  91. * @param \Magento\Framework\Url\Helper\Data $urlHelper
  92. * @param \Magento\Framework\Message\ManagerInterface $messageManager
  93. * @param PriceCurrencyInterface $priceCurrency
  94. * @param \Magento\Framework\Module\Manager $moduleManager
  95. * @param InterpretationStrategyInterface $messageInterpretationStrategy
  96. * @param array $data
  97. * @param ItemResolverInterface|null $itemResolver
  98. * @SuppressWarnings(PHPMD.ExcessiveParameterList)
  99. * @codeCoverageIgnore
  100. */
  101. public function __construct(
  102. \Magento\Framework\View\Element\Template\Context $context,
  103. \Magento\Catalog\Helper\Product\Configuration $productConfig,
  104. \Magento\Checkout\Model\Session $checkoutSession,
  105. \Magento\Catalog\Block\Product\ImageBuilder $imageBuilder,
  106. \Magento\Framework\Url\Helper\Data $urlHelper,
  107. \Magento\Framework\Message\ManagerInterface $messageManager,
  108. PriceCurrencyInterface $priceCurrency,
  109. \Magento\Framework\Module\Manager $moduleManager,
  110. InterpretationStrategyInterface $messageInterpretationStrategy,
  111. array $data = [],
  112. ItemResolverInterface $itemResolver = null
  113. ) {
  114. $this->priceCurrency = $priceCurrency;
  115. $this->imageBuilder = $imageBuilder;
  116. $this->_urlHelper = $urlHelper;
  117. $this->_productConfig = $productConfig;
  118. $this->_checkoutSession = $checkoutSession;
  119. $this->messageManager = $messageManager;
  120. parent::__construct($context, $data);
  121. $this->_isScopePrivate = true;
  122. $this->moduleManager = $moduleManager;
  123. $this->messageInterpretationStrategy = $messageInterpretationStrategy;
  124. $this->itemResolver = $itemResolver ?: ObjectManager::getInstance()->get(ItemResolverInterface::class);
  125. }
  126. /**
  127. * Set item for render
  128. *
  129. * @param AbstractItem $item
  130. * @return $this
  131. * @codeCoverageIgnore
  132. */
  133. public function setItem(AbstractItem $item)
  134. {
  135. $this->_item = $item;
  136. return $this;
  137. }
  138. /**
  139. * Get quote item
  140. *
  141. * @return AbstractItem
  142. * @codeCoverageIgnore
  143. */
  144. public function getItem()
  145. {
  146. return $this->_item;
  147. }
  148. /**
  149. * Get item product
  150. *
  151. * @return \Magento\Catalog\Model\Product
  152. * @codeCoverageIgnore
  153. */
  154. public function getProduct()
  155. {
  156. return $this->getItem()->getProduct();
  157. }
  158. /**
  159. * Identify the product from which thumbnail should be taken.
  160. *
  161. * @return \Magento\Catalog\Model\Product
  162. * @codeCoverageIgnore
  163. */
  164. public function getProductForThumbnail()
  165. {
  166. return $this->itemResolver->getFinalProduct($this->getItem());
  167. }
  168. /**
  169. * @param string $productUrl
  170. * @return $this
  171. * @codeCoverageIgnore
  172. */
  173. public function overrideProductUrl($productUrl)
  174. {
  175. $this->_productUrl = $productUrl;
  176. return $this;
  177. }
  178. /**
  179. * Check Product has URL
  180. *
  181. * @return bool
  182. */
  183. public function hasProductUrl()
  184. {
  185. if ($this->_ignoreProductUrl) {
  186. return false;
  187. }
  188. if ($this->_productUrl || $this->getItem()->getRedirectUrl()) {
  189. return true;
  190. }
  191. $product = $this->getProduct();
  192. $option = $this->getItem()->getOptionByCode('product_type');
  193. if ($option) {
  194. $product = $option->getProduct();
  195. }
  196. if ($product->isVisibleInSiteVisibility()) {
  197. return true;
  198. } else {
  199. if ($product->hasUrlDataObject()) {
  200. $data = $product->getUrlDataObject();
  201. if (in_array($data->getVisibility(), $product->getVisibleInSiteVisibilities())) {
  202. return true;
  203. }
  204. }
  205. }
  206. return false;
  207. }
  208. /**
  209. * Retrieve URL to item Product
  210. *
  211. * @return string
  212. */
  213. public function getProductUrl()
  214. {
  215. if ($this->_productUrl !== null) {
  216. return $this->_productUrl;
  217. }
  218. if ($this->getItem()->getRedirectUrl()) {
  219. return $this->getItem()->getRedirectUrl();
  220. }
  221. $product = $this->getProduct();
  222. $option = $this->getItem()->getOptionByCode('product_type');
  223. if ($option) {
  224. $product = $option->getProduct();
  225. }
  226. return $product->getUrlModel()->getUrl($product);
  227. }
  228. /**
  229. * Get item product name
  230. *
  231. * @return string
  232. */
  233. public function getProductName()
  234. {
  235. if ($this->hasProductName()) {
  236. return $this->getData('product_name');
  237. }
  238. return $this->getProduct()->getName();
  239. }
  240. /**
  241. * Get product customize options
  242. *
  243. * @return array
  244. */
  245. public function getProductOptions()
  246. {
  247. /* @var $helper \Magento\Catalog\Helper\Product\Configuration */
  248. $helper = $this->_productConfig;
  249. return $helper->getCustomOptions($this->getItem());
  250. }
  251. /**
  252. * Get list of all options for product
  253. *
  254. * @return array
  255. * @codeCoverageIgnore
  256. */
  257. public function getOptionList()
  258. {
  259. return $this->getProductOptions();
  260. }
  261. /**
  262. * Get quote item qty
  263. *
  264. * @return float|int
  265. */
  266. public function getQty()
  267. {
  268. if (!$this->_strictQtyMode && (string)$this->getItem()->getQty() == '') {
  269. return '';
  270. }
  271. return $this->getItem()->getQty() * 1;
  272. }
  273. /**
  274. * Get checkout session
  275. *
  276. * @return \Magento\Checkout\Model\Session
  277. * @codeCoverageIgnore
  278. */
  279. public function getCheckoutSession()
  280. {
  281. return $this->_checkoutSession;
  282. }
  283. /**
  284. * Retrieve item messages
  285. * Return array with keys
  286. *
  287. * text => the message text
  288. * type => type of a message
  289. *
  290. * @return array
  291. */
  292. public function getMessages()
  293. {
  294. $messages = [];
  295. $quoteItem = $this->getItem();
  296. // Add basic messages occurring during this page load
  297. $baseMessages = $quoteItem->getMessage(false);
  298. if ($baseMessages) {
  299. foreach ($baseMessages as $message) {
  300. $messages[] = ['text' => $message, 'type' => $quoteItem->getHasError() ? 'error' : 'notice'];
  301. }
  302. }
  303. /* @var $collection \Magento\Framework\Message\Collection */
  304. $collection = $this->messageManager->getMessages(true, 'quote_item' . $quoteItem->getId());
  305. if ($collection) {
  306. $additionalMessages = $collection->getItems();
  307. foreach ($additionalMessages as $message) {
  308. /* @var $message \Magento\Framework\Message\MessageInterface */
  309. $messages[] = [
  310. 'text' => $this->messageInterpretationStrategy->interpret($message),
  311. 'type' => $message->getType()
  312. ];
  313. }
  314. }
  315. $this->messageManager->getMessages(true, 'quote_item' . $quoteItem->getId())->clear();
  316. return $messages;
  317. }
  318. /**
  319. * Accept option value and return its formatted view
  320. *
  321. * @param string|array $optionValue
  322. * Method works well with these $optionValue format:
  323. * 1. String
  324. * 2. Indexed array e.g. array(val1, val2, ...)
  325. * 3. Associative array, containing additional option info, including option value, e.g.
  326. * array
  327. * (
  328. * [label] => ...,
  329. * [value] => ...,
  330. * [print_value] => ...,
  331. * [option_id] => ...,
  332. * [option_type] => ...,
  333. * [custom_view] =>...,
  334. * )
  335. *
  336. * @return array
  337. */
  338. public function getFormatedOptionValue($optionValue)
  339. {
  340. /* @var $helper \Magento\Catalog\Helper\Product\Configuration */
  341. $helper = $this->_productConfig;
  342. $params = [
  343. 'max_length' => 55,
  344. 'cut_replacer' => ' <a href="#" class="dots tooltip toggle" onclick="return false">...</a>'
  345. ];
  346. return $helper->getFormattedOptionValue($optionValue, $params);
  347. }
  348. /**
  349. * Check whether Product is visible in site
  350. *
  351. * @return bool
  352. * @codeCoverageIgnore
  353. */
  354. public function isProductVisible()
  355. {
  356. return $this->getProduct()->isVisibleInSiteVisibility();
  357. }
  358. /**
  359. * Return product additional information block
  360. *
  361. * @return AbstractBlock
  362. * @codeCoverageIgnore
  363. */
  364. public function getProductAdditionalInformationBlock()
  365. {
  366. return $this->getLayout()->getBlock('additional.product.info');
  367. }
  368. /**
  369. * Set qty mode to be strict or not
  370. *
  371. * @param bool $strict
  372. * @return $this
  373. * @codeCoverageIgnore
  374. */
  375. public function setQtyMode($strict)
  376. {
  377. $this->_strictQtyMode = $strict;
  378. return $this;
  379. }
  380. /**
  381. * Set ignore product URL rendering
  382. *
  383. * @param bool $ignore
  384. * @return $this
  385. * @codeCoverageIgnore
  386. */
  387. public function setIgnoreProductUrl($ignore = true)
  388. {
  389. $this->_ignoreProductUrl = $ignore;
  390. return $this;
  391. }
  392. /**
  393. * Return identifiers for produced content
  394. *
  395. * @return array
  396. */
  397. public function getIdentities()
  398. {
  399. $identities = [];
  400. if ($this->getItem()) {
  401. $identities = $this->getProduct()->getIdentities();
  402. }
  403. return $identities;
  404. }
  405. /**
  406. * Get product price formatted with html (final price, special price, mrp price)
  407. *
  408. * @param \Magento\Catalog\Model\Product $product
  409. * @return string
  410. */
  411. public function getProductPriceHtml(\Magento\Catalog\Model\Product $product)
  412. {
  413. $priceRender = $this->getPriceRender();
  414. $priceRender->setItem($this->getItem());
  415. $price = '';
  416. if ($priceRender) {
  417. $price = $priceRender->render(
  418. ConfiguredPriceInterface::CONFIGURED_PRICE_CODE,
  419. $product,
  420. [
  421. 'include_container' => true,
  422. 'display_minimal_price' => true,
  423. 'zone' => \Magento\Framework\Pricing\Render::ZONE_ITEM_LIST
  424. ]
  425. );
  426. }
  427. return $price;
  428. }
  429. /**
  430. * @return \Magento\Framework\Pricing\Render
  431. * @codeCoverageIgnore
  432. */
  433. protected function getPriceRender()
  434. {
  435. return $this->getLayout()->getBlock('product.price.render.default');
  436. }
  437. /**
  438. * Convert prices for template
  439. *
  440. * @param float $amount
  441. * @param bool $format
  442. * @return float
  443. */
  444. public function convertPrice($amount, $format = false)
  445. {
  446. return $format
  447. ? $this->priceCurrency->convertAndFormat($amount)
  448. : $this->priceCurrency->convert($amount);
  449. }
  450. /**
  451. * Return the unit price html
  452. *
  453. * @param AbstractItem $item
  454. * @return string
  455. */
  456. public function getUnitPriceHtml(AbstractItem $item)
  457. {
  458. /** @var Renderer $block */
  459. $block = $this->getLayout()->getBlock('checkout.item.price.unit');
  460. $block->setItem($item);
  461. return $block->toHtml();
  462. }
  463. /**
  464. * Return row total html
  465. *
  466. * @param AbstractItem $item
  467. * @return string
  468. */
  469. public function getRowTotalHtml(AbstractItem $item)
  470. {
  471. /** @var Renderer $block */
  472. $block = $this->getLayout()->getBlock('checkout.item.price.row');
  473. $block->setItem($item);
  474. return $block->toHtml();
  475. }
  476. /**
  477. * Return item price html for sidebar
  478. *
  479. * @param AbstractItem $item
  480. * @return string
  481. */
  482. public function getSidebarItemPriceHtml(AbstractItem $item)
  483. {
  484. /** @var Renderer $block */
  485. $block = $this->getLayout()->getBlock('checkout.cart.item.price.sidebar');
  486. $block->setItem($item);
  487. return $block->toHtml();
  488. }
  489. /**
  490. * Get unit price excluding tax html
  491. *
  492. * @param AbstractItem $item
  493. * @return string
  494. */
  495. public function getUnitPriceExclTaxHtml(AbstractItem $item)
  496. {
  497. /** @var Renderer $block */
  498. $block = $this->getLayout()->getBlock('checkout.onepage.review.item.price.unit.excl');
  499. $block->setItem($item);
  500. return $block->toHtml();
  501. }
  502. /**
  503. * Get unit price including tax html
  504. *
  505. * @param AbstractItem $item
  506. * @return string
  507. */
  508. public function getUnitPriceInclTaxHtml(AbstractItem $item)
  509. {
  510. /** @var Renderer $block */
  511. $block = $this->getLayout()->getBlock('checkout.onepage.review.item.price.unit.incl');
  512. $block->setItem($item);
  513. return $block->toHtml();
  514. }
  515. /**
  516. * Get row total excluding tax html
  517. *
  518. * @param AbstractItem $item
  519. * @return string
  520. */
  521. public function getRowTotalExclTaxHtml(AbstractItem $item)
  522. {
  523. /** @var Renderer $block */
  524. $block = $this->getLayout()->getBlock('checkout.onepage.review.item.price.rowtotal.excl');
  525. $block->setItem($item);
  526. return $block->toHtml();
  527. }
  528. /**
  529. * Get row total including tax html
  530. *
  531. * @param AbstractItem $item
  532. * @return string
  533. */
  534. public function getRowTotalInclTaxHtml(AbstractItem $item)
  535. {
  536. /** @var Renderer $block */
  537. $block = $this->getLayout()->getBlock('checkout.onepage.review.item.price.rowtotal.incl');
  538. $block->setItem($item);
  539. return $block->toHtml();
  540. }
  541. /**
  542. * Get row total including tax html
  543. *
  544. * @param AbstractItem $item
  545. * @return string
  546. */
  547. public function getActions(AbstractItem $item)
  548. {
  549. /** @var Actions $block */
  550. $block = $this->getChildBlock('actions');
  551. if ($block instanceof Actions) {
  552. $block->setItem($item);
  553. return $block->toHtml();
  554. } else {
  555. return '';
  556. }
  557. }
  558. /**
  559. * Retrieve product image
  560. *
  561. * @param \Magento\Catalog\Model\Product $product
  562. * @param string $imageId
  563. * @param array $attributes
  564. * @return \Magento\Catalog\Block\Product\Image
  565. */
  566. public function getImage($product, $imageId, $attributes = [])
  567. {
  568. return $this->imageBuilder->create($product, $imageId, $attributes);
  569. }
  570. }