Import.php 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\OfflineShipping\Model\ResourceModel\Carrier\Tablerate;
  7. use Magento\Framework\App\Config\ScopeConfigInterface;
  8. use Magento\Framework\Exception\LocalizedException;
  9. use Magento\Framework\Filesystem;
  10. use Magento\Framework\Filesystem\File\ReadInterface;
  11. use Magento\OfflineShipping\Model\ResourceModel\Carrier\Tablerate\CSV\ColumnResolver;
  12. use Magento\OfflineShipping\Model\ResourceModel\Carrier\Tablerate\CSV\ColumnResolverFactory;
  13. use Magento\OfflineShipping\Model\ResourceModel\Carrier\Tablerate\CSV\RowException;
  14. use Magento\OfflineShipping\Model\ResourceModel\Carrier\Tablerate\CSV\RowParser;
  15. use Magento\Store\Model\StoreManagerInterface;
  16. /**
  17. * Import offline shipping.
  18. * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  19. */
  20. class Import
  21. {
  22. /**
  23. * @var StoreManagerInterface
  24. */
  25. private $storeManager;
  26. /**
  27. * @var Filesystem
  28. */
  29. private $filesystem;
  30. /**
  31. * @var ScopeConfigInterface
  32. */
  33. private $coreConfig;
  34. /**
  35. * @var array
  36. */
  37. private $errors = [];
  38. /**
  39. * @var CSV\RowParser
  40. */
  41. private $rowParser;
  42. /**
  43. * @var CSV\ColumnResolverFactory
  44. */
  45. private $columnResolverFactory;
  46. /**
  47. * @var DataHashGenerator
  48. */
  49. private $dataHashGenerator;
  50. /**
  51. * @var array
  52. */
  53. private $uniqueHash = [];
  54. /**
  55. * Import constructor.
  56. * @param StoreManagerInterface $storeManager
  57. * @param Filesystem $filesystem
  58. * @param ScopeConfigInterface $coreConfig
  59. * @param CSV\RowParser $rowParser
  60. * @param CSV\ColumnResolverFactory $columnResolverFactory
  61. * @param DataHashGenerator $dataHashGenerator
  62. */
  63. public function __construct(
  64. StoreManagerInterface $storeManager,
  65. Filesystem $filesystem,
  66. ScopeConfigInterface $coreConfig,
  67. RowParser $rowParser,
  68. ColumnResolverFactory $columnResolverFactory,
  69. DataHashGenerator $dataHashGenerator
  70. ) {
  71. $this->storeManager = $storeManager;
  72. $this->filesystem = $filesystem;
  73. $this->coreConfig = $coreConfig;
  74. $this->rowParser = $rowParser;
  75. $this->columnResolverFactory = $columnResolverFactory;
  76. $this->dataHashGenerator = $dataHashGenerator;
  77. }
  78. /**
  79. * Check if there are errors.
  80. *
  81. * @return bool
  82. */
  83. public function hasErrors()
  84. {
  85. return (bool)count($this->getErrors());
  86. }
  87. /**
  88. * Get errors.
  89. *
  90. * @return array
  91. */
  92. public function getErrors()
  93. {
  94. return $this->errors;
  95. }
  96. /**
  97. * Retrieve columns.
  98. *
  99. * @return array
  100. */
  101. public function getColumns()
  102. {
  103. return $this->rowParser->getColumns();
  104. }
  105. /**
  106. * Get data from file.
  107. *
  108. * @param ReadInterface $file
  109. * @param int $websiteId
  110. * @param string $conditionShortName
  111. * @param string $conditionFullName
  112. * @param int $bunchSize
  113. * @return \Generator
  114. * @throws LocalizedException
  115. */
  116. public function getData(ReadInterface $file, $websiteId, $conditionShortName, $conditionFullName, $bunchSize = 5000)
  117. {
  118. $this->errors = [];
  119. $headers = $this->getHeaders($file);
  120. /** @var ColumnResolver $columnResolver */
  121. $columnResolver = $this->columnResolverFactory->create(['headers' => $headers]);
  122. $rowNumber = 1;
  123. $items = [];
  124. while (false !== ($csvLine = $file->readCsv())) {
  125. try {
  126. $rowNumber++;
  127. if (empty($csvLine)) {
  128. continue;
  129. }
  130. $rowsData = $this->rowParser->parse(
  131. $csvLine,
  132. $rowNumber,
  133. $websiteId,
  134. $conditionShortName,
  135. $conditionFullName,
  136. $columnResolver
  137. );
  138. foreach ($rowsData as $rowData) {
  139. // protect from duplicate
  140. $hash = $this->dataHashGenerator->getHash($rowData);
  141. if (array_key_exists($hash, $this->uniqueHash)) {
  142. throw new RowException(
  143. __(
  144. 'Duplicate Row #%1 (duplicates row #%2)',
  145. $rowNumber,
  146. $this->uniqueHash[$hash]
  147. )
  148. );
  149. }
  150. $this->uniqueHash[$hash] = $rowNumber;
  151. $items[] = $rowData;
  152. }
  153. if (count($rowsData) > 1) {
  154. $bunchSize += count($rowsData) - 1;
  155. }
  156. if (count($items) === $bunchSize) {
  157. yield $items;
  158. $items = [];
  159. }
  160. } catch (RowException $e) {
  161. $this->errors[] = $e->getMessage();
  162. }
  163. }
  164. if (count($items)) {
  165. yield $items;
  166. }
  167. }
  168. /**
  169. * Retrieve column headers.
  170. *
  171. * @param ReadInterface $file
  172. * @return array|bool
  173. * @throws LocalizedException
  174. */
  175. private function getHeaders(ReadInterface $file)
  176. {
  177. // check and skip headers
  178. $headers = $file->readCsv();
  179. if ($headers === false || count($headers) < 5) {
  180. throw new LocalizedException(
  181. __('The Table Rates File Format is incorrect. Verify the format and try again.')
  182. );
  183. }
  184. return $headers;
  185. }
  186. }