Catalog.php 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322
  1. <?php
  2. namespace Dotdigitalgroup\Email\Model\Sync;
  3. /**
  4. * Sync account TD for catalog.
  5. */
  6. class Catalog
  7. {
  8. /**
  9. * @var \Dotdigitalgroup\Email\Helper\Data
  10. */
  11. private $helper;
  12. /**
  13. * @var \Magento\Framework\App\Config\ScopeConfigInterface
  14. */
  15. private $scopeConfig;
  16. /**
  17. * @var mixed
  18. */
  19. private $start;
  20. /**
  21. * @var int
  22. */
  23. private $countProducts = 0;
  24. /**
  25. * @var array
  26. */
  27. private $productIds = [];
  28. /**
  29. * @var \Dotdigitalgroup\Email\Model\ImporterFactory
  30. */
  31. private $importerFactory;
  32. /**
  33. * @var \Dotdigitalgroup\Email\Model\Connector\ProductFactory
  34. */
  35. private $connectorProductFactory;
  36. /**
  37. * @var \Dotdigitalgroup\Email\Model\ResourceModel\Catalog\CollectionFactory
  38. */
  39. private $catalogCollectionFactory;
  40. /**
  41. * @var \Dotdigitalgroup\Email\Model\ResourceModel\CatalogFactory
  42. */
  43. public $catalogResourceFactory;
  44. /**
  45. * Catalog constructor.
  46. *
  47. * @param \Dotdigitalgroup\Email\Model\ResourceModel\Catalog\CollectionFactory $catalogCollection
  48. * @param \Dotdigitalgroup\Email\Model\Connector\ProductFactory $connectorProductFactory
  49. * @param \Dotdigitalgroup\Email\Model\ImporterFactory $importerFactory
  50. * @param \Dotdigitalgroup\Email\Helper\Data $helper
  51. * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
  52. * @param \Dotdigitalgroup\Email\Model\ResourceModel\CatalogFactory $catalogResourceFactory
  53. */
  54. public function __construct(
  55. \Dotdigitalgroup\Email\Model\ResourceModel\Catalog\CollectionFactory $catalogCollection,
  56. \Dotdigitalgroup\Email\Model\Connector\ProductFactory $connectorProductFactory,
  57. \Dotdigitalgroup\Email\Model\ImporterFactory $importerFactory,
  58. \Dotdigitalgroup\Email\Helper\Data $helper,
  59. \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
  60. \Dotdigitalgroup\Email\Model\ResourceModel\CatalogFactory $catalogResourceFactory
  61. ) {
  62. $this->catalogCollectionFactory = $catalogCollection;
  63. $this->connectorProductFactory = $connectorProductFactory;
  64. $this->importerFactory = $importerFactory;
  65. $this->helper = $helper;
  66. $this->scopeConfig = $scopeConfig;
  67. $this->catalogResourceFactory = $catalogResourceFactory;
  68. }
  69. /**
  70. * Catalog sync.
  71. *
  72. * @return array
  73. */
  74. public function sync()
  75. {
  76. $response = ['success' => true, 'message' => 'Done.'];
  77. $this->start = microtime(true);
  78. $enabled = $this->helper->isEnabled();
  79. $catalogSyncEnabled = $this->helper->isCatalogSyncEnabled();
  80. //api and catalog sync enabled
  81. if ($enabled && $catalogSyncEnabled) {
  82. $this->syncCatalog();
  83. }
  84. if ($this->countProducts) {
  85. $message = '----------- Catalog sync ----------- : ' .
  86. gmdate('H:i:s', microtime(true) - $this->start) .
  87. ', Total synced = ' . $this->countProducts;
  88. $this->helper->log($message);
  89. $response['message'] = $message;
  90. }
  91. return $response;
  92. }
  93. /**
  94. * Export catalog.
  95. *
  96. * @param int $storeId
  97. *
  98. * @return array|bool
  99. */
  100. public function exportCatalog($storeId)
  101. {
  102. $connectorProducts = [];
  103. //all products for export
  104. $products = $this->getProductsToExport($storeId);
  105. //get products id's
  106. try {
  107. if ($products) {
  108. $this->productIds = array_merge($this->productIds, $products->getColumnValues('entity_id'));
  109. foreach ($products as $product) {
  110. $product->setStoreId($storeId);
  111. $connProduct = $this->connectorProductFactory->create()
  112. ->setProduct($product);
  113. $connectorProducts[] = $connProduct->expose();
  114. }
  115. }
  116. } catch (\Exception $e) {
  117. $this->helper->debug((string)$e, []);
  118. }
  119. return $connectorProducts;
  120. }
  121. /**
  122. * Export in single.
  123. *
  124. * @param int $storeId
  125. * @param string $collectionName
  126. * @param int $websiteId
  127. *
  128. * @return null
  129. */
  130. public function exportInSingle($storeId, $collectionName, $websiteId)
  131. {
  132. $productIds = [];
  133. $products = $this->getProductsToExport($storeId, true);
  134. if (! empty($products)) {
  135. foreach ($products as $product) {
  136. $connectorProduct = $this->connectorProductFactory->create();
  137. $product->setStoreId($storeId);
  138. $connectorProduct->setProduct($product);
  139. $this->helper->log(
  140. '---------- Start catalog single sync ----------'
  141. );
  142. //register in queue with importer
  143. $check = $this->importerFactory->create()
  144. ->registerQueue(
  145. $collectionName,
  146. $connectorProduct->expose(),
  147. \Dotdigitalgroup\Email\Model\Importer::MODE_SINGLE,
  148. $websiteId
  149. );
  150. if ($check) {
  151. $productIds[] = $product->getId();
  152. } else {
  153. $pid = $product->getId();
  154. $msg = "Failed to register with IMPORTER. Type(Catalog) / Scope(Single) / Product Ids($pid)";
  155. $this->helper->log($msg);
  156. }
  157. }
  158. }
  159. if (! empty($productIds)) {
  160. $this->setImported($productIds, true);
  161. $this->countProducts += count($productIds);
  162. }
  163. }
  164. /**
  165. * Get product collection to export.
  166. *
  167. * @param \Magento\Store\Model\Store|int $store
  168. * @param bool $modified
  169. *
  170. * @return mixed
  171. */
  172. public function getProductsToExport($store, $modified = false)
  173. {
  174. $limit = $this->helper->getWebsiteConfig(
  175. \Dotdigitalgroup\Email\Helper\Config::XML_PATH_CONNECTOR_TRANSACTIONAL_DATA_SYNC_LIMIT
  176. );
  177. return $this->catalogCollectionFactory->create()
  178. ->getProductsToExportByStore($store, $limit, $modified);
  179. }
  180. /**
  181. * Set imported in bulk query. If modified true then set modified to null in bulk query.
  182. *
  183. * @param array $ids
  184. * @param bool $modified
  185. *
  186. * @return null
  187. */
  188. public function setImported($ids, $modified = false)
  189. {
  190. $this->catalogResourceFactory->create()
  191. ->setImportedByIds($ids, $modified);
  192. }
  193. /**
  194. * @return null
  195. */
  196. public function syncCatalog()
  197. {
  198. try {
  199. //remove product with product id set and no product
  200. $this->catalogResourceFactory->create()
  201. ->removeOrphanProducts();
  202. $scope = $this->scopeConfig->getValue(
  203. \Dotdigitalgroup\Email\Helper\Config::XML_PATH_CONNECTOR_SYNC_CATALOG_VALUES
  204. );
  205. if ($scope == 1) {
  206. $this->batchDefaultLevelValues();
  207. } elseif ($scope == 2) {
  208. $this->batchStoreLevelValues();
  209. }
  210. } catch (\Exception $e) {
  211. $this->helper->debug((string)$e, []);
  212. }
  213. }
  214. /**
  215. * Batch default level values for catalog
  216. */
  217. private function batchDefaultLevelValues()
  218. {
  219. $products = $this->exportCatalog(\Magento\Store\Model\Store::DEFAULT_STORE_ID);
  220. if (! empty($products)) {
  221. //register in queue with importer
  222. $check = $this->importerFactory->create()
  223. ->registerQueue(
  224. 'Catalog_Default',
  225. $products,
  226. \Dotdigitalgroup\Email\Model\Importer::MODE_BULK,
  227. \Magento\Store\Model\Store::DEFAULT_STORE_ID
  228. );
  229. if ($check) {
  230. //set imported
  231. $this->setImported($this->productIds);
  232. //set number of product imported
  233. $this->countProducts += count($products);
  234. } else {
  235. $pid = implode(",", $this->productIds);
  236. $msg = "Failed to register with IMPORTER. Type(Catalog) / Scope(Bulk) / Product Ids($pid)";
  237. $this->helper->log($msg);
  238. }
  239. }
  240. //using single api
  241. $this->exportInSingle(
  242. \Magento\Store\Model\Store::DEFAULT_STORE_ID,
  243. 'Catalog_Default',
  244. \Magento\Store\Model\Store::DEFAULT_STORE_ID
  245. );
  246. }
  247. /**
  248. * Batch store level values for catalog
  249. */
  250. private function batchStoreLevelValues()
  251. {
  252. $stores = $this->helper->getStores();
  253. foreach ($stores as $store) {
  254. $websiteCode = $store->getWebsite()->getCode();
  255. $storeCode = $store->getCode();
  256. $products = $this->exportCatalog($store->getId());
  257. if (! empty($products)) {
  258. //register in queue with importer
  259. $check = $this->importerFactory->create()
  260. ->registerQueue(
  261. 'Catalog_' . $websiteCode . '_'
  262. . $storeCode,
  263. $products,
  264. \Dotdigitalgroup\Email\Model\Importer::MODE_BULK,
  265. $store->getWebsiteId()
  266. );
  267. if (! $check) {
  268. $pid = implode(",", $this->productIds);
  269. $msg = "Failed to register with IMPORTER. Type(Catalog) / Scope(Bulk) / Store($store)
  270. / Product Ids($pid)";
  271. $this->helper->log($msg);
  272. }
  273. }
  274. //using single api
  275. $this->exportInSingle(
  276. $store->getId(),
  277. 'Catalog_' . $websiteCode . '_' . $storeCode,
  278. $store->getWebsiteId()
  279. );
  280. }
  281. if (! empty($this->productIds)) {
  282. //set imported
  283. $this->setImported(array_unique($this->productIds));
  284. //set number of product imported
  285. $this->countProducts += count($this->productIds);
  286. }
  287. }
  288. }