LinkRepository.php 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Downloadable\Model;
  7. use Magento\Catalog\Api\Data\ProductInterface;
  8. use Magento\Downloadable\Api\Data\LinkInterface;
  9. use Magento\Downloadable\Model\Product\Type;
  10. use Magento\Downloadable\Api\Data\File\ContentUploaderInterface;
  11. use Magento\Downloadable\Model\Product\TypeHandler\Link as LinkHandler;
  12. use Magento\Framework\EntityManager\MetadataPool;
  13. use Magento\Framework\Exception\InputException;
  14. use Magento\Framework\Exception\NoSuchEntityException;
  15. use Magento\Framework\Exception\StateException;
  16. use Magento\Framework\Json\EncoderInterface;
  17. use Magento\Framework\App\ObjectManager;
  18. /**
  19. * Class LinkRepository
  20. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  21. */
  22. class LinkRepository implements \Magento\Downloadable\Api\LinkRepositoryInterface
  23. {
  24. /**
  25. * @var \Magento\Catalog\Api\ProductRepositoryInterface
  26. */
  27. protected $productRepository;
  28. /**
  29. * @var \Magento\Downloadable\Api\Data\LinkInterfaceFactory
  30. */
  31. protected $linkDataObjectFactory;
  32. /**
  33. * @var \Magento\Downloadable\Model\LinkFactory
  34. */
  35. protected $linkFactory;
  36. /**
  37. * @var \Magento\Downloadable\Model\Link\ContentValidator
  38. */
  39. protected $contentValidator;
  40. /**
  41. * @var Type
  42. */
  43. protected $downloadableType;
  44. /**
  45. * @var ContentUploaderInterface
  46. */
  47. protected $fileContentUploader;
  48. /**
  49. * @var EncoderInterface
  50. */
  51. protected $jsonEncoder;
  52. /**
  53. * @var LinkHandler
  54. */
  55. private $linkTypeHandler;
  56. /**
  57. * @var MetadataPool
  58. */
  59. private $metadataPool;
  60. /**
  61. * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository
  62. * @param \Magento\Downloadable\Model\Product\Type $downloadableType
  63. * @param \Magento\Downloadable\Api\Data\LinkInterfaceFactory $linkDataObjectFactory
  64. * @param LinkFactory $linkFactory
  65. * @param Link\ContentValidator $contentValidator
  66. * @param EncoderInterface $jsonEncoder
  67. * @param ContentUploaderInterface $fileContentUploader
  68. */
  69. public function __construct(
  70. \Magento\Catalog\Api\ProductRepositoryInterface $productRepository,
  71. \Magento\Downloadable\Model\Product\Type $downloadableType,
  72. \Magento\Downloadable\Api\Data\LinkInterfaceFactory $linkDataObjectFactory,
  73. LinkFactory $linkFactory,
  74. Link\ContentValidator $contentValidator,
  75. EncoderInterface $jsonEncoder,
  76. ContentUploaderInterface $fileContentUploader
  77. ) {
  78. $this->productRepository = $productRepository;
  79. $this->downloadableType = $downloadableType;
  80. $this->linkDataObjectFactory = $linkDataObjectFactory;
  81. $this->linkFactory = $linkFactory;
  82. $this->contentValidator = $contentValidator;
  83. $this->jsonEncoder = $jsonEncoder;
  84. $this->fileContentUploader = $fileContentUploader;
  85. }
  86. /**
  87. * {@inheritdoc}
  88. */
  89. public function getList($sku)
  90. {
  91. /** @var \Magento\Catalog\Model\Product $product */
  92. $product = $this->productRepository->get($sku);
  93. return $this->getLinksByProduct($product);
  94. }
  95. /**
  96. * @param \Magento\Catalog\Api\Data\ProductInterface $product
  97. * @return array
  98. */
  99. public function getLinksByProduct(\Magento\Catalog\Api\Data\ProductInterface $product)
  100. {
  101. $linkList = [];
  102. $links = $this->downloadableType->getLinks($product);
  103. /** @var \Magento\Downloadable\Model\Link $link */
  104. foreach ($links as $link) {
  105. $linkList[] = $this->buildLink($link);
  106. }
  107. return $linkList;
  108. }
  109. /**
  110. * Build a link data object
  111. *
  112. * @param \Magento\Downloadable\Model\Link $resourceData
  113. * @return \Magento\Downloadable\Model\Link
  114. */
  115. protected function buildLink($resourceData)
  116. {
  117. /** @var \Magento\Downloadable\Model\Link $link */
  118. $link = $this->linkDataObjectFactory->create();
  119. $this->setBasicFields($resourceData, $link);
  120. $link->setPrice($resourceData->getPrice());
  121. $link->setNumberOfDownloads($resourceData->getNumberOfDownloads());
  122. $link->setIsShareable($resourceData->getIsShareable());
  123. $link->setLinkType($resourceData->getLinkType());
  124. $link->setLinkFile($resourceData->getLinkFile());
  125. $link->setLinkUrl($resourceData->getLinkUrl());
  126. return $link;
  127. }
  128. /**
  129. * Subroutine for build link
  130. *
  131. * @param \Magento\Downloadable\Model\Link $resourceData
  132. * @param \Magento\Downloadable\Api\Data\LinkInterface $dataObject
  133. * @return null
  134. */
  135. protected function setBasicFields($resourceData, $dataObject)
  136. {
  137. $dataObject->setId($resourceData->getId());
  138. $storeTitle = $resourceData->getStoreTitle();
  139. $title = $resourceData->getTitle();
  140. if (!empty($storeTitle)) {
  141. $dataObject->setTitle($storeTitle);
  142. } else {
  143. $dataObject->setTitle($title);
  144. }
  145. $dataObject->setSortOrder($resourceData->getSortOrder());
  146. $dataObject->setSampleType($resourceData->getSampleType());
  147. $dataObject->setSampleFile($resourceData->getSampleFile());
  148. $dataObject->setSampleUrl($resourceData->getSampleUrl());
  149. }
  150. /**
  151. * {@inheritdoc}
  152. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  153. * @SuppressWarnings(PHPMD.NPathComplexity)
  154. */
  155. public function save($sku, LinkInterface $link, $isGlobalScopeContent = true)
  156. {
  157. $product = $this->productRepository->get($sku, true);
  158. if ($link->getId() !== null) {
  159. return $this->updateLink($product, $link, $isGlobalScopeContent);
  160. } else {
  161. if ($product->getTypeId() !== \Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE) {
  162. throw new InputException(
  163. __('The product needs to be the downloadable type. Verify the product and try again.')
  164. );
  165. }
  166. $validateLinkContent = !($link->getLinkType() === 'file' && $link->getLinkFile());
  167. $validateSampleContent = !($link->getSampleType() === 'file' && $link->getSampleFile());
  168. if (!$this->contentValidator->isValid($link, $validateLinkContent, $validateSampleContent)) {
  169. throw new InputException(__('The link information is invalid. Verify the link and try again.'));
  170. }
  171. if (!in_array($link->getLinkType(), ['url', 'file'], true)) {
  172. throw new InputException(__('The link type is invalid. Verify and try again.'));
  173. }
  174. $title = $link->getTitle();
  175. if (empty($title)) {
  176. throw new InputException(__('The link title is empty. Enter the link title and try again.'));
  177. }
  178. return $this->saveLink($product, $link, $isGlobalScopeContent);
  179. }
  180. }
  181. /**
  182. * @param \Magento\Catalog\Api\Data\ProductInterface $product
  183. * @param LinkInterface $link
  184. * @param bool $isGlobalScopeContent
  185. * @return int
  186. */
  187. protected function saveLink(
  188. \Magento\Catalog\Api\Data\ProductInterface $product,
  189. LinkInterface $link,
  190. $isGlobalScopeContent
  191. ) {
  192. $linkData = [
  193. 'link_id' => (int)$link->getId(),
  194. 'is_delete' => 0,
  195. 'type' => $link->getLinkType(),
  196. 'sort_order' => $link->getSortOrder(),
  197. 'title' => $link->getTitle(),
  198. 'price' => $link->getPrice(),
  199. 'number_of_downloads' => $link->getNumberOfDownloads(),
  200. 'is_shareable' => $link->getIsShareable(),
  201. ];
  202. if ($link->getLinkType() == 'file' && $link->getLinkFile() === null) {
  203. $linkData['file'] = $this->jsonEncoder->encode(
  204. [
  205. $this->fileContentUploader->upload($link->getLinkFileContent(), 'link_file'),
  206. ]
  207. );
  208. } elseif ($link->getLinkType() === 'url') {
  209. $linkData['link_url'] = $link->getLinkUrl();
  210. } else {
  211. //existing link file
  212. $linkData['file'] = $this->jsonEncoder->encode(
  213. [
  214. [
  215. 'file' => $link->getLinkFile(),
  216. 'status' => 'old',
  217. ]
  218. ]
  219. );
  220. }
  221. if ($link->getSampleType() == 'file') {
  222. $linkData['sample']['type'] = 'file';
  223. if ($link->getSampleFile() === null) {
  224. $fileData = [
  225. $this->fileContentUploader->upload($link->getSampleFileContent(), 'link_sample_file'),
  226. ];
  227. } else {
  228. $fileData = [
  229. [
  230. 'file' => $link->getSampleFile(),
  231. 'status' => 'old',
  232. ]
  233. ];
  234. }
  235. $linkData['sample']['file'] = $this->jsonEncoder->encode($fileData);
  236. } elseif ($link->getSampleType() == 'url') {
  237. $linkData['sample']['type'] = 'url';
  238. $linkData['sample']['url'] = $link->getSampleUrl();
  239. }
  240. $downloadableData = ['link' => [$linkData]];
  241. if ($isGlobalScopeContent) {
  242. $product->setStoreId(0);
  243. }
  244. $this->getLinkTypeHandler()->save($product, $downloadableData);
  245. return $product->getLastAddedLinkId();
  246. }
  247. /**
  248. * @param \Magento\Catalog\Api\Data\ProductInterface $product
  249. * @param LinkInterface $link
  250. * @param bool $isGlobalScopeContent
  251. * @return mixed
  252. * @throws InputException
  253. * @throws NoSuchEntityException
  254. * @SuppressWarnings(PHPMD.CyclomaticComplexity)
  255. * @SuppressWarnings(PHPMD.NPathComplexity)
  256. */
  257. protected function updateLink(
  258. \Magento\Catalog\Api\Data\ProductInterface $product,
  259. LinkInterface $link,
  260. $isGlobalScopeContent
  261. ) {
  262. /** @var $existingLink \Magento\Downloadable\Model\Link */
  263. $existingLink = $this->linkFactory->create()->load($link->getId());
  264. if (!$existingLink->getId()) {
  265. throw new NoSuchEntityException(
  266. __('No downloadable link with the provided ID was found. Verify the ID and try again.')
  267. );
  268. }
  269. $linkFieldValue = $product->getData(
  270. $this->getMetadataPool()->getMetadata(ProductInterface::class)->getLinkField()
  271. );
  272. if ($existingLink->getProductId() != $linkFieldValue) {
  273. throw new InputException(
  274. __("The downloadable link isn't related to the product. Verify the link and try again.")
  275. );
  276. }
  277. $validateLinkContent = !($link->getLinkFileContent() === null);
  278. $validateSampleContent = !($link->getSampleFileContent() === null);
  279. if (!$this->contentValidator->isValid($link, $validateLinkContent, $validateSampleContent)) {
  280. throw new InputException(__('The link information is invalid. Verify the link and try again.'));
  281. }
  282. if ($isGlobalScopeContent) {
  283. $product->setStoreId(0);
  284. }
  285. $title = $link->getTitle();
  286. if (empty($title)) {
  287. if ($isGlobalScopeContent) {
  288. throw new InputException(__('The link title is empty. Enter the link title and try again.'));
  289. }
  290. }
  291. if ($link->getLinkType() == 'file' && $link->getLinkFileContent() === null && !$link->getLinkFile()) {
  292. $link->setLinkFile($existingLink->getLinkFile());
  293. }
  294. if ($link->getSampleType() == 'file' && $link->getSampleFileContent() === null && !$link->getSampleFile()) {
  295. $link->setSampleFile($existingLink->getSampleFile());
  296. }
  297. $this->saveLink($product, $link, $isGlobalScopeContent);
  298. return $existingLink->getId();
  299. }
  300. /**
  301. * {@inheritdoc}
  302. */
  303. public function delete($id)
  304. {
  305. /** @var $link \Magento\Downloadable\Model\Link */
  306. $link = $this->linkFactory->create()->load($id);
  307. if (!$link->getId()) {
  308. throw new NoSuchEntityException(
  309. __('No downloadable link with the provided ID was found. Verify the ID and try again.')
  310. );
  311. }
  312. try {
  313. $link->delete();
  314. } catch (\Exception $exception) {
  315. throw new StateException(__('The link with "%1" ID can\'t be deleted.', $link->getId()), $exception);
  316. }
  317. return true;
  318. }
  319. /**
  320. * Get MetadataPool instance
  321. *
  322. * @deprecated 100.1.0 MAGETWO-52273
  323. * @return MetadataPool
  324. */
  325. private function getMetadataPool()
  326. {
  327. if (!$this->metadataPool) {
  328. $this->metadataPool = ObjectManager::getInstance()->get(MetadataPool::class);
  329. }
  330. return $this->metadataPool;
  331. }
  332. /**
  333. * Get LinkTypeHandler instance
  334. *
  335. * @deprecated 100.1.0 MAGETWO-52273
  336. * @return LinkHandler
  337. */
  338. private function getLinkTypeHandler()
  339. {
  340. if (!$this->linkTypeHandler) {
  341. $this->linkTypeHandler = ObjectManager::getInstance()->get(LinkHandler::class);
  342. }
  343. return $this->linkTypeHandler;
  344. }
  345. }