PageRenderTime 24ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/hitch_commands/src/SpeedLab/Hitch/CommandsBundle/Command/Item/Processor/ShopifyCatalogFeedFileGenerator.php

https://bitbucket.org/cdelacruz_sft/hitch
PHP | 322 lines | 258 code | 61 blank | 3 comment | 26 complexity | fb5d5274877e376d6432ef50fbfa0da8 MD5 | raw file
  1. <?php
  2. namespace SpeedLab\Hitch\CommandsBundle\Command\Item\Processor;
  3. use ArrayObject;
  4. use SpeedLab\Hitch\CommandsBundle\Command\HitchCommandBase;
  5. use SpeedLab\Hitch\CommandsBundle\Command\Utils\CodeGeneratorInterface;
  6. use SpeedLab\Hitch\DatabaseBundle\Model\ItemColorCd;
  7. use SpeedLab\Hitch\DatabaseBundle\Model\ItemColorCdPeer;
  8. use SpeedLab\Hitch\DatabaseBundle\Model\ItemSizeCd;
  9. use SpeedLab\Hitch\DatabaseBundle\Model\ItemSizeCdPeer;
  10. use SpeedLab\Hitch\DatabaseBundle\Model\Vendor;
  11. use SpeedLab\Hitch\DatabaseBundle\Model\VendorPeer;
  12. use Symfony\Component\Security\Acl\Exception\Exception;
  13. class ShopifyCatalogFeedFileGenerator extends CatalogFeedFileGenerator
  14. {
  15. use ShopifyItemsProcessorMixin;
  16. const COLOR_CODE_FIELD = 'option1';
  17. const SIZE_CODE_FIELD = 'option2';
  18. public function buildVendors()
  19. {
  20. /* @var CodeGeneratorInterface $codeGenerator */
  21. $codeGenerator = $this->getCodeGenerator();
  22. $result = new ArrayObject();
  23. $processedVendors = new ArrayObject();
  24. $host = $this;
  25. $this->iterateProducts(
  26. $this->getItems(),
  27. function($product) use (
  28. $codeGenerator,
  29. $result,
  30. $processedVendors,
  31. $host
  32. ) {
  33. $vendorName = $host->normalizeDescriptionText($product->vendor);
  34. if (isset($processedVendors[$vendorName])) {
  35. return;
  36. }
  37. $vendor = VendorPeer::findByDivisionAndVendorName($host->getDivision(), $vendorName);
  38. if (is_null($vendor)) {
  39. $vendorNum = $codeGenerator->generateCode(
  40. $vendorName,
  41. ['namespace' => $host->getDivision() . '_vendor_num']
  42. );
  43. $vendorNum = str_pad($vendorNum, 10, '0', STR_PAD_LEFT);
  44. $vendor = new Vendor();
  45. $vendor->setVendorNum($vendorNum);
  46. $vendor->setDivision($host->getDivision());
  47. $vendor->setVendorName($vendorName);
  48. $vendor->save();
  49. if (isset($this->output)) {
  50. $this->output->writeln('Processing vendor "' . $product->vendor
  51. . '" => "' . $vendor->getVendorNum() . '" / ' . $vendor->getVendorName(),
  52. HitchCommandBase::STYLE_INFO);
  53. }
  54. } else {
  55. if (isset($this->output)) {
  56. $this->output->writeln('Loading vendor "' . $product->vendor
  57. . '" => "' . $vendor->getVendorNum() . '" / ' . $vendor->getVendorName(),
  58. HitchCommandBase::STYLE_INFO);
  59. }
  60. }
  61. $entry = new ArrayObject();
  62. $entry['num'] = $vendor->getVendorNum();
  63. $entry['name'] = $vendor->getVendorName();
  64. $entry['address1'] = '';
  65. $result->append($entry);
  66. $processedVendors[$vendorName] = TRUE;
  67. });
  68. return $result;
  69. }
  70. public function buildColorCodes()
  71. {
  72. /* @var CodeGeneratorInterface $codeGenerator */
  73. $codeGenerator = $this->getCodeGenerator();
  74. $result = new ArrayObject();
  75. $processedColors = new ArrayObject();
  76. $host = $this;
  77. $this->iterateVariants(
  78. $this->getItems(),
  79. function($parentProduct, $variant) use (
  80. $codeGenerator,
  81. $result,
  82. $processedColors,
  83. $host
  84. ) {
  85. $colorDesc = $host->normalizeDescriptionText($variant->{self::COLOR_CODE_FIELD});
  86. if (isset($processedColors[$colorDesc])) {
  87. return;
  88. }
  89. $itemColorCode = ItemColorCdPeer::findByDivisionAndColorDesc($host->getDivision(), $colorDesc);
  90. if (is_null($itemColorCode)) {
  91. $colorCode = ($codeGenerator->generateCode(
  92. $colorDesc,
  93. ['namespace' => $host->getDivision() . '_color_code']
  94. ));
  95. $colorCode = strtoupper(str_pad($colorCode, 4, '0', STR_PAD_LEFT));
  96. $itemColorCode = new ItemColorCd();
  97. $itemColorCode->setColorCd($colorCode);
  98. $itemColorCode->setDivision($host->getDivision());
  99. $itemColorCode->setColorDesc($colorDesc);
  100. $itemColorCode->setDisplaySeq(0);
  101. $itemColorCode->setCreatedAt('Now');
  102. $itemColorCode->save();
  103. if (isset($this->output)) {
  104. $this->output->writeln('Processing color "' . $variant->{self::COLOR_CODE_FIELD}
  105. . '" => "' . $itemColorCode->getColorDesc() . '" / ' . $itemColorCode->getColorCd(),
  106. HitchCommandBase::STYLE_INFO);
  107. }
  108. } else {
  109. if (isset($this->output)) {
  110. $this->output->writeln('Loading color "' . $variant->{self::COLOR_CODE_FIELD}
  111. . '" => "' . $itemColorCode->getColorDesc() . '" / ' . $itemColorCode->getColorCd(),
  112. HitchCommandBase::STYLE_INFO);
  113. }
  114. }
  115. $entry = new ArrayObject();
  116. $entry['position'] = 0;
  117. $entry['code'] = $itemColorCode->getColorCd();
  118. $entry['desc'] = $colorDesc;
  119. $result->append($entry);
  120. $processedColors[$colorDesc] = TRUE;
  121. });
  122. return $result;
  123. }
  124. public function buildSizeCodes()
  125. {
  126. /* @var CodeGeneratorInterface $codeGenerator */
  127. $codeGenerator = $this->getCodeGenerator();
  128. $result = new ArrayObject();
  129. $processedSizes = new ArrayObject();
  130. $host = $this;
  131. $this->iterateVariants(
  132. $this->getItems(),
  133. function($parentProduct, $variant) use (
  134. $codeGenerator,
  135. $result,
  136. $processedSizes,
  137. $host
  138. ) {
  139. $sizeDesc = $host->normalizeDescriptionText($variant->{self::SIZE_CODE_FIELD});
  140. if (isset($processedSizes[$sizeDesc])) {
  141. return;
  142. }
  143. $itemSizeCode = ItemSizeCdPeer::findByDivisionAndSizeDesc($this->getDivision(), $sizeDesc);
  144. if (is_null($itemSizeCode)) {
  145. $sizeCode = ($codeGenerator->generateCode(
  146. $sizeDesc,
  147. ['namespace' => $host->getDivision() . '_size_code']
  148. ));
  149. $sizeCode = strtoupper(str_pad($sizeCode, 4, '0', STR_PAD_LEFT));
  150. $itemSizeCode = new ItemSizeCd();
  151. $itemSizeCode->setSizeCd($sizeCode);
  152. $itemSizeCode->setDivision($this->getDivision());
  153. $itemSizeCode->setSizeDesc($sizeDesc);
  154. $itemSizeCode->setDisplaySeq(0);
  155. $itemSizeCode->setCreatedAt('Now');
  156. $itemSizeCode->save();
  157. if (isset($this->output)) {
  158. $this->output->writeln('Processing size "' . $variant->{self::SIZE_CODE_FIELD}
  159. . '" => "' . $itemSizeCode->getSizeDesc() . '" / ' . $itemSizeCode->getSizeCd(),
  160. HitchCommandBase::STYLE_INFO);
  161. }
  162. } else {
  163. if (isset($this->output)) {
  164. $this->output->writeln('Loading size "' . $variant->{self::SIZE_CODE_FIELD}
  165. . '" => "' . $itemSizeCode->getSizeDesc() . '" / ' . $itemSizeCode->getSizeCd(),
  166. HitchCommandBase::STYLE_INFO);
  167. }
  168. }
  169. $entry['position'] = 0;
  170. $entry['code'] = $itemSizeCode->getSizeCd();
  171. $entry['desc'] = $sizeDesc;
  172. $result->append($entry);
  173. $processedSizes[$sizeDesc] = TRUE;
  174. });
  175. return $result;
  176. }
  177. public function processItems($vendors, $colorCodes, $sizeCodes)
  178. {
  179. $result = new ArrayObject();
  180. $colorsByDesc = $this->indexArrayBy($colorCodes, 'desc');
  181. $sizesByDesc = $this->indexArrayBy($sizeCodes, 'desc');
  182. $vendorsByName = $this->indexArrayBy($vendors, 'name');
  183. $host = $this;
  184. $totalProcessed = 0;
  185. $this->iterateVariants(
  186. $this->getItems(),
  187. function($parentProduct, $variant) use (
  188. $result,
  189. $colorsByDesc,
  190. $sizesByDesc,
  191. $vendorsByName,
  192. $host,
  193. &$totalProcessed
  194. ) {
  195. if (isset($this->output)) {
  196. $this->output->writeln('Processing variant "' . $variant->id . '" / product "'
  197. . $parentProduct->id . '" ...', HitchCommandBase::STYLE_INFO);
  198. }
  199. $resultCount = count($result);
  200. if ($resultCount == 0 || $result[$resultCount - 1]['num'] != $parentProduct->id) {
  201. $lastItem = new ArrayObject();
  202. $lastItem['num'] = $parentProduct->id;
  203. $lastItem['desc'] = $parentProduct->title;
  204. $lastItem['unitWeight'] = $variant->weight;
  205. $lastItem['skus'] = new ArrayObject();
  206. $result[] = $lastItem;
  207. } else {
  208. $lastItem = $result[$resultCount - 1];
  209. }
  210. $colorDesc = $host->normalizeDescriptionText($variant->{self::COLOR_CODE_FIELD});
  211. $colorCode = $colorsByDesc[$colorDesc]['code'];
  212. $sizeDesc = $this->normalizeDescriptionText($variant->{self::SIZE_CODE_FIELD});
  213. $sizeCode = $sizesByDesc[$sizeDesc]['code'];
  214. $vendorName = $this->normalizeDescriptionText($parentProduct->vendor);
  215. $vendorNum = $vendorsByName[$vendorName]['num'];
  216. $sku = new ArrayObject();
  217. $sku['colorCode'] = $colorCode;
  218. $sku['sizeCode'] = $sizeCode;
  219. $sku['status'] = 'ACTIVE';
  220. $sku['retailPrice'] = $variant->price;
  221. $sku['originalPrice'] = $variant->price;
  222. $sku['cost'] = 0.0;
  223. $sku['skucode'] = $host->filterSkucode($variant->sku);
  224. $sku['barcode'] = $variant->barcode;
  225. $sku['itemDesc'] = $parentProduct->title;
  226. $sku['vendorNum'] = $vendorNum;
  227. $lastItem['skus']->append($sku);
  228. $totalProcessed++;
  229. });
  230. if (isset($this->output)) {
  231. $this->output->writeln('Loaded ' . count($this->getItems()) . ' items from the database.');
  232. $this->output->writeln('Written ' . count($result) . ' items.');
  233. $this->output->writeln("A total of $totalProcessed variants were processed.",
  234. HitchCommandBase::STYLE_INFO);
  235. }
  236. return $result;
  237. }
  238. public function validateFeedDataModel($model)
  239. {
  240. $barcodes = [];
  241. foreach ($model['items'] as $item) {
  242. foreach ($item['skus'] as $sku) {
  243. if (is_null($sku['barcode']) || $sku['barcode'] == '') {
  244. throw new Exception("SKU " . print_r($sku, TRUE) . " doesn't have a valid barcode.");
  245. }
  246. if (isset($barcodes[$sku['barcode']])) {
  247. throw new Exception("SKU " . print_r($sku, TRUE) . " doesn't have a unique barcode.");
  248. } else {
  249. $barcodes[$sku['barcode']] = TRUE;
  250. }
  251. }
  252. }
  253. }
  254. private function indexArrayBy($arr, $byKey) {
  255. $result = new ArrayObject();
  256. foreach ($arr as $elem) {
  257. $result[$elem[$byKey]] = $elem;
  258. }
  259. return $result;
  260. }
  261. }