From 5aba402ed79b5c7c6f97a8c8690e2f3282bf342d Mon Sep 17 00:00:00 2001 From: jordan allain Date: Mon, 8 Nov 2021 18:02:43 -0500 Subject: [PATCH 01/15] Adds product/save to message queue - Adds a getWebhooks method/endpoint to the Reclaim interface for querying the customizable webhooks. - Adds the observer that runs when a product is saved. - Adds the Cron class for managing product data that needs to be synced to Klaviyo. - Admin HTML for configuring the webhook. - Modify the webhook helper so we only encode the json once. --- Api/ReclaimInterface.php | 8 ++ Cron/ProductsTopic.php | 96 ++++++++++++++++++++++ Helper/ScopeSetting.php | 24 +++++- Helper/Webhook.php | 18 ++-- Model/Reclaim.php | 5 ++ Observer/ProductSaveAfter.php | 150 ++++++++++++++++++++++++++++++++++ etc/adminhtml/events.xml | 3 + etc/adminhtml/system.xml | 5 ++ etc/crontab.xml | 6 ++ etc/webapi.xml | 6 ++ 10 files changed, 308 insertions(+), 13 deletions(-) create mode 100644 Cron/ProductsTopic.php create mode 100644 Observer/ProductSaveAfter.php diff --git a/Api/ReclaimInterface.php b/Api/ReclaimInterface.php index 6bbca469..aeba458d 100644 --- a/Api/ReclaimInterface.php +++ b/Api/ReclaimInterface.php @@ -27,6 +27,14 @@ public function reclaim(); */ public function getWebhookSecret(); + /** + * Returns the registered webhooks + * + * @return mixed[] + * @api + */ + public function getWebhooks(); + /** * Returns the Klaviyo log file * diff --git a/Cron/ProductsTopic.php b/Cron/ProductsTopic.php new file mode 100644 index 00000000..f44d17dc --- /dev/null +++ b/Cron/ProductsTopic.php @@ -0,0 +1,96 @@ +_klaviyoLogger = $klaviyoLogger; + $this->_klProduct = $klProduct; + $this->_klSyncFactory = $klSyncFactory; + $this->_klProductCollectionFactory = $klProductCollectionFactory; + } + + public function queueKlProductsForSync() + { + $klProductsCollection = $this->_klProductCollectionFactory->create(); + $klProductsToSync = $klProductsCollection->getRowsForSync('NEW') + ->addFieldToSelect(['id','payload','status','topic', 'klaviyo_id']) + ->getData(); + + if (empty($klProductsToSync)) + { + return; + } + + $idsToUpdate = []; + + foreach ($klProductsToSync as $klProductToSync) + { + $klSync = $this->_klSyncFactory->create(); + $klSync->setData([ + 'payload'=> $klProductToSync['payload'], + 'topic'=> $klProductToSync['topic'], + 'klaviyo_id'=>$klProductToSync['klaviyo_id'], + 'status'=> 'NEW' + ]); + try { + $klSync->save(); + array_push($idsToUpdate, $klProductToSync['id']); + } catch (\Exception $e) { + $this->_klaviyoLogger->log(sprintf('Unable to move row: %s', $e)); + } + } + + $klProductsCollection->updateRowStatus($idsToUpdate, 'MOVED'); + } + + public function clean() + { + $klProductsCollection = $this->_klProductCollectionFactory->create(); + $idsToDelete = $klProductsCollection->getIdsToDelete('MOVED'); + + $klProductsCollection->deleteRows($idsToDelete); + } +} diff --git a/Helper/ScopeSetting.php b/Helper/ScopeSetting.php index 61c8b991..b6de7ed6 100755 --- a/Helper/ScopeSetting.php +++ b/Helper/ScopeSetting.php @@ -30,7 +30,8 @@ class ScopeSetting extends \Magento\Framework\App\Helper\AbstractHelper const WEBHOOK_SECRET = 'klaviyo_reclaim_webhook/klaviyo_webhooks/webhook_secret'; const PRODUCT_DELETE_BEFORE = 'klaviyo_reclaim_webhook/klaviyo_webhooks/using_product_delete_before_webhook'; - + const PRODUCT_SAVE_AFTER = 'klaviyo_reclaim_webhook/klaviyo_webhooks/using_product_save_after_webhook'; + const KLAVIYO_OAUTH_NAME = 'klaviyo_reclaim_oauth/klaviyo_oauth/integration_name'; protected $_scopeConfig; @@ -143,6 +144,19 @@ public function getWebhookSecret($storeId = null) return $this->getScopeSetting(self::WEBHOOK_SECRET, $storeId); } + public function getWebhooks() + { + $registeredWebhooks = []; + + $product_delete = $this->getProductDeleteBeforeSetting(); + $product_save = $this->getProductSaveAfterSetting(); + + array_push($registeredWebhooks, ['product/delete', $product_delete)]; + array_push($registeredWebhooks, ['product/save', $product_save]); + + return $registeredWebhooks; + } + public function isEnabled($storeId = null) { return $this->getScopeSetting(self::ENABLE, $storeId); @@ -221,7 +235,7 @@ public function getConsentAtCheckoutSMSListId($storeId = null) { return $this->getScopeSetting(self::CONSENT_AT_CHECKOUT_SMS_LIST_ID, $storeId); } - + public function getConsentAtCheckoutSMSConsentText($storeId = null) { return $this->getScopeSetting(self::CONSENT_AT_CHECKOUT_SMS_CONSENT_TEXT, $storeId); @@ -264,5 +278,9 @@ public function getProductDeleteBeforeSetting($storeId = null) return $this->getScopeSetting(self::PRODUCT_DELETE_BEFORE, $storeId); } -} + public function getProductSaveAfterSetting($storeId = null) + { + return $this->getScopeSetting(self::PRODUCT_SAVE_AFTER, $storeId); + } +} diff --git a/Helper/Webhook.php b/Helper/Webhook.php index b4752654..6158d014 100755 --- a/Helper/Webhook.php +++ b/Helper/Webhook.php @@ -33,14 +33,13 @@ public function __construct( /** * @param string $webhookType - * @param array $data + * @param string $data * @param string $klaviyoId * @return string * @throws Exception */ public function makeWebhookRequest($webhookType, $data, $klaviyoId=null) { - if (!$klaviyoId) { $klaviyoId = $this->_klaviyoScopeSetting->getPublicApiKey(); } @@ -51,12 +50,12 @@ public function makeWebhookRequest($webhookType, $data, $klaviyoId=null) CURLOPT_URL => $url, CURLOPT_RETURNTRANSFER => true, CURLOPT_CUSTOMREQUEST => 'POST', - CURLOPT_POSTFIELDS => json_encode($data), + CURLOPT_POSTFIELDS => $data, CURLOPT_USERAGENT => self::USER_AGENT, CURLOPT_HTTPHEADER => array( 'Content-Type: application/json', 'Magento-two-signature: ' . $this->createWebhookSecurity($data), - 'Content-Length: '. strlen(json_encode($data)), + 'Content-Length: '. strlen($data), 'Topic: ' . $webhookType ), ]); @@ -66,24 +65,23 @@ public function makeWebhookRequest($webhookType, $data, $klaviyoId=null) $err = curl_errno($curl); if ($err) { - $this->_klaviyoLogger->log(sprintf('Unable to send webhook to %s with data: %s', $url, json_encode($data))); + $this->_klaviyoLogger->log(sprintf('Unable to send webhook to %s with data: %s', $url, $data)); } // Close cURL session handle curl_close($curl); + return $response; } /** - * @param array data + * @param string data * @return string * @throws Exception */ - private function createWebhookSecurity(array $data) + private function createWebhookSecurity(string $data) { $webhookSecret = $this->_klaviyoScopeSetting->getWebhookSecret(); - return hash_hmac('sha256', json_encode($data), $webhookSecret); - + return hash_hmac('sha256', $data, $webhookSecret); } } - diff --git a/Model/Reclaim.php b/Model/Reclaim.php index bcfa05a3..d87e5b20 100644 --- a/Model/Reclaim.php +++ b/Model/Reclaim.php @@ -73,6 +73,11 @@ public function getWebhookSecret() return $this->_klaviyoScopeSetting->getWebhookSecret(); } + public function getWebhooks() + { + return $this->_klaviyoScopeSetting->getWebhooks(); + } + /** * Returns the Klaviyo log file * diff --git a/Observer/ProductSaveAfter.php b/Observer/ProductSaveAfter.php new file mode 100644 index 00000000..de33e3ba --- /dev/null +++ b/Observer/ProductSaveAfter.php @@ -0,0 +1,150 @@ +_webhookHelper = $webhookHelper; + $this->_klaviyoScopeSetting = $klaviyoScopeSetting; + $this->_categoryFactory = $categoryFactory; + $this->_klProductFactory = $klProductFactory; + $this->_klaviyoLogger = $klaviyoLogger; + $this->_stockRegistry = $stockRegistry; + } + + /** + * customer register event handler + * + * @param Observer $observer + * @return void + * @throws Exception + */ + public function execute(Observer $observer) + { + $product = $observer->getEvent()->getProduct(); + $storeIds = $product->getStoreIds(); + $storeIdKlaviyoMap = $this->_klaviyoScopeSetting->getStoreIdKlaviyoAccountSetMap($storeIds); + + foreach ($storeIdKlaviyoMap as $klaviyoId => $storeIds) { + if (empty($storeIds)) { + continue; + } + + if ($this->_klaviyoScopeSetting->getWebhookSecret() && $this->_klaviyoScopeSetting->getProductSaveAfterSetting($storeIds[0])) { + + $normalizedProduct = $this->normalizeProduct($product); + $data = [ + "status"=>"NEW", + "topic"=>"product/save", + "klaviyo_id"=>$klaviyoId, + "payload"=>json_encode($normalizedProduct) + ]; + $klProduct = $this->_klProductFactory->create(); + $klProduct->setData($data); + $klProduct->save(); + + // $this->_klaviyoLogger->log( print_r("Created new row?", true)); + + // $this->_webhookHelper->makeWebhookRequest('product/save', $normalizedProduct, $klaviyoId); + } + } + } + + private function normalizeProduct($product=null) + { + if ($product == null) { + return; + } + + $product_id = $product->getId(); + + // remove thumnbail image url? + + $product_info = array( + 'product' => array( + 'store_ids' => $product->getStoreIds(), + 'ID' => $product_id, + 'TypeID' => $product->getTypeId(), + 'Name' => $product->getName(), + 'qty' => $this->_stockRegistry->getStockItem($product_id)->getQty(), + 'Visibility' => $product->getVisibility(), + 'IsInStock' => $product->isInStock(), + 'Status' => $product->getStatus(), + 'CreatedAt' => $product->getCreatedAt(), + 'UpdatedAt' => $product->getUpdatedAt(), + 'FirstImageURL' => $product->getImage(), + 'ThumbnailImageURL' => $product->getThumbnail(), + 'metadata' => array( + 'price' => $product->getPrice(), + 'sku' => $product->getSku() + ), + 'categories' => [] + ) + ); + + if ($product->getSpecialPrice()) { + $product_info['metadata']['special_price'] = $product->getSpecialPrice(); + $product_info['metadata']['special_from_date'] = $product->getSpecialFromDate(); + $product_info['metadata']['special_to_date'] = $product->getSpecialToDate(); + } + + $product_category_ids = $product->getCategoryIds(); + $category_factory = $this->_categoryFactory->create(); + foreach ($product_category_ids as $category_id) { + $category = $category_factory->load($category_id); + $product_info['categories'][$category_id] = $category->getName(); + } + + return $product_info; + } +} diff --git a/etc/adminhtml/events.xml b/etc/adminhtml/events.xml index 1dc26010..c454f9d9 100644 --- a/etc/adminhtml/events.xml +++ b/etc/adminhtml/events.xml @@ -5,6 +5,9 @@ + + + diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index 1f1a02b9..faeb629a 100755 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -158,6 +158,11 @@ Magento\Config\Model\Config\Source\Yesno This will remove deleted products from the Klaviyo catalog. + + + Magento\Config\Model\Config\Source\Yesno + This will update or create saved products in the Klaviyo catalog. + diff --git a/etc/crontab.xml b/etc/crontab.xml index 0ce9711d..154bb971 100644 --- a/etc/crontab.xml +++ b/etc/crontab.xml @@ -16,5 +16,11 @@ 59 23 * * * + + */5 * * * * + + + 59 23 * * * + diff --git a/etc/webapi.xml b/etc/webapi.xml index b40b57c6..f1012d1a 100644 --- a/etc/webapi.xml +++ b/etc/webapi.xml @@ -54,6 +54,12 @@ + + + + + + From ff657f60683eb2603a0b14242ee375b9e3ac3cd5 Mon Sep 17 00:00:00 2001 From: jordan allain Date: Tue, 9 Nov 2021 13:25:37 -0500 Subject: [PATCH 02/15] Remove comments - Remove some comments. - Reduce if statements to a single line. --- Observer/ProductSaveAfter.php | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/Observer/ProductSaveAfter.php b/Observer/ProductSaveAfter.php index de33e3ba..c6ddb7d9 100644 --- a/Observer/ProductSaveAfter.php +++ b/Observer/ProductSaveAfter.php @@ -76,12 +76,9 @@ public function execute(Observer $observer) $storeIdKlaviyoMap = $this->_klaviyoScopeSetting->getStoreIdKlaviyoAccountSetMap($storeIds); foreach ($storeIdKlaviyoMap as $klaviyoId => $storeIds) { - if (empty($storeIds)) { - continue; - } + if (empty($storeIds)) {continue;} if ($this->_klaviyoScopeSetting->getWebhookSecret() && $this->_klaviyoScopeSetting->getProductSaveAfterSetting($storeIds[0])) { - $normalizedProduct = $this->normalizeProduct($product); $data = [ "status"=>"NEW", @@ -92,24 +89,16 @@ public function execute(Observer $observer) $klProduct = $this->_klProductFactory->create(); $klProduct->setData($data); $klProduct->save(); - - // $this->_klaviyoLogger->log( print_r("Created new row?", true)); - - // $this->_webhookHelper->makeWebhookRequest('product/save', $normalizedProduct, $klaviyoId); } } } private function normalizeProduct($product=null) { - if ($product == null) { - return; - } + if ($product == null) {return;} $product_id = $product->getId(); - // remove thumnbail image url? - $product_info = array( 'product' => array( 'store_ids' => $product->getStoreIds(), From b60705e0825df807b505442f8ed1c3e7e2b9b7b0 Mon Sep 17 00:00:00 2001 From: jordan allain Date: Tue, 9 Nov 2021 13:28:34 -0500 Subject: [PATCH 03/15] Reduce conditional to single line --- Cron/ProductsTopic.php | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Cron/ProductsTopic.php b/Cron/ProductsTopic.php index f44d17dc..af5c6cc3 100644 --- a/Cron/ProductsTopic.php +++ b/Cron/ProductsTopic.php @@ -59,10 +59,7 @@ public function queueKlProductsForSync() ->addFieldToSelect(['id','payload','status','topic', 'klaviyo_id']) ->getData(); - if (empty($klProductsToSync)) - { - return; - } + if (empty($klProductsToSync)){return;} $idsToUpdate = []; From a140aa62f2bc1ce1e3bcb50cdaccd240a945f9d2 Mon Sep 17 00:00:00 2001 From: jordan allain Date: Tue, 9 Nov 2021 13:32:35 -0500 Subject: [PATCH 04/15] Whitespace --- Cron/ProductsTopic.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cron/ProductsTopic.php b/Cron/ProductsTopic.php index af5c6cc3..3d3ec94e 100644 --- a/Cron/ProductsTopic.php +++ b/Cron/ProductsTopic.php @@ -59,7 +59,7 @@ public function queueKlProductsForSync() ->addFieldToSelect(['id','payload','status','topic', 'klaviyo_id']) ->getData(); - if (empty($klProductsToSync)){return;} + if (empty($klProductsToSync)) {return;} $idsToUpdate = []; From 43c53eea2e287eff6490b30e9ce3c8ae073effff Mon Sep 17 00:00:00 2001 From: jordan allain Date: Tue, 9 Nov 2021 14:01:37 -0500 Subject: [PATCH 05/15] Use json_encode for makeWebhookRequest's second argument --- Observer/ProductDeleteBefore.php | 2 +- Observer/SaveOrderMarketingConsent.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Observer/ProductDeleteBefore.php b/Observer/ProductDeleteBefore.php index 9f25d597..82a2190c 100644 --- a/Observer/ProductDeleteBefore.php +++ b/Observer/ProductDeleteBefore.php @@ -67,7 +67,7 @@ public function execute(Observer $observer) 'store_ids' => $storeIds, 'product_id' => $product->getId(), ); - $this->_webhookHelper->makeWebhookRequest('product/delete', $data, $klaviyoId); + $this->_webhookHelper->makeWebhookRequest('product/delete', json_encode($data), $klaviyoId); } } } diff --git a/Observer/SaveOrderMarketingConsent.php b/Observer/SaveOrderMarketingConsent.php index 7fa0be2c..297062f3 100644 --- a/Observer/SaveOrderMarketingConsent.php +++ b/Observer/SaveOrderMarketingConsent.php @@ -92,7 +92,7 @@ public function execute(Observer $observer) } if (count($data["data"]) > 0) { - $this->_webhookHelper->makeWebhookRequest('custom/consent', $data); + $this->_webhookHelper->makeWebhookRequest('custom/consent', json_encode($data)); } return $this; From 905c644345c2e679b2de4c07c677cbfbf7c9fcd7 Mon Sep 17 00:00:00 2001 From: jordan allain Date: Tue, 9 Nov 2021 14:13:41 -0500 Subject: [PATCH 06/15] Fix order of paren and bracket --- Helper/ScopeSetting.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Helper/ScopeSetting.php b/Helper/ScopeSetting.php index b6de7ed6..73d93e94 100755 --- a/Helper/ScopeSetting.php +++ b/Helper/ScopeSetting.php @@ -151,7 +151,7 @@ public function getWebhooks() $product_delete = $this->getProductDeleteBeforeSetting(); $product_save = $this->getProductSaveAfterSetting(); - array_push($registeredWebhooks, ['product/delete', $product_delete)]; + array_push($registeredWebhooks, ['product/delete', $product_delete]); array_push($registeredWebhooks, ['product/save', $product_save]); return $registeredWebhooks; From 682cc17259da77c05c0364f7dc4cdbe180f67d04 Mon Sep 17 00:00:00 2001 From: jordan allain Date: Tue, 9 Nov 2021 23:45:29 -0500 Subject: [PATCH 07/15] Restructure product/save payload - Move store_ids to top level property. --- Observer/ProductSaveAfter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Observer/ProductSaveAfter.php b/Observer/ProductSaveAfter.php index c6ddb7d9..44c7fea5 100644 --- a/Observer/ProductSaveAfter.php +++ b/Observer/ProductSaveAfter.php @@ -100,8 +100,8 @@ private function normalizeProduct($product=null) $product_id = $product->getId(); $product_info = array( + 'store_ids' => $product->getStoreIds(), 'product' => array( - 'store_ids' => $product->getStoreIds(), 'ID' => $product_id, 'TypeID' => $product->getTypeId(), 'Name' => $product->getName(), From fcfe92b0c01a53f0732610aed9ef2e1855a46c5b Mon Sep 17 00:00:00 2001 From: jordan allain Date: Wed, 10 Nov 2021 00:46:07 -0500 Subject: [PATCH 08/15] Nest categories under product key --- Observer/ProductSaveAfter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Observer/ProductSaveAfter.php b/Observer/ProductSaveAfter.php index 44c7fea5..8cb3d73b 100644 --- a/Observer/ProductSaveAfter.php +++ b/Observer/ProductSaveAfter.php @@ -131,7 +131,7 @@ private function normalizeProduct($product=null) $category_factory = $this->_categoryFactory->create(); foreach ($product_category_ids as $category_id) { $category = $category_factory->load($category_id); - $product_info['categories'][$category_id] = $category->getName(); + $product_info['product']['categories'][$category_id] = $category->getName(); } return $product_info; From b9c26fc175d8d4e9874664f251800fe94c92e6cf Mon Sep 17 00:00:00 2001 From: jordan allain Date: Fri, 12 Nov 2021 17:29:16 -0500 Subject: [PATCH 09/15] Sidd review 1 of 2 --- Cron/ProductsTopic.php | 2 +- Helper/ScopeSetting.php | 25 ++++++++++--------------- Helper/Webhook.php | 4 ++-- Observer/ProductSaveAfter.php | 31 ++++++++++++------------------- etc/adminhtml/system.xml | 4 ++-- 5 files changed, 27 insertions(+), 39 deletions(-) diff --git a/Cron/ProductsTopic.php b/Cron/ProductsTopic.php index 3d3ec94e..5a3e52d3 100644 --- a/Cron/ProductsTopic.php +++ b/Cron/ProductsTopic.php @@ -76,7 +76,7 @@ public function queueKlProductsForSync() $klSync->save(); array_push($idsToUpdate, $klProductToSync['id']); } catch (\Exception $e) { - $this->_klaviyoLogger->log(sprintf('Unable to move row: %s', $e)); + $this->_klaviyoLogger->log(sprintf('Unable to move row: %s', $e->getMessage())); } } diff --git a/Helper/ScopeSetting.php b/Helper/ScopeSetting.php index 73d93e94..602353af 100755 --- a/Helper/ScopeSetting.php +++ b/Helper/ScopeSetting.php @@ -29,8 +29,8 @@ class ScopeSetting extends \Magento\Framework\App\Helper\AbstractHelper const KLAVIYO_NAME_DEFAULT = 'klaviyo'; const WEBHOOK_SECRET = 'klaviyo_reclaim_webhook/klaviyo_webhooks/webhook_secret'; - const PRODUCT_DELETE_BEFORE = 'klaviyo_reclaim_webhook/klaviyo_webhooks/using_product_delete_before_webhook'; - const PRODUCT_SAVE_AFTER = 'klaviyo_reclaim_webhook/klaviyo_webhooks/using_product_save_after_webhook'; + const PRODUCT_DELETE_WEBHOOK = 'klaviyo_reclaim_webhook/klaviyo_webhooks/using_product_delete_webhook'; + const PRODUCT_SAVE_WEBHOOK = 'klaviyo_reclaim_webhook/klaviyo_webhooks/using_product_save_webhook'; const KLAVIYO_OAUTH_NAME = 'klaviyo_reclaim_oauth/klaviyo_oauth/integration_name'; @@ -146,15 +146,10 @@ public function getWebhookSecret($storeId = null) public function getWebhooks() { - $registeredWebhooks = []; - - $product_delete = $this->getProductDeleteBeforeSetting(); - $product_save = $this->getProductSaveAfterSetting(); - - array_push($registeredWebhooks, ['product/delete', $product_delete]); - array_push($registeredWebhooks, ['product/save', $product_save]); - - return $registeredWebhooks; + return $registeredWebhooks = [ + ['product/delete' => $this->getProductDeleteWebhookSetting()], + ['product/save' => $this->getProductSaveWebhookSetting()], + ]; } public function isEnabled($storeId = null) @@ -273,14 +268,14 @@ public function getStoreIdKlaviyoAccountSetMap($storeIds) return $storeMap; } - public function getProductDeleteBeforeSetting($storeId = null) + public function getProductDeleteWebhookSetting($storeId = null) { - return $this->getScopeSetting(self::PRODUCT_DELETE_BEFORE, $storeId); + return $this->getScopeSetting(self::PRODUCT_DELETE_WEBHOOK, $storeId); } - public function getProductSaveAfterSetting($storeId = null) + public function getProductSaveWebhookSetting($storeId = null) { - return $this->getScopeSetting(self::PRODUCT_SAVE_AFTER, $storeId); + return $this->getScopeSetting(self::PRODUCT_SAVE_WEBHOOK, $storeId); } } diff --git a/Helper/Webhook.php b/Helper/Webhook.php index 6158d014..fad9a542 100755 --- a/Helper/Webhook.php +++ b/Helper/Webhook.php @@ -33,7 +33,7 @@ public function __construct( /** * @param string $webhookType - * @param string $data + * @param string $data json payload to be sent in the body of the request * @param string $klaviyoId * @return string * @throws Exception @@ -65,7 +65,7 @@ public function makeWebhookRequest($webhookType, $data, $klaviyoId=null) $err = curl_errno($curl); if ($err) { - $this->_klaviyoLogger->log(sprintf('Unable to send webhook to %s with data: %s', $url, $data)); + $this->_klaviyoLogger->log(sprintf("Unable to send webhook to %s with data: %s", $url, $data)); } // Close cURL session handle diff --git a/Observer/ProductSaveAfter.php b/Observer/ProductSaveAfter.php index 8cb3d73b..5bdca61f 100644 --- a/Observer/ProductSaveAfter.php +++ b/Observer/ProductSaveAfter.php @@ -4,12 +4,9 @@ use Exception; use Klaviyo\Reclaim\Helper\ScopeSetting; -use Klaviyo\Reclaim\Helper\Webhook; -use Klaviyo\Reclaim\Helper\Logger; use Klaviyo\Reclaim\Model\ProductsFactory; use Magento\Catalog\Model\CategoryFactory; -use Magento\Catalog\Model\Product; use Magento\CatalogInventory\Api\StockRegistryInterface; use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; @@ -24,41 +21,38 @@ class ProductSaveAfter implements ObserverInterface protected $_klaviyoScopeSetting; /** - * Klaviyo logger helper - * @var \Klaviyo\Reclaim\Helper\Logger $klaviyoLogger + * Magento product category helper + * @var CategoryFactory $categoryFactory */ - protected $_klaviyoLogger; + protected $_categoryFactory; /** - * @var Webhook $webhookHelper + * Klaviyo product factory + * @var klProductFactory */ - protected $_webhookHelper; - protected $_categoryFactory; protected $_klProductFactory; + + /** + * Magento stock registry api interface + * @var $stockRegistry + */ protected $_stockRegistry; - protected $product_category_names = []; /** - * @param Webhook $webhookHelper * @param ScopeSetting $klaviyoScopeSetting * @param CategoryFactory $categoryFactory * @param ProductsFactory $klProductFactory * @param StockRegistryInterface $stockRegistry - * @param Logger $klaviyoLogger */ public function __construct( - Webhook $webhookHelper, ScopeSetting $klaviyoScopeSetting, CategoryFactory $categoryFactory, ProductsFactory $klProductFactory, - StockRegistryInterface $stockRegistry, - Logger $klaviyoLogger + StockRegistryInterface $stockRegistry ) { - $this->_webhookHelper = $webhookHelper; $this->_klaviyoScopeSetting = $klaviyoScopeSetting; $this->_categoryFactory = $categoryFactory; $this->_klProductFactory = $klProductFactory; - $this->_klaviyoLogger = $klaviyoLogger; $this->_stockRegistry = $stockRegistry; } @@ -86,8 +80,7 @@ public function execute(Observer $observer) "klaviyo_id"=>$klaviyoId, "payload"=>json_encode($normalizedProduct) ]; - $klProduct = $this->_klProductFactory->create(); - $klProduct->setData($data); + $klProduct = $this->_klProductFactory->setData($data); $klProduct->save(); } } diff --git a/etc/adminhtml/system.xml b/etc/adminhtml/system.xml index faeb629a..13995e0f 100755 --- a/etc/adminhtml/system.xml +++ b/etc/adminhtml/system.xml @@ -153,12 +153,12 @@ Magento\Config\Model\Config\Backend\Encrypted - + Magento\Config\Model\Config\Source\Yesno This will remove deleted products from the Klaviyo catalog. - + Magento\Config\Model\Config\Source\Yesno This will update or create saved products in the Klaviyo catalog. From 67d5e2d2151c6ba4ce928855bae7e63caaf51c77 Mon Sep 17 00:00:00 2001 From: jordan allain Date: Mon, 15 Nov 2021 14:54:54 -0500 Subject: [PATCH 10/15] Interpolate with double quotes --- Helper/Webhook.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Helper/Webhook.php b/Helper/Webhook.php index fad9a542..18c85de9 100755 --- a/Helper/Webhook.php +++ b/Helper/Webhook.php @@ -65,7 +65,7 @@ public function makeWebhookRequest($webhookType, $data, $klaviyoId=null) $err = curl_errno($curl); if ($err) { - $this->_klaviyoLogger->log(sprintf("Unable to send webhook to %s with data: %s", $url, $data)); + $this->_klaviyoLogger->log(sprintf("Unable to send webhook to $url with data: $data")); } // Close cURL session handle From d2b1ea99b18c2d8dade035dd086dc7dd5057d551 Mon Sep 17 00:00:00 2001 From: jordan allain Date: Mon, 15 Nov 2021 14:56:22 -0500 Subject: [PATCH 11/15] Move the category name hydration into cron - In the observer we'll just get the cateroy ids. - In the cron job we'll look up the category names based on the ids so this code runs in the background instead of when the user is saving a product. --- Cron/ProductsTopic.php | 30 ++++++++++++++++++++++++++++++ Observer/ProductSaveAfter.php | 32 ++++++++------------------------ 2 files changed, 38 insertions(+), 24 deletions(-) diff --git a/Cron/ProductsTopic.php b/Cron/ProductsTopic.php index 5a3e52d3..ee99047f 100644 --- a/Cron/ProductsTopic.php +++ b/Cron/ProductsTopic.php @@ -7,6 +7,8 @@ use Klaviyo\Reclaim\Model\ResourceModel\Products; use Klaviyo\Reclaim\Model\ResourceModel\Products\CollectionFactory; +use Magento\Catalog\Model\CategoryFactory; + class ProductsTopic { /** @@ -15,6 +17,12 @@ class ProductsTopic */ protected $_klaviyoLogger; + /** + * Magento product category helper + * @var CategoryFactory $categoryFactory + */ + protected $_categoryFactory; + /** * Klaviyo Products Resource Model * @var Products @@ -42,12 +50,14 @@ class ProductsTopic public function __construct( Logger $klaviyoLogger, Products $klProduct, + CategoryFactory $categoryFactory, SyncsFactory $klSyncFactory, CollectionFactory $klProductCollectionFactory ) { $this->_klaviyoLogger = $klaviyoLogger; $this->_klProduct = $klProduct; + $this->_categoryFactory = $categoryFactory; $this->_klSyncFactory = $klSyncFactory; $this->_klProductCollectionFactory = $klProductCollectionFactory; } @@ -65,6 +75,7 @@ public function queueKlProductsForSync() foreach ($klProductsToSync as $klProductToSync) { + $klProductToSync['payload'] = json_encode($this->addCategoryNames($klProductToSync['payload'])); $klSync = $this->_klSyncFactory->create(); $klSync->setData([ 'payload'=> $klProductToSync['payload'], @@ -90,4 +101,23 @@ public function clean() $klProductsCollection->deleteRows($idsToDelete); } + + /** + * Helper function to associate category names with their ids + * @param string $payload + * @return array + */ + public function addCategoryNames(string $payload): array + { + $decoded_payload = json_decode($payload, true); + $category_ids = $decoded_payload['product']['categories']; + if (empty($category_ids)) {return $decoded_payload;} + $decoded_payload['product']['categories'] = []; + $category_factory = $this->_categoryFactory->create(); + foreach ($category_ids as $category_id) { + $category = $category_factory->load($category_id); + $decoded_payload['product']['categories'][$category_id] = $category->getName(); + } + return $decoded_payload; + } } diff --git a/Observer/ProductSaveAfter.php b/Observer/ProductSaveAfter.php index 5bdca61f..1fb6a1ad 100644 --- a/Observer/ProductSaveAfter.php +++ b/Observer/ProductSaveAfter.php @@ -6,7 +6,6 @@ use Klaviyo\Reclaim\Helper\ScopeSetting; use Klaviyo\Reclaim\Model\ProductsFactory; -use Magento\Catalog\Model\CategoryFactory; use Magento\CatalogInventory\Api\StockRegistryInterface; use Magento\Framework\Event\Observer; use Magento\Framework\Event\ObserverInterface; @@ -20,12 +19,6 @@ class ProductSaveAfter implements ObserverInterface */ protected $_klaviyoScopeSetting; - /** - * Magento product category helper - * @var CategoryFactory $categoryFactory - */ - protected $_categoryFactory; - /** * Klaviyo product factory * @var klProductFactory @@ -46,12 +39,10 @@ class ProductSaveAfter implements ObserverInterface */ public function __construct( ScopeSetting $klaviyoScopeSetting, - CategoryFactory $categoryFactory, ProductsFactory $klProductFactory, StockRegistryInterface $stockRegistry ) { $this->_klaviyoScopeSetting = $klaviyoScopeSetting; - $this->_categoryFactory = $categoryFactory; $this->_klProductFactory = $klProductFactory; $this->_stockRegistry = $stockRegistry; } @@ -72,15 +63,16 @@ public function execute(Observer $observer) foreach ($storeIdKlaviyoMap as $klaviyoId => $storeIds) { if (empty($storeIds)) {continue;} - if ($this->_klaviyoScopeSetting->getWebhookSecret() && $this->_klaviyoScopeSetting->getProductSaveAfterSetting($storeIds[0])) { + if ($this->_klaviyoScopeSetting->getWebhookSecret() && $this->_klaviyoScopeSetting->getProductSaveWebhookSetting($storeIds[0])) { $normalizedProduct = $this->normalizeProduct($product); $data = [ - "status"=>"NEW", - "topic"=>"product/save", - "klaviyo_id"=>$klaviyoId, - "payload"=>json_encode($normalizedProduct) + 'status'=>'NEW', + 'topic'=>'product/save', + 'klaviyo_id'=>$klaviyoId, + 'payload'=>json_encode($normalizedProduct) ]; - $klProduct = $this->_klProductFactory->setData($data); + $klProduct = $this->_klProductFactory->create(); + $klProduct->setData($data); $klProduct->save(); } } @@ -110,7 +102,7 @@ private function normalizeProduct($product=null) 'price' => $product->getPrice(), 'sku' => $product->getSku() ), - 'categories' => [] + 'categories' => $product->getCategoryIds() ) ); @@ -119,14 +111,6 @@ private function normalizeProduct($product=null) $product_info['metadata']['special_from_date'] = $product->getSpecialFromDate(); $product_info['metadata']['special_to_date'] = $product->getSpecialToDate(); } - - $product_category_ids = $product->getCategoryIds(); - $category_factory = $this->_categoryFactory->create(); - foreach ($product_category_ids as $category_id) { - $category = $category_factory->load($category_id); - $product_info['product']['categories'][$category_id] = $category->getName(); - } - return $product_info; } } From dae44cbe0823e6ed0bd514061e124412f49dfdc0 Mon Sep 17 00:00:00 2001 From: jordan allain Date: Tue, 16 Nov 2021 15:18:31 -0500 Subject: [PATCH 12/15] Sidd feedback 2 --- Cron/EventsTopic.php | 69 +++------------------- Cron/ProductsTopic.php | 35 +++-------- Helper/CategoryMapper.php | 107 ++++++++++++++++++++++++++++++++++ Helper/Webhook.php | 10 ++-- Observer/ProductSaveAfter.php | 21 ++++--- 5 files changed, 139 insertions(+), 103 deletions(-) create mode 100644 Helper/CategoryMapper.php diff --git a/Cron/EventsTopic.php b/Cron/EventsTopic.php index 0b4546f0..0dce1aca 100644 --- a/Cron/EventsTopic.php +++ b/Cron/EventsTopic.php @@ -2,6 +2,7 @@ namespace Klaviyo\Reclaim\Cron; +use Klaviyo\Reclaim\Helper\CategoryMapper; use Klaviyo\Reclaim\Helper\Logger; use Klaviyo\Reclaim\Model\SyncsFactory; use Klaviyo\Reclaim\Model\Quote\QuoteIdMask; @@ -36,37 +37,31 @@ class EventsTopic protected $_klSyncFactory; /** - * Magento Category Factory - * @var CategoryFactory + * Klaviyo helper for mapping category ids to names + * @var CategoryMapper $categoryMapperactory */ - protected $_categoryFactory; - - /** - * Category Map of ids to names - * @var array - */ - protected $categoryMap = []; - + protected $_categoryMapper; /** * @param Logger $klaviyoLogger * @param CollectionFactory $eventsCollectionFactory * @param SyncsFactory $klSyncFactory * @param QuoteIdMask $quoteIdMaskResource * @param CategoryFactory $categoryFactory + * @param CategoryMapper $categoryMapper */ public function __construct( Logger $klaviyoLogger, CollectionFactory $eventsCollectionFactory, SyncsFactory $klSyncFactory, QuoteIdMask $quoteIdMaskResource, - CategoryFactory $categoryFactory + CategoryMapper $categoryMapper ) { $this->_klaviyoLogger = $klaviyoLogger; $this->_eventsCollectionFactory = $eventsCollectionFactory; $this->_klSyncFactory = $klSyncFactory; $this->_quoteIdMaskResource = $quoteIdMaskResource; - $this->_categoryFactory = $categoryFactory; + $this->_categoryMapper = $categoryMapper; } /** @@ -89,7 +84,7 @@ public function moveRowsToSync() // Capture all events that have been moved and add data to Sync table foreach ($eventsData as $event){ if ($event['event'] == 'Added To Cart') { - $event['payload'] = json_encode($this->replaceQuoteIdAndCategoryIds($event['payload'])); + $event['payload'] = json_encode($this->_categoryMapper->replaceQuoteIdAndCategoryIds($event['payload'])); } //TODO: This can probably be done as one bulk update instead of individual inserts @@ -137,54 +132,8 @@ public function replaceQuoteIdAndCategoryIds(string $payload): array unset($decoded_payload['QuoteId']); // Replace CategoryIds for Added Item, Quote Items with resp. CategoryNames - $decoded_payload = $this->replaceCategoryIdsWithNames($decoded_payload); + $decoded_payload = $this->_categoryMapper->replaceCategoryIdsWithNames($decoded_payload); return $decoded_payload; } - - /** - * Replace all CategoryIds in event payload with their respective names - * @param $payload - * @return array - */ - public function replaceCategoryIdsWithNames(array $payload): array - { - $this->updateCategoryMap($payload['Categories']); - - foreach ($payload['Items'] as &$item){ - $item['Categories'] = $this->searchCategoryMapAndReturnNames($item['Categories']); - } - - $payload['AddedItemCategories'] = $this->searchCategoryMapAndReturnNames($payload['AddedItemCategories']); - $payload['Categories'] = $this->searchCategoryMapAndReturnNames($payload['Categories']); - - return $payload; - } - - /** - * Retrieve categoryNames using categoryIds - * @param array $categoryIds - */ - public function updateCategoryMap(array $categoryIds) - { - $categoryFactory = $this->_categoryFactory->create(); - - foreach($categoryIds as $categoryId){ - if (!in_array($categoryId, $this->categoryMap)){ - $this->categoryMap[$categoryId] = $categoryFactory->load($categoryId)->getName(); - } - } - } - - /** - * Return array of CategoryNames from CategoryMap using ids - * @param array $categoryIds - * @return array - */ - public function searchCategoryMapAndReturnNames(array $categoryIds): array - { - return array_values( - array_intersect_key($this->categoryMap, array_flip($categoryIds)) - ); - } } diff --git a/Cron/ProductsTopic.php b/Cron/ProductsTopic.php index ee99047f..56e41b1c 100644 --- a/Cron/ProductsTopic.php +++ b/Cron/ProductsTopic.php @@ -2,13 +2,12 @@ namespace Klaviyo\Reclaim\Cron; +use Klaviyo\Reclaim\Helper\CategoryMapper; use Klaviyo\Reclaim\Helper\Logger; use Klaviyo\Reclaim\Model\SyncsFactory; use Klaviyo\Reclaim\Model\ResourceModel\Products; use Klaviyo\Reclaim\Model\ResourceModel\Products\CollectionFactory; -use Magento\Catalog\Model\CategoryFactory; - class ProductsTopic { /** @@ -18,10 +17,10 @@ class ProductsTopic protected $_klaviyoLogger; /** - * Magento product category helper - * @var CategoryFactory $categoryFactory + * Klaviyo helper for mapping category ids to names + * @var CategoryMapper $categoryMapperactory */ - protected $_categoryFactory; + protected $_categoryMapper; /** * Klaviyo Products Resource Model @@ -46,18 +45,19 @@ class ProductsTopic * @param Products $klProduct * @param SyncsFactory $klSyncFactory * @param CollectionFactory $klProductCollectionFactory + * @param CategoryMapper $categoryMapper */ public function __construct( Logger $klaviyoLogger, Products $klProduct, - CategoryFactory $categoryFactory, + CategoryMapper $categoryMapper, SyncsFactory $klSyncFactory, CollectionFactory $klProductCollectionFactory ) { $this->_klaviyoLogger = $klaviyoLogger; $this->_klProduct = $klProduct; - $this->_categoryFactory = $categoryFactory; + $this->_categoryMapper = $categoryMapper; $this->_klSyncFactory = $klSyncFactory; $this->_klProductCollectionFactory = $klProductCollectionFactory; } @@ -75,7 +75,7 @@ public function queueKlProductsForSync() foreach ($klProductsToSync as $klProductToSync) { - $klProductToSync['payload'] = json_encode($this->addCategoryNames($klProductToSync['payload'])); + $klProductToSync['payload'] = json_encode($this->_categoryMapper->addCategoryNames($klProductToSync['payload'])); $klSync = $this->_klSyncFactory->create(); $klSync->setData([ 'payload'=> $klProductToSync['payload'], @@ -101,23 +101,4 @@ public function clean() $klProductsCollection->deleteRows($idsToDelete); } - - /** - * Helper function to associate category names with their ids - * @param string $payload - * @return array - */ - public function addCategoryNames(string $payload): array - { - $decoded_payload = json_decode($payload, true); - $category_ids = $decoded_payload['product']['categories']; - if (empty($category_ids)) {return $decoded_payload;} - $decoded_payload['product']['categories'] = []; - $category_factory = $this->_categoryFactory->create(); - foreach ($category_ids as $category_id) { - $category = $category_factory->load($category_id); - $decoded_payload['product']['categories'][$category_id] = $category->getName(); - } - return $decoded_payload; - } } diff --git a/Helper/CategoryMapper.php b/Helper/CategoryMapper.php new file mode 100644 index 00000000..f4c1bd3c --- /dev/null +++ b/Helper/CategoryMapper.php @@ -0,0 +1,107 @@ +_categoryFactory = $categoryFactory; + } + + /** + * Replace all CategoryIds in payload with their respective names + * @param $payload + * @return array + */ + public function replaceCategoryIdsWithNames(array $payload): array + { + $this->updateCategoryMap($payload['Categories']); + + foreach ($payload['Items'] as &$item){ + $item['Categories'] = $this->searchCategoryMapAndReturnNames($item['Categories']); + } + + $payload['AddedItemCategories'] = $this->searchCategoryMapAndReturnNames($payload['AddedItemCategories']); + $payload['Categories'] = $this->searchCategoryMapAndReturnNames($payload['Categories']); + + return $payload; + } + + /** + * Adds all category names in payload to their respective ids + * @param $payload json encoded string of the payload + * @return array + */ + public function addCategoryNames(string $payload): array + { + $decoded_payload = json_decode($payload, true); + $this->updateCategoryMap($decoded_payload['product']['Categories']); + + $decoded_payload['product']['Categories'] = $this-> + searchCategoryMapAndReturnIdsAndNames( + $decoded_payload['product']['Categories'] + ); + + return $decoded_payload; + } + + /** + * Retrieve categoryNames using categoryIds + * @param array $categoryIds + */ + public function updateCategoryMap(array $categoryIds) + { + $categoryFactory = $this->_categoryFactory->create(); + + foreach($categoryIds as $categoryId){ + if (!in_array($categoryId, $this->categoryMap)){ + $this->categoryMap[$categoryId] = $categoryFactory->load($categoryId)->getName(); + } + } + } + + /** + * Return array of CategoryNames from CategoryMap using ids + * @param array $categoryIds + * @return array + */ + public function searchCategoryMapAndReturnNames(array $categoryIds): array + { + return array_values( + array_intersect_key($this->categoryMap, array_flip($categoryIds)) + ); + } + + /** + * Return array of arrays mapping category ids to their names + * @param array $categoryIds + * @return array + */ + public function searchCategoryMapAndReturnIdsAndNames(array $categoryIds): array + { + $categoryIdsAndNames = []; + foreach ($categoryIds as $categoryId){ + $categoryIdsAndNames[$categoryId] = $this->categoryMap[$categoryId]; + } + return $categoryIdsAndNames; + } +} diff --git a/Helper/Webhook.php b/Helper/Webhook.php index 18c85de9..b6bdc09a 100755 --- a/Helper/Webhook.php +++ b/Helper/Webhook.php @@ -52,12 +52,12 @@ public function makeWebhookRequest($webhookType, $data, $klaviyoId=null) CURLOPT_CUSTOMREQUEST => 'POST', CURLOPT_POSTFIELDS => $data, CURLOPT_USERAGENT => self::USER_AGENT, - CURLOPT_HTTPHEADER => array( + CURLOPT_HTTPHEADER => [ 'Content-Type: application/json', 'Magento-two-signature: ' . $this->createWebhookSecurity($data), 'Content-Length: '. strlen($data), 'Topic: ' . $webhookType - ), + ], ]); // Submit the request @@ -65,7 +65,7 @@ public function makeWebhookRequest($webhookType, $data, $klaviyoId=null) $err = curl_errno($curl); if ($err) { - $this->_klaviyoLogger->log(sprintf("Unable to send webhook to $url with data: $data")); + $this->_klaviyoLogger->log("Unable to send webhook to $url with data: $data"); } // Close cURL session handle @@ -75,8 +75,8 @@ public function makeWebhookRequest($webhookType, $data, $klaviyoId=null) } /** - * @param string data - * @return string + * @param string $data json payload used to create hmac signature + * @return string an HMAC signature for webhooks * @throws Exception */ private function createWebhookSecurity(string $data) diff --git a/Observer/ProductSaveAfter.php b/Observer/ProductSaveAfter.php index 1fb6a1ad..86b4c14d 100644 --- a/Observer/ProductSaveAfter.php +++ b/Observer/ProductSaveAfter.php @@ -84,13 +84,12 @@ private function normalizeProduct($product=null) $product_id = $product->getId(); - $product_info = array( + $product_info = [ 'store_ids' => $product->getStoreIds(), - 'product' => array( + 'product' => [ 'ID' => $product_id, 'TypeID' => $product->getTypeId(), 'Name' => $product->getName(), - 'qty' => $this->_stockRegistry->getStockItem($product_id)->getQty(), 'Visibility' => $product->getVisibility(), 'IsInStock' => $product->isInStock(), 'Status' => $product->getStatus(), @@ -98,18 +97,18 @@ private function normalizeProduct($product=null) 'UpdatedAt' => $product->getUpdatedAt(), 'FirstImageURL' => $product->getImage(), 'ThumbnailImageURL' => $product->getThumbnail(), - 'metadata' => array( + 'Metadata' => [ 'price' => $product->getPrice(), 'sku' => $product->getSku() - ), - 'categories' => $product->getCategoryIds() - ) - ); + ], + 'Categories' => $product->getCategoryIds() + ] + ]; if ($product->getSpecialPrice()) { - $product_info['metadata']['special_price'] = $product->getSpecialPrice(); - $product_info['metadata']['special_from_date'] = $product->getSpecialFromDate(); - $product_info['metadata']['special_to_date'] = $product->getSpecialToDate(); + $product_info['Metadata']['special_price'] = $product->getSpecialPrice(); + $product_info['Metadata']['special_from_date'] = $product->getSpecialFromDate(); + $product_info['Metadata']['special_to_date'] = $product->getSpecialToDate(); } return $product_info; } From 2699a28770ff76b6a92588834c960eb4cbc40d34 Mon Sep 17 00:00:00 2001 From: jordan allain Date: Tue, 16 Nov 2021 17:01:37 -0500 Subject: [PATCH 13/15] Respond with array of arrays in getWebhooks - Change the response from the getWebhooks endpoint so that it returns an array of arrays instead of an array of associative arrays. This makes it unpackable app-side. --- Helper/ScopeSetting.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Helper/ScopeSetting.php b/Helper/ScopeSetting.php index 602353af..bb0fa27a 100755 --- a/Helper/ScopeSetting.php +++ b/Helper/ScopeSetting.php @@ -147,8 +147,8 @@ public function getWebhookSecret($storeId = null) public function getWebhooks() { return $registeredWebhooks = [ - ['product/delete' => $this->getProductDeleteWebhookSetting()], - ['product/save' => $this->getProductSaveWebhookSetting()], + ['product/delete', $this->getProductDeleteWebhookSetting()], + ['product/save', $this->getProductSaveWebhookSetting()], ]; } From cd37f4dc9505eea7925cb76dcb08a1a02b062b54 Mon Sep 17 00:00:00 2001 From: jordan allain Date: Thu, 18 Nov 2021 17:13:41 -0500 Subject: [PATCH 14/15] Scott feedback --- Helper/ScopeSetting.php | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/Helper/ScopeSetting.php b/Helper/ScopeSetting.php index bb0fa27a..5d4286f5 100755 --- a/Helper/ScopeSetting.php +++ b/Helper/ScopeSetting.php @@ -147,8 +147,13 @@ public function getWebhookSecret($storeId = null) public function getWebhooks() { return $registeredWebhooks = [ - ['product/delete', $this->getProductDeleteWebhookSetting()], - ['product/save', $this->getProductSaveWebhookSetting()], + [ + 'topic' => 'product/delete', + 'enabled' => $this->getProductDeleteWebhookSetting() + ], + [ + 'topic' => 'product/save', + 'enabled' => $this->getProductSaveWebhookSetting()], ]; } From 440ebc817c01b3a1a4b462e7a0c34ccc5021c1c6 Mon Sep 17 00:00:00 2001 From: jordan allain Date: Tue, 7 Dec 2021 16:06:31 -0500 Subject: [PATCH 15/15] Update capitalization of filename --- etc/crontab.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/etc/crontab.xml b/etc/crontab.xml index 154bb971..dd2cd295 100644 --- a/etc/crontab.xml +++ b/etc/crontab.xml @@ -1,10 +1,10 @@ - + */5 * * * * - + 59 23 * * *