diff --git a/Api/Data/QueueCollectionInterface.php b/Api/Data/QueueCollectionInterface.php new file mode 100644 index 0000000..afc3755 --- /dev/null +++ b/Api/Data/QueueCollectionInterface.php @@ -0,0 +1,24 @@ + + */ +namespace Remarkety\Mgconnector\Block\Adminhtml\Install; + +use \Magento\Store\Model\ResourceModel\Store\Collection as StoreCollection; +use \Remarkety\Mgconnector\Model\QueueFactory; +use \Magento\Catalog\Model\ProductFactory; + +class Grid extends \Magento\Backend\Block\Widget\Grid\Extended +{ + public function __construct( + \Magento\Backend\Block\Template\Context $context, + \Magento\Backend\Helper\Data $backendHelper, + array $data = [] + ) + { + parent::__construct($context, $backendHelper, $data); + $this->setPagerVisibility(false); + $this->setFilterVisibility(false); + } + + public function getRowUrl($item) + { + return ''; + } + + protected function _prepareCollection() + { + $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); + /** @var \Magento\Store\Model\ResourceModel\Store\Collection $collection */ + $collection = $objectManager->create('Magento\Store\Model\ResourceModel\Store\Collection'); + + $collection->addOrder('website_id')->addOrder('group_id'); + + $this->setCollection($collection); + parent::_prepareCollection(); + return $this; + } + + protected function _prepareColumns() + { + $this->addColumn('website_id', [ + 'header' => __('Website'), + 'index' => 'website_id', + 'renderer' => 'Remarkety\Mgconnector\Block\Adminhtml\Install\Grid\Render\Website' + ]); + + $this->addColumn('group_id', [ + 'header' => __('Store'), + 'index' => 'group_id', + 'renderer' => 'Remarkety\Mgconnector\Block\Adminhtml\Install\Grid\Render\Group' + ]); + + $this->addColumn('name', array( + 'header' => __('Store view'), + 'index' => 'name' + )); + + $this->addColumn('store_id', [ + 'header' => __('Status'), + 'index' => 'store_id', + 'renderer' => 'Remarkety\Mgconnector\Block\Adminhtml\Install\Grid\Render\Status' + ]); + + return parent::_prepareColumns(); + } +} diff --git a/Block/Adminhtml/Install/Grid/Render/Group.php b/Block/Adminhtml/Install/Grid/Render/Group.php new file mode 100644 index 0000000..0facc38 --- /dev/null +++ b/Block/Adminhtml/Install/Grid/Render/Group.php @@ -0,0 +1,30 @@ + + */ +class Group extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer +{ + + /** + * {@inheritdoc} + */ + public function render(\Magento\Framework\DataObject $row) + { + $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); + /** + * @var $groupRepository \Magento\Store\Model\GroupRepository + */ + $groupRepository = $objectManager->get('Magento\Store\Model\GroupRepository'); + $group = $groupRepository->get($row->getGroupId()); + + return $group->getName(); + } +} diff --git a/Block/Adminhtml/Install/Grid/Render/Status.php b/Block/Adminhtml/Install/Grid/Render/Status.php new file mode 100644 index 0000000..2b6f2af --- /dev/null +++ b/Block/Adminhtml/Install/Grid/Render/Status.php @@ -0,0 +1,44 @@ + + */ +class Status extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer +{ + + /** + * {@inheritdoc} + */ + public function render(\Magento\Framework\DataObject $row) + { + $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); + /** + * @var $configHelper ConfigHelper + */ + $configHelper = $objectManager->get('Remarkety\Mgconnector\Helper\ConfigHelper'); + $installed = $configHelper->isStoreInstalled($row->getStoreId()); + if($installed){ + $ret = ''. __('Connected') .''; + + $publicId = $configHelper->getRemarketyPublicId($row->getStoreId()); + if(empty($publicId)){ + $ret .= '
'; + $ret .= '(' . __('Missing Remarkety\'s store id; website tracking and live updates will not work.') . ')'; + } + + return $ret; + } else { + return ''; + } + } +} diff --git a/Block/Adminhtml/Install/Grid/Render/Website.php b/Block/Adminhtml/Install/Grid/Render/Website.php new file mode 100644 index 0000000..51ed808 --- /dev/null +++ b/Block/Adminhtml/Install/Grid/Render/Website.php @@ -0,0 +1,30 @@ + + */ +class Website extends \Magento\Backend\Block\Widget\Grid\Column\Renderer\AbstractRenderer +{ + + /** + * {@inheritdoc} + */ + public function render(\Magento\Framework\DataObject $row) + { + $objectManager = \Magento\Framework\App\ObjectManager::getInstance(); + /** + * @var $websiteRepo \Magento\Store\Model\WebsiteRepository + */ + $websiteRepo = $objectManager->get('Magento\Store\Model\WebsiteRepository'); + $website = $websiteRepo->getById($row->getWebsiteId()); + + return $website->getName(); + } +} diff --git a/Block/Adminhtml/Install/Install.php b/Block/Adminhtml/Install/Install.php index dcd9a5e..af7e5f3 100644 --- a/Block/Adminhtml/Install/Install.php +++ b/Block/Adminhtml/Install/Install.php @@ -2,14 +2,24 @@ namespace Remarkety\Mgconnector\Block\Adminhtml\Install; +use Remarkety\Mgconnector\Helper\ConfigHelper; + class Install extends \Magento\Framework\View\Element\Template { + public $configHelper; + public function __construct(\Magento\Framework\View\Element\Template\Context $context, - \Remarkety\Mgconnector\Helper\Data $remarketyHelper){ + \Remarkety\Mgconnector\Helper\Data $remarketyHelper, + ConfigHelper $configHelper){ parent::__construct($context); $this->remarketyHelper = $remarketyHelper; + $this->configHelper = $configHelper; } + public function getStoresGrid(){ + $block = $this->getLayout()->createBlock('Remarkety\Mgconnector\Block\Adminhtml\Install\Grid'); + return $block->toHtml(); + } protected function _toHtml() { @@ -21,4 +31,4 @@ protected function _toHtml() public function getHelperMode(){ return $this->remarketyHelper->getMode(); } -} \ No newline at end of file +} diff --git a/Block/Adminhtml/Install/Install/Login/Form.php b/Block/Adminhtml/Install/Install/Login/Form.php index d1bcf6e..cfc9b98 100644 --- a/Block/Adminhtml/Install/Install/Login/Form.php +++ b/Block/Adminhtml/Install/Install/Login/Form.php @@ -66,10 +66,14 @@ protected function _prepareForm() 'class' => 'required-entry admin__control-text' )); + $options = $this->_systemStore->getStoreValuesForForm(false, false); + $selected_store_id = $this->getRequest()->getParam('store'); + $fieldset->addField('store_id', 'select', array( 'name' => 'data[store_id]', 'label' =>__('Sync Remarkety with this view:'), - 'values' => $this->_systemStore->getStoreValuesForForm(false, false) + 'values' => $options, + 'value' => $selected_store_id )); $fieldset->addField('button', 'note', array( @@ -88,4 +92,4 @@ public function currentStore($id = null) { $manager = $om->get('Magento\Store\Model\StoreManagerInterface'); return $manager->getStore($id); } -} \ No newline at end of file +} diff --git a/Block/Adminhtml/Install/Welcome/Form/Form.php b/Block/Adminhtml/Install/Welcome/Form/Form.php index b2607a9..591f272 100644 --- a/Block/Adminhtml/Install/Welcome/Form/Form.php +++ b/Block/Adminhtml/Install/Welcome/Form/Form.php @@ -40,22 +40,15 @@ protected function _prepareForm() 'value' => 'complete', )); $fieldset->addField('instruction', 'note', array( - 'text' => '', - 'label' => false, - 'after_element_html' => '

' . __('Welcome to Remarkety - What\'s next?') . '

+ 'text' => '

' . __('Welcome to Remarkety - What\'s next?') . '

  1. Sign in to your account here
  2. Create campaigns, send emails and monitor results.
  3. Increase sales and customer\'s Life Time Value
  4. Need help? We are here for you: support@remarkety.com (+1 800 570-7564)
- ' - )); - $fieldset->addField('button', 'note', array( + ', 'label' => false, - 'name' => 'button', - 'after_element_html' => '', )); $this->setForm($form); diff --git a/Block/Adminhtml/Install/Welcome/Store.php b/Block/Adminhtml/Install/Welcome/Store.php deleted file mode 100644 index b18de24..0000000 --- a/Block/Adminhtml/Install/Welcome/Store.php +++ /dev/null @@ -1,39 +0,0 @@ -_coreRegistry = $registry; - parent::__construct($context, $data); - } - public function _construct() - { - parent::_construct(); - $this->_blockGroup = 'Remarkety_Mgconnector'; - $this->_controller = 'adminhtml_install'; - $this->_headerText = __('remarkety test'); - $this->_mode = 'welcome'; - $this->removeButton('reset'); - $this->removeButton('back'); - $this->removeButton('save'); - - } - - protected function _prepareLayout() - { - parent::_prepareLayout(); - } -} \ No newline at end of file diff --git a/Block/Adminhtml/Install/Welcome/Store/Store.php b/Block/Adminhtml/Install/Welcome/Store/Store.php deleted file mode 100644 index 2a997c8..0000000 --- a/Block/Adminhtml/Install/Welcome/Store/Store.php +++ /dev/null @@ -1,55 +0,0 @@ -storeManager = $storeManager; - $this->_configResource = $context->getScopeConfig(); - - parent::__construct($context); - } - public function _toHtml(){ - $this->setTemplate('mgconnector/install/welcome/store.phtml'); - return parent::_toHtml(); - - } - - public function getStoresStatus() - { - $stores = array(); - - foreach ($this->storeManager->getWebsites() as $_website) { - $stores[$_website->getCode()] = array( - 'name' => $_website->getName(), - 'id' => $_website->getWebsiteId(), - ); - - foreach ($_website->getGroups() as $_group) { - $stores[$_website->getCode()]['store_groups'][$_group->getGroupId()] = [ - 'name' => $_group->getName(), - 'id' => $_group->getGroupId(), - ]; - - foreach ($_group->getStores() as $_store) { - $isInstalled = $this->_configResource->getValue(\Remarkety\Mgconnector\Model\Install::XPATH_INSTALLED, \Remarkety\Mgconnector\Model\Install::STORE_SCOPE, $_store->getStoreId()); - $stores[$_website->getCode()]['store_groups'][$_group->getGroupId()]['store_views'][$_store->getStoreId()] = array( - 'name' => $_store->getName(), - 'id' => $_store->getStoreId(), - 'isInstalled' => $isInstalled, - ); - } - } - } - return $stores; - } -} \ No newline at end of file diff --git a/Block/Adminhtml/Queue/Grid.php b/Block/Adminhtml/Queue/Grid.php index 52e36c8..e1e51fc 100644 --- a/Block/Adminhtml/Queue/Grid.php +++ b/Block/Adminhtml/Queue/Grid.php @@ -118,6 +118,41 @@ protected function _prepareColumns() 'index' => 'next_attempt' )); + $this->addColumn('last_error_message', array( + 'header' => __('Last error'), + 'width' => '200px', + 'index' => 'last_error_message' + )); + return parent::_prepareColumns(); } -} \ No newline at end of file + + /** + * @return $this + */ + protected function _prepareMassaction() + { + $this->setMassactionIdField('queue_id'); + $this->getMassactionBlock()->setFormFieldName('queue'); + + $this->getMassactionBlock()->addItem( + 'resend', + [ + 'label' => __('Resend'), + 'url' => $this->getUrl('/*/resend') + ] + ); + + $this->getMassactionBlock()->addItem( + 'delete', + [ + 'label' => __('Delete'), + 'url' => $this->getUrl('/*/delete'), + 'confirm' => __('Are you sure?') + ] + ); + + + return $this; + } +} diff --git a/Controller/Adminhtml/Install/Webhooks.php b/Controller/Adminhtml/Install/Webhooks.php new file mode 100644 index 0000000..407124c --- /dev/null +++ b/Controller/Adminhtml/Install/Webhooks.php @@ -0,0 +1,44 @@ + + */ +namespace Remarkety\Mgconnector\Controller\Adminhtml\Install; + +use \Magento\Backend\App\Action\Context; +use Magento\Store\Model\StoreManager; +use Remarkety\Mgconnector\Helper\ConfigHelper; + +class Webhooks extends \Magento\Backend\App\Action +{ + protected $configHelper; + protected $storeManager; + + public function __construct( + Context $context, + ConfigHelper $configHelper, + StoreManager $storeManager + ){ + parent::__construct($context); + $this->configHelper = $configHelper; + $this->storeManager = $storeManager; + } + + public function execute(){ + $enabled = $this->getRequest()->getParam('enabled'); + if($enabled == 0){ + //disable + $this->configHelper->setWebhooksGloballStatus(false); + } else { + //enable + $this->configHelper->setWebhooksGloballStatus(true); + //get remarkety store id for eash enabled store + + } + $this->_redirect('*/install/install'); + } +} diff --git a/Controller/Adminhtml/Queue/Delete.php b/Controller/Adminhtml/Queue/Delete.php new file mode 100644 index 0000000..959bab7 --- /dev/null +++ b/Controller/Adminhtml/Queue/Delete.php @@ -0,0 +1,50 @@ +resultPageFactory = $resultPageFactory; + $this->queueRepository = $queueRepository; + $this->eventMethods = $eventMethods; + } + + public function execute() + { + $itemsDeleted = 0; + $item_ids = $this->getRequest()->getParam('queue'); + foreach ($item_ids as $id){ + try { + $item = $this->queueRepository->getById($id); + $this->queueRepository->delete($item); + $itemsDeleted++; + } catch (\Exception $ex){ + $this->eventMethods->logError($ex); + } + + } + $this->getMessageManager()->addSuccessMessage(__('Total of %1 events(s) were deleted', $itemsDeleted)); + $this->_redirect('/*/queue'); + } +} diff --git a/Controller/Adminhtml/Queue/Queue.php b/Controller/Adminhtml/Queue/Queue.php index 0f91348..2ba9e24 100644 --- a/Controller/Adminhtml/Queue/Queue.php +++ b/Controller/Adminhtml/Queue/Queue.php @@ -31,4 +31,4 @@ public function execute() return $resultPage; } -} \ No newline at end of file +} diff --git a/Controller/Adminhtml/Queue/Resend.php b/Controller/Adminhtml/Queue/Resend.php new file mode 100644 index 0000000..7a6951f --- /dev/null +++ b/Controller/Adminhtml/Queue/Resend.php @@ -0,0 +1,58 @@ +resultPageFactory = $resultPageFactory; + $this->queueRepository = $queueRepository; + $this->eventMethods = $eventMethods; + } + + public function execute() + { + $itemsSent = 0; + $item_ids = $this->getRequest()->getParam('queue'); + foreach ($item_ids as $id){ + try { + $item = $this->queueRepository->getById($id); + if($this->eventMethods->makeRequest( + $item->getEventType(), + json_decode($item->getPayload(), true), + $item->getStoreId(), + $item->getAttempts(), + $item->getQueueId() + )) { + $itemsSent++; + $this->queueRepository->delete($item); + } + } catch (\Exception $ex){ + $this->eventMethods->logError($ex); + } + + } + $this->getMessageManager()->addSuccessMessage(__('Total of %1 events(s) were resent', $itemsSent)); + $this->_redirect('/*/queue'); + } +} diff --git a/Cron/Queue.php b/Cron/Queue.php index d5ccf7a..a987770 100644 --- a/Cron/Queue.php +++ b/Cron/Queue.php @@ -4,6 +4,7 @@ use Psr\Log\LoggerInterface; use Remarkety\Mgconnector\Model\Queue as QueueModel; +use Remarkety\Mgconnector\Model\QueueRepository; use Remarkety\Mgconnector\Observer\EventMethods; class Queue @@ -24,21 +25,26 @@ class Queue */ protected $eventMethods; + protected $queueRepository; + /** * Queue constructor. * * @param LoggerInterface $logger - * @param QueueModel $queueModel - * @param EventMethods $eventMethods + * @param QueueModel $queueModel + * @param EventMethods $eventMethods + * @param QueueRepository $queueRepository */ public function __construct( LoggerInterface $logger, QueueModel $queueModel, - EventMethods $eventMethods + EventMethods $eventMethods, + QueueRepository $queueRepository ) { $this->logger = $logger; $this->queueModel = $queueModel; $this->eventMethods = $eventMethods; + $this->queueRepository = $queueRepository; } /** @@ -54,14 +60,13 @@ protected function resend($queueItems,$resetAttempts = false) { foreach($queueItems as $queue) { $result = $this->eventMethods->makeRequest( $queue->getEventType(), - unserialize($queue->getPayload()), - $resetAttempts ? 1 : ($queue->getAttempts()+1), + json_decode($queue->getPayload(), true), + $queue->getStoreId(), + $resetAttempts ? 0 : $queue->getAttempts(), $queue->getId() ); if($result) { - $this->queueModel - ->load($queue->getId()) - ->delete(); + $this->queueRepository->deleteById($queue->getId()); $sent++; } } @@ -91,4 +96,4 @@ public function execute() return $this; } -} \ No newline at end of file +} diff --git a/Helper/ConfigHelper.php b/Helper/ConfigHelper.php new file mode 100644 index 0000000..3a13aec --- /dev/null +++ b/Helper/ConfigHelper.php @@ -0,0 +1,80 @@ +_scopeConfig = $scopeConfig; + $this->_activeStore = $sManager->getStore(); + $this->configResource = $configResource; + $this->cacheTypeList = $cacheTypeList; + } + + public function isStoreInstalled($storeId){ + $installed = $this->_scopeConfig->getValue(\Remarkety\Mgconnector\Model\Install::XPATH_INSTALLED, \Remarkety\Mgconnector\Model\Install::STORE_SCOPE, $storeId); + return !empty($installed); + } + + public function getRemarketyPublicId($store = null) + { + $store = is_null($store) ? $this->_activeStore : $store; + $store_id = is_numeric($store) ? $store : $store->getId(); + $id = $this->_scopeConfig->getValue(self::RM_STORE_ID, ScopeInterface::SCOPE_STORES, $store_id); + return (empty($id) || is_null($id)) ? false : $id; + } + + public function isWebhooksGloballyEnabled(){ + $webhooksEnabled = $this->_scopeConfig->getValue(self::WEBHOOKS_ENABLED); + if(is_null($webhooksEnabled) || !empty($webhooksEnabled)){ + return true; + } + return false; + } + + public function shouldSendProductUpdates(){ + $webhooks = $this->_scopeConfig->getValue(self::PRODUCT_WEBHOOKS_DISABLED); + if(empty($webhooks)){ + return true; + } + return false; + } + + /** + * @param bool $enabled + */ + public function setWebhooksGloballStatus($enabled){ + $this->configResource->saveConfig( + self::WEBHOOKS_ENABLED, + $enabled ? 1 : 0, + ScopeConfigInterface::SCOPE_TYPE_DEFAULT, + 0 + ); + $this->cacheTypeList->cleanType('config'); + } +} diff --git a/Helper/Data.php b/Helper/Data.php index b7bcbe9..fb5fad3 100644 --- a/Helper/Data.php +++ b/Helper/Data.php @@ -2,23 +2,36 @@ namespace Remarkety\Mgconnector\Helper; +use Magento\Catalog\Api\Data\ProductAttributeMediaGalleryEntryInterface; +use Magento\Catalog\Api\Data\ProductInterface; use Magento\TestFramework\Inspection\Exception; use \Remarkety\Mgconnector\Model\Install as InstallModel; class Data extends \Magento\Framework\App\Helper\AbstractHelper { + protected $storeManager; + protected $galleryManagement; + protected $_catalogProductTypeConfigurable; + private $categoryMapCache = []; + protected $categoryFactory; public function __construct(\Magento\Framework\App\Helper\Context $context, \Magento\Framework\Module\ModuleResource $moduleResource, \Magento\Integration\Model\Integration $integration, \Magento\Customer\Model\Session $session, - InstallModel $installModel - + InstallModel $installModel, + \Magento\Store\Model\StoreManagerInterface $storeManager, + \Magento\Catalog\Model\Product\Gallery\GalleryManagement $galleryManagement, + \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable $catalogProductTypeConfigurable, + \Magento\Catalog\Model\CategoryFactory $categoryFactory ){ - $this->integration = $integration; $this->moduleResource = $moduleResource; $this->session = $session; $this->installModel = $installModel; + $this->storeManager = $storeManager; + $this->galleryManagement = $galleryManagement; + $this->_catalogProductTypeConfigurable = $catalogProductTypeConfigurable; + $this->categoryFactory = $categoryFactory; parent::__construct($context); } @@ -64,4 +77,86 @@ public function getMode() } return $mode; } + + public function getMediaUrl() + { + $mediaUrl = $this->storeManager->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA); + return $mediaUrl; + } + + public function getMediaGalleryImages(ProductInterface $product) + { + /** + * @var $images ProductAttributeMediaGalleryEntryInterface[] + */ + $images = $this->galleryManagement->getList($product->getSku()); + $ret = []; + $imagesData = []; + if ($images) { + foreach ($images as $imageAttr) { + if($imageAttr->getMediaType() == "image"){ + $types = $imageAttr->getTypes(); + if(empty($types)){ + $imagesData['id'] = $imageAttr->getId(); + $imagesData['product_id'] = $imageAttr->getEntityId(); + $imagesData['src'] = $this->getMediaUrl() . 'catalog/product' . $imageAttr->getFile(); + $ret[] = $imagesData; + } else { + foreach ($types as $type){ + $imagesData['id'] = $imageAttr->getId(); + $imagesData['type'] = $type; + $imagesData['product_id'] = $imageAttr->getEntityId(); + $imagesData['src'] = $this->getMediaUrl() . 'catalog/product' . $imageAttr->getFile(); + $ret[] = $imagesData; + } + } + } + } + } + return $ret; + } + + public function getImage($product) + { + $images = $this->galleryManagement->getList($product->getSku()); + $imageDet = []; + $imagesData = []; + if($images) { + foreach ($images as $imageAttr) { + if ($imageAttr['types']) { + foreach ($imageAttr['types'] as $type) { + if ($type == 'image') { + $imagesData['id'] = $imageAttr['id']; + $imagesData['product_id'] = $imageAttr['entity_id']; + $imagesData['src'] = $this->getMediaUrl() . 'catalog/product' . $imageAttr['file']; + $imageDet = $imagesData; + } + + } + } + } + return $imageDet; + } + } + + public function getCategory($category_id) + { + if (!isset($this->categoryMapCache[$category_id])) { + $category = $this->categoryFactory->create()->load($category_id); + $this->categoryMapCache[$category_id] = $category->getName(); + } + if (!isset($this->categoryMapCache[$category_id])) return false; + + return ['code' => $category_id, 'name' => $this->categoryMapCache[$category_id]]; + } + + public function getParentId($id) + { + $parentByChild = $this->_catalogProductTypeConfigurable->getParentIdsByChild($id); + if (isset($parentByChild[0])) { + $id = $parentByChild[0]; + return $id; + } + return false; + } } diff --git a/Model/Api/Data.php b/Model/Api/Data.php index b4f24d9..6526c07 100644 --- a/Model/Api/Data.php +++ b/Model/Api/Data.php @@ -1,7 +1,9 @@ [ @@ -291,9 +303,21 @@ public function __construct(ProductFactory $productFactory, CustomerCollectionFactory $customerCollectionFactory, \Magento\Sales\Model\ResourceModel\Order\CollectionFactory $salesOrderResourceCollectionFactory, RuleFactory $ruleFactory, - CouponFactory $couponFactory + CouponFactory $couponFactory, + Config $resourceConfig, + TypeListInterface $cacheTypeList, + Collection $queueCollection, + QueueRepository $queueRepository, + EventMethods $eventMethods, + DataHelper $dataHelper ) { + $this->dataHelper = $dataHelper; + $this->eventMethods = $eventMethods; + $this->queueRepo = $queueRepository; + $this->queueCollection = $queueCollection; + $this->cacheTypeList = $cacheTypeList; + $this->resourceConfig = $resourceConfig; $this->productFactory = $productFactory; $this->productCollectionFactory = $searchResultFactory; $this->customerFactory = $customerFactory; @@ -322,15 +346,6 @@ public function __construct(ProductFactory $productFactory, $this->couponFactory = $couponFactory; } - public function getParentId($id) - { - $parentByChild = $this->_catalogProductTypeConfigurable->getParentIdsByChild($id); - if (isset($parentByChild[0])) { - $id = $parentByChild[0]; - return $id; - } - return false; - } /** * Get All products from catalog * @@ -436,13 +451,13 @@ public function getProducts( } $prod['product_exists'] = $active; - $prod['image'] = $this->getImage($row); - $prod['images'] = $this->getMediaGalleryImages($row); + $prod['image'] = $this->dataHelper->getImage($row); + $prod['images'] = $this->dataHelper->getMediaGalleryImages($row); $prod['body_html'] = $row->getDescription(); $prod['id'] = $row->getId(); - $parent_id = $this->getParentId($row->getId()); + $parent_id = $this->dataHelper->getParentId($row->getId()); if ($row->getTypeId() == 'simple' && $parent_id) { $parentProductData = $this->productFactory->create()->load($parent_id); if ($parentProductData->getId()) { @@ -462,7 +477,7 @@ public function getProducts( return $object; } - private function getCategory($category_id) + public function getCategory($category_id) { if (!isset($this->categoryMapCache[$category_id])) { $category = $this->categoryFactory->create()->load($category_id); @@ -473,51 +488,6 @@ private function getCategory($category_id) return ['code' => $category_id, 'name' => $this->categoryMapCache[$category_id]]; } - public function getMediaGalleryImages($product) - { - $images = $this->entryFactory->getList($product->getSku()); - $imageDet = []; - $imagesData = []; - if ($images) { - foreach ($images as $imageAttr) { - $imagesData['id'] = $imageAttr['id']; - $imagesData['product_id'] = $imageAttr['entity_id']; - $imagesData['src'] = $this->getMediaUrl() . 'catalog/product' . $imageAttr['file'];; - $imageDet[] = $imagesData; - } - return $imageDet; - } return; - } - - public function getImage($product) - { - $images = $this->entryFactory->getList($product->getSku()); - $imageDet = []; - $imagesData = []; - if($images) { - foreach ($images as $imageAttr) { - if ($imageAttr['types']) { - foreach ($imageAttr['types'] as $type) { - if ($type == 'image') { - $imagesData['id'] = $imageAttr['id']; - $imagesData['product_id'] = $imageAttr['entity_id']; - $imagesData['src'] = $this->getMediaUrl() . 'catalog/product' . $imageAttr['file']; - $imageDet = $imagesData; - } - - } - } - } - return $imageDet; - } - } - - public function getMediaUrl() - { - $mediaUrl = $this->_storeManagerInterface->getStore()->getBaseUrl(\Magento\Framework\UrlInterface::URL_TYPE_MEDIA); - return $mediaUrl; - } - /** * Get All products from catalog * @@ -787,6 +757,7 @@ public function getOrders( } } } + $ord['id'] = empty($order->getOriginalIncrementId()) ? $order->getIncrementId() : $order->getOriginalIncrementId(); if ($order->getCustomerId()) { $ord['customer'] = $this->getCustomerDataById($order->getCustomerId()); } else { @@ -1139,4 +1110,201 @@ public function createCoupon($ruleId, $couponCode, $expiration = null){ return $response; } + + /** + * @param int|null $mage_store_id + * @param string $configName + * @param string $scope + * @return string + */ + public function getConfig($mage_store_id, $configName, $scope) + { + $store_id = 0; + if($scope == 'stores'){ + $store_id = $mage_store_id; + } else { + $scope = 'default'; + } + return $this->scopeConfig->getValue('remarkety/mgconnector/' . $configName, $scope, $store_id); + } + + /** + * @param int|null $mage_store_id + * @param string $configName + * @param string $scope + * @param string $newValue + * @return string + */ + public function setConfig($mage_store_id, $configName, $scope, $newValue) + { + $store_id = 0; + if($scope == 'stores'){ + $store_id = $mage_store_id; + } else { + $scope = 'default'; + } + $this->resourceConfig->saveConfig( + 'remarkety/mgconnector/' . $configName, + $newValue, + $scope, + $store_id + ); + + $this->cacheTypeList->cleanType('config'); + return 1; + } + + + /** + * @return string + */ + public function getVersion() + { + return '2.2.0'; + } + + /** + * @param int $mage_store_id + * @param int|null $limit + * @param int|null $page + * @param int|null $minId + * @param int|null $maxId + * @return \Remarkety\Mgconnector\Api\Data\QueueCollectionInterface + */ + public function getQueueItems($mage_store_id, $limit = null, $page = null, $minId = null, $maxId = null) + { + $sel = $this->queueCollection + ->getSelect(); + $sel->where('store_id', $mage_store_id) + ->order('queue_id asc'); + + if(empty($limit) || !is_numeric($limit)){ + $limit = 10; + } + + if(empty($limit) || !is_numeric($limit)){ + $page = 0; + } + + if(is_numeric($limit) && is_numeric($page)){ + $page++; + $sel->limitPage($page, $limit); + } + + if(is_numeric($minId)){ + $sel->where('queue_id >= ' . $minId); + } + + if(is_numeric($maxId)){ + $sel->where('queue_id <= ' . $maxId); + } + + $object = new \Remarkety\Mgconnector\Model\Api\Data\QueueCollection(); + $data = $this->queueCollection->toArray(); + $object->setQueueItems($data['items']); + + return $object; + } + + /** + * @param int $mage_store_id + * @param int|null $minId + * @param int|null $maxId + * @return array + */ + public function deleteQueueItems($mage_store_id, $minId = null, $maxId = null) + { + $sel = $this->queueCollection + ->getSelect(); + $sel->where('store_id = '. $mage_store_id) + ->order('queue_id asc'); + + if(is_numeric($minId)){ + $sel->where('queue_id >= ' . $minId); + } + + if(is_numeric($maxId)){ + $sel->where('queue_id <= ' . $maxId); + } + $toDelete = $this->queueCollection->count(); + $itemsDeleted = 0; + foreach ($this->queueCollection as $item){ + try { + $this->queueRepo->delete($item); + $itemsDeleted++; + } catch (\Exception $ex){ + } + } + $ret = [ + 'response' => [ + 'totalMatching' => $toDelete, + 'totalDeleted' => $itemsDeleted + ] + ]; + return $ret; + } + + /** + * @param int $mage_store_id + * @param int|null $limit + * @param int|null $page + * @param int|null $minId + * @param int|null $maxId + * @return int + */ + public function retryQueueItems($mage_store_id, $limit = null, $page = null, $minId = null, $maxId = null) + { + $sel = $this->queueCollection + ->getSelect(); + $sel->where('store_id = '. $mage_store_id) + ->order('queue_id asc'); + + if(is_numeric($minId)){ + $sel->where('queue_id >= ' . $minId); + } + + if(is_numeric($maxId)){ + $sel->where('queue_id <= ' . $maxId); + } + + if(empty($limit) || !is_numeric($limit)){ + $limit = 10; + } + + if(empty($limit) || !is_numeric($limit)){ + $page = 0; + } + + if(is_numeric($limit) && is_numeric($page)){ + $page++; + $sel->limitPage($page, $limit); + } + + $itemsSent = 0; + /** + * @var $item QueueInterface + */ + foreach ($this->queueCollection as $item){ + try { + if($this->eventMethods->makeRequest( + $item->getEventType(), + json_decode($item->getPayload(), true), + $item->getStoreId(), + $item->getAttempts(), + $item->getQueueId() + )) { + $itemsSent++; + $this->queueRepo->delete($item); + } + } catch (\Exception $ex){ + } + } + $ret = [ + 'response' => [ + 'totalMatching' => $this->queueCollection->count(), + 'sentSuccessfully' => $itemsSent + ] + ]; + return $ret; + } } diff --git a/Model/Api/Data/QueueCollection.php b/Model/Api/Data/QueueCollection.php new file mode 100644 index 0000000..6164461 --- /dev/null +++ b/Model/Api/Data/QueueCollection.php @@ -0,0 +1,13 @@ +_items; + } + + public function setQueueItems(array $items = null) { + $this->_items = $items; + } +} diff --git a/Model/Data/Queue.php b/Model/Data/Queue.php new file mode 100644 index 0000000..88a532e --- /dev/null +++ b/Model/Data/Queue.php @@ -0,0 +1,193 @@ +_get('queue_id'); + } + + /** + * Get URL Key + * + * @return string|null + */ + public function getEventType() + { + return $this->_get('event_type'); + } + + /** + * Get URL Key + * + * @return string|null + */ + public function getPayload() + { + return $this->_get('payload'); + } + + /** + * Get URL Key + * + * @return int|null + */ + public function getAttempts() + { + return $this->_get('attempts'); + } + + /** + * Get URL Key + * + * @return string|null + */ + public function getLastAttempt() + { + return $this->_get('last_attempt'); + } + + /** + * Get URL Key + * + * @return string|null + */ + public function getNextAttempt() + { + return $this->_get('next_attempt'); + } + + /** + * Get URL Key + * + * @return string|null + */ + public function getStatus() + { + return $this->_get('status'); + } + + /** + * Set ID + * + * @param int $queueId + * @return \Remarkety\Mgconnector\Api\Data\QueueInterface + */ + public function setQueueId($queueId) + { + return $this->setData('queue_id', $queueId); + } + + /** + * Set ID + * + * @param string $eventType + * @return \Remarkety\Mgconnector\Api\Data\QueueInterface + */ + public function setEventType($eventType) + { + return $this->setData('event_type', $eventType); + } + + /** + * Set ID + * + * @param array $payload + * @return \Remarkety\Mgconnector\Api\Data\QueueInterface + */ + public function setPayload($payload) + { + return $this->setData('payload', $payload); + } + + /** + * Set ID + * + * @param int $attempts + * @return \Remarkety\Mgconnector\Api\Data\QueueInterface + */ + public function setAttempts($attempts) + { + return $this->setData('attempts', $attempts); + } + + /** + * Set ID + * + * @param string $lastAttempt + * @return \Remarkety\Mgconnector\Api\Data\QueueInterface + */ + public function setLastAttempt($lastAttempt) + { + return $this->setData('last_attempt', $lastAttempt); + } + + /** + * Set ID + * + * @param string $nextAttempt + * @return \Remarkety\Mgconnector\Api\Data\QueueInterface + */ + public function setNextAttempt($nextAttempt) + { + return $this->setData('next_attempt', $nextAttempt); + } + + /** + * Set ID + * + * @param string $status + * @return \Remarkety\Mgconnector\Api\Data\QueueInterface + */ + public function setStatus($status) + { + return $this->setData('status', $status); + } + + /** + * @return int|null + */ + public function getStoreId() + { + return $this->_get('store_id'); + } + + /** + * @param $storeId + * @return \Remarkety\Mgconnector\Api\Data\QueueInterface + */ + public function setStoreId($storeId) + { + return $this->setData('store_id', $storeId); + } + + /** + * @return string|null + */ + public function getLastErrorMessage() + { + return $this->_get('last_error_message'); + } + + /** + * @return \Remarkety\Mgconnector\Api\Data\QueueInterface + */ + public function setLastErrorMessage($message) + { + return $this->setData('last_error_message', $message); + } +} diff --git a/Model/Install.php b/Model/Install.php index 5c492ca..25000ac 100644 --- a/Model/Install.php +++ b/Model/Install.php @@ -3,6 +3,7 @@ namespace Remarkety\Mgconnector\Model; +use Magento\Framework\App\Cache\TypeList; use \Magento\Framework\Model\Context; use \Magento\Framework\App\Config\ScopeConfigInterface; use \Magento\Framework\App\Config\Data as ConfigData; @@ -89,6 +90,8 @@ class Install extends \Magento\Framework\Model\AbstractModel protected $_webtracking; + protected $_cache; + public function __construct(Context $context, \Magento\Framework\Registry $registry, ScopeConfigInterface $scopeConfig, @@ -104,9 +107,11 @@ public function __construct(Context $context, Config $config, \Magento\Integration\Model\IntegrationService $integrationService, \Magento\Integration\Model\OauthService $oauthService, - Session $session + Session $session, + TypeList $cache ){ parent::__construct($context, $registry); + $this->_cache = $cache; $this->context = $context; $this->scopeConfigInterface = $scopeConfig; $this->_resourceConfig = $resourceConfig; @@ -344,7 +349,7 @@ protected function _markInstalled($storeId) { $this->_webtracking->setRemarketyPublicId($storeId, $response['storePublicId']); } - + $this->_cache->cleanType('config'); return $this; } diff --git a/Model/Queue.php b/Model/Queue.php index b738689..5c405de 100644 --- a/Model/Queue.php +++ b/Model/Queue.php @@ -1,7 +1,9 @@ _init('Remarkety\Mgconnector\Model\ResourceModel\Queue'); @@ -17,6 +19,11 @@ public function getQueueId() return $this->getData('queue_id'); } + public function getIdentities() + { + return [self::CACHE_TAG . '_' . $this->getId()]; + } + /** * Get URL Key * @@ -82,7 +89,7 @@ public function setQueueId($queueId) { return $this->setData('queue_id', $queueId); - } +} /** * Set ID * @@ -143,4 +150,37 @@ public function setStatus($status) { return $this->setData('status', $status); } -} \ No newline at end of file + + /** + * @return string|null + */ + public function getLastErrorMessage() + { + return $this->getData('last_error_message'); + } + + /** + * @return \Remarkety\Mgconnector\Api\Data\QueueInterface + */ + public function setLastErrorMessage($message) + { + return $this->setData('last_error_message', $message); + } + + /** + * @return int + */ + public function getStoreId() + { + return $this->getData('store_id' ); + } + + /** + * @param int $storeId + * @return \Remarkety\Mgconnector\Api\Data\QueueInterface + */ + public function setStoreId($storeId) + { + return $this->setData( 'store_id', $storeId ); + } +} diff --git a/Model/QueueRepository.php b/Model/QueueRepository.php new file mode 100644 index 0000000..f553836 --- /dev/null +++ b/Model/QueueRepository.php @@ -0,0 +1,108 @@ +objectFactory = $objectFactory; + $this->collectionFactory = $collectionFactory; + $this->searchResultsFactory = $searchResultsFactory; + } + + public function save(QueueInterface $object) + { + try + { + $object->save(); + } + catch(\Exception $e) + { + throw new CouldNotSaveException(__($e->getMessage())); + } + return $object; + } + + /** + * @param $id + * @return QueueInterface + * @throws NoSuchEntityException + */ + public function getById($id) + { + $object = $this->objectFactory->create(); + $object->load($id); + if (!$object->getId()) { + throw new NoSuchEntityException(__('Object with id "%1" does not exist.', $id)); + } + return $object; + } + + public function delete(QueueInterface $object) + { + try { + $object->delete(); + } catch (\Exception $exception) { + throw new CouldNotDeleteException(__($exception->getMessage())); + } + return true; + } + + public function deleteById($id) + { + return $this->delete($this->getById($id)); + } + + public function getList(SearchCriteriaInterface $criteria) + { + $searchResults = $this->searchResultsFactory->create(); + $searchResults->setSearchCriteria($criteria); + $collection = $this->collectionFactory->create(); + foreach ($criteria->getFilterGroups() as $filterGroup) { + $fields = []; + $conditions = []; + foreach ($filterGroup->getFilters() as $filter) { + $condition = $filter->getConditionType() ? $filter->getConditionType() : 'eq'; + $fields[] = $filter->getField(); + $conditions[] = [$condition => $filter->getValue()]; + } + if ($fields) { + $collection->addFieldToFilter($fields, $conditions); + } + } + $searchResults->setTotalCount($collection->getSize()); + $sortOrders = $criteria->getSortOrders(); + if ($sortOrders) { + /** @var SortOrder $sortOrder */ + foreach ($sortOrders as $sortOrder) { + $collection->addOrder( + $sortOrder->getField(), + ($sortOrder->getDirection() == SortOrder::SORT_ASC) ? 'ASC' : 'DESC' + ); + } + } + $collection->setCurPage($criteria->getCurrentPage()); + $collection->setPageSize($criteria->getPageSize()); + $objects = []; + foreach ($collection as $objectModel) { + $objects[] = $objectModel; + } + $searchResults->setItems($objects); + return $searchResults; + }} diff --git a/Model/ResourceModel/Queue.php b/Model/ResourceModel/Queue.php index 42248b3..906f56d 100644 --- a/Model/ResourceModel/Queue.php +++ b/Model/ResourceModel/Queue.php @@ -1,13 +1,9 @@ _init('mgconnector_queue', 'queue_id'); + $this->_init('mgconnector_queue','queue_id'); } } diff --git a/Model/ResourceModel/Queue/Collection.php b/Model/ResourceModel/Queue/Collection.php index b53fc39..7accb96 100644 --- a/Model/ResourceModel/Queue/Collection.php +++ b/Model/ResourceModel/Queue/Collection.php @@ -1,12 +1,9 @@ _init('Remarkety\Mgconnector\Model\Queue', 'Remarkety\Mgconnector\Model\ResourceModel\Queue'); + $this->_init('Remarkety\Mgconnector\Model\Queue','Remarkety\Mgconnector\Model\ResourceModel\Queue'); } -} \ No newline at end of file +} diff --git a/Model/Webtracking.php b/Model/Webtracking.php index ba3c963..ad64d00 100644 --- a/Model/Webtracking.php +++ b/Model/Webtracking.php @@ -3,7 +3,6 @@ use \Magento\Config\Model\ResourceModel\Config; use Magento\Store\Model\StoreManager; -use \Magento\Store\Model\Store; use \Magento\Framework\App\Config\ScopeConfigInterface; Class Webtracking extends \Magento\Framework\Model\AbstractModel @@ -38,4 +37,4 @@ public function setRemarketyPublicId($store, $newId) $store_id ); } -} \ No newline at end of file +} diff --git a/Observer/EventMethods.php b/Observer/EventMethods.php index 6452fec..d26b8dc 100644 --- a/Observer/EventMethods.php +++ b/Observer/EventMethods.php @@ -1,14 +1,23 @@ customerRegistry = $customerRegistry; + $this->customerRepository = $customerRepository; + $this->request = $request; + $this->logger = $logger; + $this->customerSerializer = $customerSerializer; + $this->orderSerializer = $orderSerializer; + $this->addressSerializer = $addressSerializer; + $this->productSerializer = $productSerializer; -){ $this->_coreRegistry = $coreRegistry; $this->subscriber = $subscriber; $this->_customerGroup = $customerGroupModel; - $this->_remarketyQueue = $remarketyQueue; + $this->_remarketyQueueRepo = $remarketyQueueRepo; $this->_store = $store; $this->scopeConfigInterface = $scopeConfig; + $this->configHelper = $configHelper; + $this->queueFactory = $queueFactory; + $this->_token = $this->scopeConfigInterface->getValue('remarkety/mgconnector/api_key'); $intervals = $this->scopeConfigInterface->getValue('remarkety/mgconnector/intervals'); if(empty($intervals)){ @@ -58,76 +114,29 @@ public function __construct( } } - protected function _customerRegistration() - { - $this->makeRequest('customers/create', $this->_prepareCustomerUpdateData()); - return $this; + protected function isWebhooksEnabled($store){ + if(!$this->configHelper->isWebhooksGloballyEnabled()){ + return false; + } + return !empty($this->configHelper->getRemarketyPublicId($store)); } - protected function _customerUpdate() - { - if($this->_hasDataChanged()) { - $this->makeRequest('customers/update', $this->_prepareCustomerUpdateData()); - } - return $this; + protected function shouldSendProductUpdates(){ + return $this->configHelper->shouldSendProductUpdates(); } - protected function _hasDataChanged() + protected function _customerUpdate(\Magento\Customer\Api\Data\CustomerInterface $customer, $isNew = false) { - $customerReg = $this->_coreRegistry->registry('customer_data_object_observer'); - - if(!$this->_hasDataChanged && $customerReg) { - $validate = array( - 'firstname', - 'lastname', - 'title', - 'birthday', - 'gender', - 'email', - 'group_id', - 'default_billing', - 'is_subscribed', - ); - $originalData = $customerReg->getOrigData(); - $currentData = $customerReg->getData(); - foreach ($validate as $field) { - if (isset($originalData[$field])) { - if (!isset($currentData[$field]) || $currentData[$field] != $originalData[$field]) { - $this->_hasDataChanged = true; - break; - } - } + if($this->isWebhooksEnabled($customer->getStoreId())) { + $eventType = self::EVENT_CUSTOMERS_UPDATED; + if($isNew){ + $eventType = self::EVENT_CUSTOMERS_CREATE; } - $customerData = $customerReg->getData(); - if(!$this->_hasDataChanged && isset($customerData['is_subscribed'])) { - $subscriber = $this->subscriber->loadByEmail($customerReg->getEmail()); - $isSubscribed = $subscriber->getId() ? $subscriber->getData('subscriber_status') == \Magento\Newsletter\Model\Subscriber::STATUS_SUBSCRIBED : false; + $data = $this->customerSerializer->serialize($customer); - if($customerData['is_subscribed'] !== $isSubscribed) { - $this->_hasDataChanged = true; - } - } + $this->makeRequest($eventType, $data, $customer->getStoreId()); } - if(!$this->_hasDataChanged && $this->_coreRegistry->registry('customer_address_object_observer') && $this->_coreRegistry->registry('customer_orig_address')) { - $validate = array( - 'street', - 'city', - 'region', - 'postcode', - 'country_id', - 'telephone', - ); - - $addressObs = $this->_coreRegistry->registry('customer_address_object_observer')->getData(); - $originalAddressObs = $this->_coreRegistry->registry('customer_orig_address'); - $addressDiffKeys = array_keys( array_diff($addressObs, $originalAddressObs)); - - if(array_intersect($addressDiffKeys, $validate)) { - $this->_hasDataChanged = true; - } - } - - return $this->_hasDataChanged; + return $this; } protected function _getRequestConfig($eventType) @@ -135,41 +144,66 @@ protected function _getRequestConfig($eventType) return array( 'adapter' => 'Zend_Http_Client_Adapter_Curl', 'curloptions' => array( -// CURLOPT_FOLLOWLOCATION => true, CURLOPT_HEADER => true, CURLOPT_CONNECTTIMEOUT => self::REMARKETY_TIMEOUT -// CURLOPT_SSL_CIPHER_LIST => "RC4-SHA" ), ); } - protected function _getHeaders($eventType,$payload) + protected function _getHeaders($eventType,$payload, $storeId = null) { $domain = $this->_store->getBaseUrl(UrlInterface::URL_TYPE_WEB); $domain = substr($domain, 7, -1); - $headers = array( + if(empty($storeId) && isset($payload['storeId'])){ + $storeId = $payload['storeId']; + } + + $headers = [ 'X-Domain: ' . $domain, 'X-Token: ' . $this->_token, 'X-Event-Type: ' . $eventType, 'X-Platform: ' . self::REMARKETY_PLATFORM, 'X-Version: ' . self::REMARKETY_VERSION, - 'X-Magento-Store-Id: ' . $this->_store->getId() - ); - if (isset($payload['storeId'])) - $headers[] = 'X-Magento-Store-Id: ' . $payload['storeId']; + 'X-Magento-Store-Id: ' . (empty($storeId) ? $this->_store->getId() : $storeId) + ]; return $headers; } - public function makeRequest($eventType, $payload, $attempt = 1, $queueId = null) + protected function shouldSendEvent($eventType, $payload, $storeId){ + $data = array( + 'eventType' => $eventType, + 'payload' => $payload, + 'storeId' => $storeId + ); + $hash = md5(serialize($data)); + if($this->_coreRegistry->registry($hash)){ + return false; + } + $this->_coreRegistry->register($hash, 1); + return true; + } + + public function makeRequest($eventType, $payload, $storeId = null, $attempt = 0, $queueId = null) { try { - $client = new \Zend_Http_Client(self::REMARKETY_EVENTS_ENDPOINT, $this->_getRequestConfig($eventType)); + if(!$this->shouldSendEvent($eventType, $payload, $storeId)){ + //safety for not sending the same event on same event + $this->logger->debug('Event already sent ' . $eventType); + return true; + } + + $url = self::REMARKETY_EVENTS_ENDPOINT; + if(!empty($storeId)){ + $remarketyId = $this->configHelper->getRemarketyPublicId($storeId); + $url .= '?debug=1&storeId=' . $remarketyId; + } + $client = new \Zend_Http_Client($url, $this->_getRequestConfig($eventType)); $payload = array_merge($payload, $this->_getPayloadBase($eventType)); $json = json_encode($payload); $response = $client - ->setHeaders($this->_getHeaders($eventType, $payload)) + ->setHeaders($this->_getHeaders($eventType, $payload, $storeId)) ->setRawData($json, 'application/json') ->request(self::REMARKETY_METHOD); @@ -181,42 +215,55 @@ public function makeRequest($eventType, $payload, $attempt = 1, $queueId = null) case '401': throw new \Exception('Request failed, probably wrong API key or inactive account.'); default: - $this->_queueRequest($eventType, $payload, $attempt, $queueId); + $err = $response->getStatus() . ' - ' . $response->getRawBody(); + $this->_queueRequest($eventType, $payload, $attempt+1, $queueId, $storeId, $err); } } catch(\Exception $e) { - $this->_queueRequest($eventType, $payload, $attempt, $queueId); + $err = $e->getCode() . ' - ' . $e->getMessage(); + $this->_queueRequest($eventType, $payload, $attempt+1, $queueId, $storeId, $err); } return false; } - protected function _queueRequest($eventType, $payload, $attempt, $queueId) + protected function _queueRequest($eventType, $payload, $attempt, $queueId, $storeId, $err = null) { - $queueModel = $this->_remarketyQueue; + $queueModel = null; if(!empty($this->_intervals[$attempt-1])) { $now = time(); $nextAttempt = $now + (int)$this->_intervals[$attempt-1] * 60; if($queueId) { - $queueModel->load($queueId); + $queueModel = $this->_remarketyQueueRepo->getById($queueId); $queueModel->setAttempts($attempt); $queueModel->setLastAttempt( date("Y-m-d H:i:s", $now) ); $queueModel->setNextAttempt( date("Y-m-d H:i:s", $nextAttempt) ); + $queueModel->setStoreId($storeId); + if(!empty($err)){ + $queueModel->setLastErrorMessage($err); + } } else { + $queueModel = $this->queueFactory->create(); + $this->_remarketyQueueRepo->save($queueModel); $queueModel->setData(array( 'event_type' => $eventType, - 'payload' => serialize($payload), + 'payload' => json_encode($payload), 'attempts' => $attempt, 'last_attempt' => date("Y-m-d H:i:s", $now), 'next_attempt' => date("Y-m-d H:i:s", $nextAttempt), 'status' => 1, + 'store_id' => $storeId )); + if(!empty($err)){ + $queueModel->setLastErrorMessage($err); + } } - return $queueModel->save(); + return $this->_remarketyQueueRepo->save($queueModel); } elseif($queueId) { - $queueModel->load($queueId); + $queueModel = $this->_remarketyQueueRepo->getById($queueId); + $queueModel->setAttempts($attempt); $queueModel->setStatus(0); - return $queueModel->save(); + return $this->_remarketyQueueRepo->save($queueModel); } return false; } @@ -231,121 +278,39 @@ protected function _getPayloadBase($eventType) return $arr; } - protected function _prepareCustomerUpdateData() - { - $customerReg = $this->_coreRegistry->registry('customer_data_object_observer'); - if($customerReg) { - $arr = array( - 'id' => (int)$customerReg->getId(), - 'email' => $customerReg->getEmail(), - 'created_at' => date('c', strtotime($customerReg->getCreatedAt())), - 'first_name' => $customerReg->getFirstname(), - 'last_name' => $customerReg->getLastname(), - 'store_id' => $customerReg->getStoreId(), - //'extra_info' => array(), - ); - - $isSubscribed = $customerReg->getIsSubscribed(); - if ($isSubscribed === null) { - $subscriber = $this->subscriber->loadByEmail($customerReg->getEmail()); - if ($subscriber->getId()) { - $isSubscribed = $subscriber->getData('subscriber_status') == \Magento\Newsletter\Model\Subscriber::STATUS_SUBSCRIBED; - } else { - $isSubscribed = false; - } - } - $arr = array_merge($arr, array('accepts_marketing' => (bool)$isSubscribed)); - - if ($title = $customerReg->getPrefix()) { - $arr = array_merge($arr, array('title' => $title)); - } - if ($dob = $customerReg->getDob()) { - $arr = array_merge($arr, array('birthdate' => $dob)); - } - - if ($gender = $customerReg->getGender()) { - $arr = array_merge($arr, array('gender' => $gender)); - } - - if ($address = $customerReg->getDefaultBillingAddress()) { - $street = $address->getStreet(); - $arr = array_merge($arr, array('default_address' => array( - 'address1' => isset($street[0]) ? $street[0] : '', - 'address2' => isset($street[1]) ? $street[1] : '', - 'city' => $address->getCity(), - 'province' => $address->getRegion(), - 'phone' => $address->getTelephone(), - 'country_code' => $address->getCountryId(), - 'zip' => $address->getPostcode(), - ))); - } - - - if ($group = $this->_customerGroup->load($customerReg->getGroupId())) { - $arr = array_merge($arr, array('groups' => array( - array( - 'id' => (int)$customerReg->getGroupId(), - 'name' => $group->getCustomerGroupCode(), - ) - ))); - } - - return $arr; - } - return array(); - } - - - protected function _prepareCustomerSubscribtionUpdateData() + protected function _prepareCustomerSubscribtionUpdateData(Subscriber $subscriber, $clientIp = null) { - $subscriber = $this->_coreRegistry->registry('subscriber_object_data_observer'); $arr = array( 'email' => $subscriber->getSubscriberEmail(), - 'accepts_marketing' => $subscriber->getData('subscriber_status') == \Magento\Newsletter\Model\Subscriber::STATUS_SUBSCRIBED, - 'storeId' => $this->_store->getId() + 'accepts_marketing' => $subscriber->getSubscriberStatus() == \Magento\Newsletter\Model\Subscriber::STATUS_SUBSCRIBED, + 'storeId' => $subscriber->getStoreId() ); + if(!empty($clientIp)){ + $arr['client_ip'] = $clientIp; + } + return $arr; } - protected function _prepareCustomerSubscribtionDeleteData() + protected function _prepareCustomerSubscribtionDeleteData(Subscriber $subscriber) { - $subscriber = $this->_coreRegistry->registry('subscriber_object_data_observer'); $arr = array( 'email' => $subscriber->getSubscriberEmail(), 'accepts_marketing' => false, - 'storeId' => $this->_store->getId() + 'storeId' => $subscriber->getStoreId() ); return $arr; } - public function resend($queueItems,$resetAttempts = false) { - $sent=0; - foreach($queueItems as $_queue) { - $result = $this->makeRequest($_queue->getEventType(), unserialize($_queue->getPayload()), $resetAttempts ? 1 : ($_queue->getAttempts()+1), $_queue->getId()); - if($result) { - $this->_remarketyQueue - ->load($_queue->getId()) - ->delete(); - $sent++; - } - } - return $sent; + public function logError(\Exception $exception){ + $this->logger->error("Remarkety:".self::class." - " . $exception->getMessage(), [ + 'message' => $exception->getMessage(), + 'line' => $exception->getLine(), + 'file' => $exception->getFile(), + 'trace' => $exception->getTraceAsString() + ]); } - - public function run() - { - $collection = $this->_remarketyQueue->getCollection(); - $nextAttempt = date("Y-m-d H:i:s"); - $collection - ->getSelect() - ->where('next_attempt <= ?', $nextAttempt) - ->where('status = 1') - ->order('main_table.next_attempt asc'); - $this->resend($collection); - return $this; - } - } diff --git a/Observer/TriggerCancelOrderItem.php b/Observer/TriggerCancelOrderItem.php new file mode 100644 index 0000000..436117b --- /dev/null +++ b/Observer/TriggerCancelOrderItem.php @@ -0,0 +1,20 @@ +getEvent(); + } +} diff --git a/Observer/TriggerCatalogInventorySave.php b/Observer/TriggerCatalogInventorySave.php new file mode 100644 index 0000000..85cb17e --- /dev/null +++ b/Observer/TriggerCatalogInventorySave.php @@ -0,0 +1,24 @@ +getEvent(); +// $_item = $event->getItem(); +// if ((int)$_item->getQty != (int)$_item->getOrigData('qty')) { +// $willSend = true; +// } + } +} diff --git a/Observer/TriggerCustomerAddressBeforeUpdateObserver.php b/Observer/TriggerCustomerAddressBeforeUpdateObserver.php index 91b27a2..d84666f 100644 --- a/Observer/TriggerCustomerAddressBeforeUpdateObserver.php +++ b/Observer/TriggerCustomerAddressBeforeUpdateObserver.php @@ -7,47 +7,21 @@ use Magento\Customer\Model\CustomerFactory; use \Magento\Framework\ObjectManager\ObjectManager; use \Magento\Framework\Registry; +use Remarkety\Mgconnector\Helper\ConfigHelper; use Remarkety\Mgconnector\Observer\EventMethods; use \Magento\Newsletter\Model\Subscriber; use \Magento\Customer\Model\Group; use \Remarkety\Mgconnector\Model\Queue; use \Magento\Store\Model\Store; use \Magento\Framework\App\Config\ScopeConfigInterface; +use Remarkety\Mgconnector\Serializer\AddressSerializer; +use Remarkety\Mgconnector\Serializer\CustomerSerializer; +use Remarkety\Mgconnector\Serializer\OrderSerializer; class TriggerCustomerAddressBeforeUpdateObserver extends EventMethods implements ObserverInterface { - /** - * @var Registry - */ - protected $_coreRegistry; - - protected $_origAddressData = null; - /** - * @var CustomerFactory - */ - protected $_customerFactory; - - protected $__objectManager; - public function __construct( - CustomerFactory $customerFactory, - ObjectManager $objectManager, - Registry $registry, - \Magento\Customer\Model\Session $customerSession, - Subscriber $subscriber, - Group $customerGroupModel, - Queue $remarketyQueue, - Store $store, - ScopeConfigInterface $scopeConfig - - ) { - parent::__construct($registry, $subscriber, $customerGroupModel, $remarketyQueue, $store, $scopeConfig); - $this->_customerFactory = $customerFactory; - $this->_objectManager = $objectManager; - $this->_coreRegistry = $registry; - $this->session = $customerSession; - } /** * Apply catalog price rules to product in admin * @@ -56,12 +30,13 @@ public function __construct( */ public function execute(\Magento\Framework\Event\Observer $observer) { - $address = $this->session->getCustomer()->getDefaultBillingAddress(); - if(!empty($address)) { - $this->_origAddressData = $address->getData(); + try { + if($this->request->getFullActionName() == "customer_account_loginPost"){ + return $this; + } + } catch (\Exception $ex){ + $this->logError($ex); } - $this->_coreRegistry->unregister( 'customer_orig_address' ); - $this->_coreRegistry->register('customer_orig_address', $this->_origAddressData); return $this; } } diff --git a/Observer/TriggerCustomerAddressUpdateObserver.php b/Observer/TriggerCustomerAddressUpdateObserver.php index 90856bc..69d8b37 100644 --- a/Observer/TriggerCustomerAddressUpdateObserver.php +++ b/Observer/TriggerCustomerAddressUpdateObserver.php @@ -7,79 +7,57 @@ use Magento\Customer\Model\CustomerFactory; use \Magento\Framework\Registry; use \Magento\Framework\ObjectManager\ObjectManager; +use Remarkety\Mgconnector\Helper\ConfigHelper; use Remarkety\Mgconnector\Observer\EventMethods; use \Magento\Newsletter\Model\Subscriber; use \Magento\Customer\Model\Group; use \Remarkety\Mgconnector\Model\Queue; use \Magento\Store\Model\Store; use \Magento\Framework\App\Config\ScopeConfigInterface; +use Remarkety\Mgconnector\Serializer\AddressSerializer; +use Remarkety\Mgconnector\Serializer\CustomerSerializer; +use Remarkety\Mgconnector\Serializer\OrderSerializer; class TriggerCustomerAddressUpdateObserver extends EventMethods implements ObserverInterface { /** - * @var Registry - */ - protected $_coreRegistry; - - protected $_origAddressData = null; - /** - * @var CustomerFactory - */ - protected $_customerFactory; - - protected $_address = null; - - protected $_customer = null; - - public function __construct( - CustomerFactory $customerFactory, - ObjectManager $objectManager, - Registry $registry, - Subscriber $subscriber, - Group $customerGroupModel, - Queue $remarketyQueue, - Store $store, - ScopeConfigInterface $scopeConfig - - ) { - parent::__construct($registry, $subscriber, $customerGroupModel, $remarketyQueue, $store, $scopeConfig); - $this->_customerFactory = $customerFactory; - $this->_objectManager = $objectManager; - } - - /** - * Apply catalog price rules to product in admin + * Customer update address * * @param \Magento\Framework\Event\Observer $observer * @return $this */ public function execute(\Magento\Framework\Event\Observer $observer) { - $this->_address = $observer->getEvent()->getCustomerAddress(); - $this->_customer = $this->_address->getCustomer(); - - if($this->_coreRegistry->registry('remarkety_customer_save_observer_executed_'.$this->_customer->getId())) { - return $this; - } - - $this->_store = $this->_customer->getStore(); - - $isDefaultBilling = - ($this->_customer == null || $this->_customer->getDefaultBillingAddress() == null) - ? false - : ($this->_address->getId() == $this->_customer->getDefaultBillingAddress()->getId()); - if (!$isDefaultBilling || !$this->_customer->getId()) { - return $this; + try { + if($this->request->getFullActionName() == "customer_account_loginPost"){ + return $this; + } + $address = $observer->getEvent()->getCustomerAddress(); + /** + * @var $customer \Magento\Customer\Api\Data\CustomerInterface + */ + + $customerId = $address->getCustomer()->getId(); + $this->customerRegistry->remove($customerId); + $customer = $this->customerRepository->getById($customerId); + + if($this->_coreRegistry->registry('remarkety_customer_save_observer_executed_'.$customer->getId())) { + return $this; + } + $this->_coreRegistry->register('remarkety_customer_save_observer_executed_'.$customer->getId(),true); + + $isDefaultBilling = false; + if($customer && $customer->getDefaultBilling() == $address->getId()){ + $isDefaultBilling = true; + } + if (!$isDefaultBilling || !$customer->getId()) { + return $this; + } + + $this->_customerUpdate($customer); + } catch (\Exception $ex){ + $this->logError($ex); } - - $this->_coreRegistry->unregister( 'customer_address_object_observer' ); - $this->_coreRegistry->unregister( 'customer_data_object_observer' ); - $this->_coreRegistry->register('customer_address_object_observer', $this->_address); - $this->_coreRegistry->register('customer_data_object_observer', $this->_customer); - $this->_customerUpdate(); - - $this->_coreRegistry->unregister( 'remarkety_customer_save_observer_executed_'.$this->_customer->getId() ); - $this->_coreRegistry->register('remarkety_customer_save_observer_executed_'.$this->_customer->getId(),true); return $this; } } diff --git a/Observer/TriggerCustomerDeleteObserver.php b/Observer/TriggerCustomerDeleteObserver.php index 8f2bae9..b385ada 100644 --- a/Observer/TriggerCustomerDeleteObserver.php +++ b/Observer/TriggerCustomerDeleteObserver.php @@ -2,7 +2,9 @@ namespace Remarkety\Mgconnector\Observer; +use Magento\Customer\Model\Backend\Customer; use Magento\Framework\Event\ObserverInterface; +use Remarkety\Mgconnector\Helper\ConfigHelper; use Remarkety\Mgconnector\Observer\EventMethods; use \Magento\Customer\Model\Session; use \Magento\Framework\Registry; @@ -11,35 +13,33 @@ use \Remarkety\Mgconnector\Model\Queue; use \Magento\Store\Model\Store; use \Magento\Framework\App\Config\ScopeConfigInterface; +use Remarkety\Mgconnector\Serializer\AddressSerializer; +use Remarkety\Mgconnector\Serializer\CustomerSerializer; +use Remarkety\Mgconnector\Serializer\OrderSerializer; class TriggerCustomerDeleteObserver extends EventMethods implements ObserverInterface { + public function execute(\Magento\Framework\Event\Observer $observer){ + try { + /** + * @var $customer Customer + */ + $customer = $observer->getEvent()->getCustomer(); + if (!$customer->getId()) { + return $this; + } + $store = $customer->getStore(); - public function __construct( - Session $customerSession, - Registry $registry, - Subscriber $subscriber, - Group $customerGroupModel, - Queue $remarketyQueue, - Store $store, - ScopeConfigInterface $scopeConfig - ){ - parent::__construct($registry, $subscriber, $customerGroupModel, $remarketyQueue, $store, $scopeConfig); - $this->session = $customerSession; - $this->_coreRegistry = $registry; - } + if($this->isWebhooksEnabled($store)) { + $this->makeRequest(self::EVENT_CUSTOMERS_DELETED, array( + 'id' => (int)$customer->getId(), + 'email' => $customer->getEmail(), + ), $store->getId()); + } - public function execute(\Magento\Framework\Event\Observer $observer){ - $customer = $observer->getEvent()->getCustomer(); - if (!$customer->getId()) { - return $this; + } catch (\Exception $ex){ + $this->logError($ex); } - $this->_store = $customer->getStore(); - - $this->makeRequest('customers/delete', array( - 'id' => (int)$customer->getId(), - 'email' => $customer->getEmail(), - )); return $this; } -} \ No newline at end of file +} diff --git a/Observer/TriggerCustomerUpdateObserver.php b/Observer/TriggerCustomerUpdateObserver.php index ca6e4af..38c9482 100644 --- a/Observer/TriggerCustomerUpdateObserver.php +++ b/Observer/TriggerCustomerUpdateObserver.php @@ -8,38 +8,17 @@ use \Magento\Framework\Registry; use \Magento\Newsletter\Model\Subscriber; use \Magento\Customer\Model\Group; +use Remarkety\Mgconnector\Helper\ConfigHelper; use \Remarkety\Mgconnector\Model\Queue; use \Magento\Store\Model\Store; use \Magento\Framework\App\Config\ScopeConfigInterface; +use Remarkety\Mgconnector\Serializer\AddressSerializer; +use Remarkety\Mgconnector\Serializer\CustomerSerializer; +use Remarkety\Mgconnector\Serializer\OrderSerializer; class TriggerCustomerUpdateObserver extends EventMethods implements ObserverInterface { - /** - * @var Registry - */ - protected $_coreRegistry; - - - protected $_origAddressData = null; - /** - * @var CustomerFactory - */ - protected $_customerFactory; - protected $_customer = null; - - public function __construct( - CustomerFactory $customerFactory, - Registry $registry, - Subscriber $subscriber, - Group $customerGroupModel, - Queue $remarketyQueue, - Store $store, - ScopeConfigInterface $scopeConfig - ) { - parent::__construct($registry, $subscriber, $customerGroupModel, $remarketyQueue, $store, $scopeConfig); - $this->_customerFactory = $customerFactory; - } /** * Apply catalog price rules to product in admin * @@ -48,25 +27,24 @@ public function __construct( */ public function execute(\Magento\Framework\Event\Observer $observer) { - $this->_customer = $observer->getEvent()->getCustomer(); - - if($this->_coreRegistry->registry('remarkety_customer_save_observer_executed_'.$this->_customer->getId()) || !$this->_customer->getId()) { - return $this; - } - - $this->_coreRegistry->unregister( 'customer_data_object_observer' ); - $this->_coreRegistry->register('customer_data_object_observer', $this->_customer); - $this->_store = $this->_customer->getStore(); - if($this->_customer->getOrigData() === null) { - $this->_customerRegistration(); - } else { - $this->_customerUpdate(); + try { + if($this->request->getFullActionName() == "customer_account_loginPost"){ + return $this; + } + /** + * @var $customer \Magento\Customer\Api\Data\CustomerInterface + */ + $customer = $this->customerRepository->getById($observer->getEvent()->getCustomer()->getId()); + if($this->_coreRegistry->registry('remarkety_customer_save_observer_executed_'.$customer->getId()) || !$customer->getId()) { + return $this; + } + $this->_coreRegistry->register('remarkety_customer_save_observer_executed_'.$customer->getId(),true); + + $isNew = $customer->getCreatedAt() == $customer->getUpdatedAt(); + $this->_customerUpdate($customer, $isNew); + } catch (\Exception $ex){ + $this->logError($ex); } - - $this->_coreRegistry->unregister( 'remarkety_customer_save_observer_executed_'.$this->_customer->getId() ); - - $this->_coreRegistry->register('remarkety_customer_save_observer_executed_'.$this->_customer->getId(),true); return $this; } - } diff --git a/Observer/TriggerOrderUpdated.php b/Observer/TriggerOrderUpdated.php new file mode 100644 index 0000000..9d6abad --- /dev/null +++ b/Observer/TriggerOrderUpdated.php @@ -0,0 +1,47 @@ +getEvent(); + /** + * @var $order Order + */ + $order = $event->getDataByKey('order'); + if ($order && $this->isWebhooksEnabled($order->getStore())) { + + $eventType = self::EVENT_ORDERS_UPDATED; + if ($order->getCreatedAt() == $order->getUpdatedAt()) { + $eventType = self::EVENT_ORDERS_CREATED; + } + + $data = $this->orderSerializer->serialize($order); + $this->makeRequest($eventType, $data, $order->getStore()->getId()); + } + } catch (\Exception $ex){ + $this->logError($ex); + } + } + +} diff --git a/Observer/TriggerProductBeforeDelete.php b/Observer/TriggerProductBeforeDelete.php new file mode 100644 index 0000000..a24ab3f --- /dev/null +++ b/Observer/TriggerProductBeforeDelete.php @@ -0,0 +1,40 @@ +shouldSendProductUpdates()){ + return; + } + + $event = $observer->getEvent(); + /** + * @var $product ProductInterface + */ + $product = $event->getDataByKey('product'); + if(!empty($product)) { + $storeIds = $product->getStoreIds(); + if (!empty($storeIds)) { + $this->_coreRegistry->register('product_stores_' . $product->getId(), $storeIds); + } + } + } catch (\Exception $ex){ + $this->logError($ex); + } + } +} diff --git a/Observer/TriggerProductDelete.php b/Observer/TriggerProductDelete.php new file mode 100644 index 0000000..a68965c --- /dev/null +++ b/Observer/TriggerProductDelete.php @@ -0,0 +1,46 @@ +shouldSendProductUpdates()){ + return; + } + + $event = $observer->getEvent(); + /** + * @var $product ProductInterface + */ + $product = $event->getDataByKey('product'); + if(!empty($product)) { + $storeIds = $this->_coreRegistry->registry('product_stores_' . $product->getId()); + if (!empty($storeIds)) { + foreach ($storeIds as $storeId) { + if ($this->isWebhooksEnabled($storeId)) { + $this->makeRequest(self::EVENT_PRODUCTS_DELETE, [ + 'id' => $product->getId() + ], $storeId); + } + } + } + } + } catch (\Exception $ex){ + $this->logError($ex); + } + } +} diff --git a/Observer/TriggerProductUpdated.php b/Observer/TriggerProductUpdated.php new file mode 100644 index 0000000..0ee58ea --- /dev/null +++ b/Observer/TriggerProductUpdated.php @@ -0,0 +1,57 @@ +shouldSendProductUpdates()){ + return; + } + + $event = $observer->getEvent(); + /** + * @var $product ProductInterface + */ + $product = $event->getDataByKey('product'); + $eventType = self::EVENT_PRODUCTS_UPDATED; + if($product->isObjectNew()){ + $eventType = self::EVENT_PRODUCTS_CREATED; + } + if(!empty($product)) { + $storeIds = $product->getStoreIds(); + if (!empty($storeIds)) { + foreach ($storeIds as $storeId) { + if ($this->isWebhooksEnabled($storeId)) { + $data = $this->productSerializer->serialize($product, $storeId); + + $this->makeRequest($eventType, $data, $storeId); + } + } + } + } + } catch (\Exception $ex){ + $this->logError($ex); + } + } + +} diff --git a/Observer/TriggerRefundOrderInventory.php b/Observer/TriggerRefundOrderInventory.php new file mode 100644 index 0000000..f534d09 --- /dev/null +++ b/Observer/TriggerRefundOrderInventory.php @@ -0,0 +1,47 @@ +shouldSendProductUpdates()){ + return; + } + + $event = $observer->getEvent(); + /** + * @var $creditMemo Creditmemo + */ + $creditMemo = $event->getCreditmemo(); + foreach ($creditMemo->getAllItems() as $item){ + if($item->getBackToStock()) { + $product = $this->productSerializer->loadProduct($item->getProductId()); + $storeIds = $product->getStoreIds(); + if (!empty($storeIds)) { + foreach ($storeIds as $storeId) { + if ($this->isWebhooksEnabled($storeId)) { + $data = $this->productSerializer->serialize($product, $storeId); + $this->makeRequest(self::EVENT_PRODUCTS_UPDATED, $data, $storeId); + } + } + } + } + } + } catch (\Exception $ex){ + $this->logError($ex); + } + } +} diff --git a/Observer/TriggerRevertQuoteInventory.php b/Observer/TriggerRevertQuoteInventory.php new file mode 100644 index 0000000..6cdf75c --- /dev/null +++ b/Observer/TriggerRevertQuoteInventory.php @@ -0,0 +1,47 @@ +shouldSendProductUpdates()){ + return; + } + + /** + * @var $order Order + */ + $order = $observer->getEvent()->getOrder(); + if($order) { + foreach ($order->getAllItems() as $item) { + $product = $this->productSerializer->loadProduct($item->getProductId()); + $storeIds = $product->getStoreIds(); + if (!empty($storeIds)) { + foreach ($storeIds as $storeId) { + if ($this->isWebhooksEnabled($storeId)) { + $data = $this->productSerializer->serialize($product, $storeId); + $this->makeRequest(self::EVENT_PRODUCTS_UPDATED, $data, $storeId); + } + } + } + } + } + } catch (\Exception $ex){ + $this->logError($ex); + } + } +} diff --git a/Observer/TriggerSubscribeDeleteObserver.php b/Observer/TriggerSubscribeDeleteObserver.php index 8b9ba96..1e79783 100644 --- a/Observer/TriggerSubscribeDeleteObserver.php +++ b/Observer/TriggerSubscribeDeleteObserver.php @@ -7,37 +7,31 @@ use \Magento\Framework\Registry; use \Magento\Newsletter\Model\Subscriber; use \Magento\Customer\Model\Group; +use Remarkety\Mgconnector\Helper\ConfigHelper; use \Remarkety\Mgconnector\Model\Queue; use \Magento\Store\Model\Store; use Magento\Store\Model\StoreManager; use \Magento\Framework\App\Config\ScopeConfigInterface; +use Remarkety\Mgconnector\Serializer\AddressSerializer; +use Remarkety\Mgconnector\Serializer\CustomerSerializer; +use Remarkety\Mgconnector\Serializer\OrderSerializer; class TriggerSubscribeDeleteObserver extends EventMethods implements ObserverInterface { - - - public function __construct( - Session $customerSession, - Registry $registry, - Subscriber $subscriber, - Group $customerGroupModel, - Queue $remarketyQueue, - Store $store, - ScopeConfigInterface $scopeConfig, - StoreManager $sManager - ){ - parent::__construct($registry, $subscriber, $customerGroupModel, $remarketyQueue, $store, $scopeConfig); - $this->session = $customerSession; - $this->_store = $sManager->getStore(); - } - public function execute(\Magento\Framework\Event\Observer $observer) { - $subscriber = $observer->getEvent()->getSubscriber(); - if (!$this->_coreRegistry->registry('remarkety_subscriber_deleted_' . $subscriber->getEmail()) && $subscriber->getId()) { - $this->makeRequest('customers/update', $this->_prepareCustomerSubscribtionDeleteData()); + try { + $subscriber = $observer->getEvent()->getSubscriber(); + if (!$this->_coreRegistry->registry('remarkety_subscriber_deleted_' . $subscriber->getEmail()) && $subscriber->getId()) { + $this->makeRequest( + 'newsletter/unsubscribed', + $this->_prepareCustomerSubscribtionDeleteData($subscriber), + $subscriber->getStoreId() + ); + } + } catch (\Exception $ex){ + $this->logError($ex); } - return $this; } -} \ No newline at end of file +} diff --git a/Observer/TriggerSubscribeUpdateObserver.php b/Observer/TriggerSubscribeUpdateObserver.php index 1224ee1..200df44 100644 --- a/Observer/TriggerSubscribeUpdateObserver.php +++ b/Observer/TriggerSubscribeUpdateObserver.php @@ -2,38 +2,65 @@ namespace Remarkety\Mgconnector\Observer; +use Magento\Customer\Model\CustomerRegistry; +use Magento\Customer\Model\ResourceModel\CustomerRepository; +use Magento\Framework\App\Request\Http; use Magento\Framework\Event\ObserverInterface; use \Magento\Customer\Model\Session; +use Magento\Framework\HTTP\PhpEnvironment\RemoteAddress; use \Magento\Framework\Registry; use \Magento\Newsletter\Model\Subscriber; use \Magento\Customer\Model\Group; -use \Remarkety\Mgconnector\Model\Queue; +use Magento\Quote\Api\CartRepositoryInterface; +use Remarkety\Mgconnector\Model\QueueRepository; +use Remarkety\Mgconnector\Helper\ConfigHelper; use \Magento\Store\Model\Store; use Magento\Store\Model\StoreManager; use \Magento\Framework\App\Config\ScopeConfigInterface; use \Magento\Checkout\Model\Session as CheckoutSession; +use Remarkety\Mgconnector\Serializer\AddressSerializer; +use Remarkety\Mgconnector\Serializer\CustomerSerializer; +use Remarkety\Mgconnector\Serializer\OrderSerializer; +use Remarkety\Mgconnector\Serializer\ProductSerializer; +use Psr\Log\LoggerInterface; class TriggerSubscribeUpdateObserver extends EventMethods implements ObserverInterface { protected $_subscriber = null; protected $_checkoutSession; -// protected $_coreRegistry; + protected $cartRepository; + protected $session; + protected $remoteAddress; public function __construct( + LoggerInterface $logger, Session $customerSession, CheckoutSession $CheckoutSession, Registry $registry, Subscriber $subscriber, Group $customerGroupModel, - Queue $remarketyQueue, + QueueRepository $remarketyQueueRepo, Store $store, ScopeConfigInterface $scopeConfig, - StoreManager $sManager + StoreManager $sManager, + OrderSerializer $orderSerializer, + CustomerSerializer $customerSerializer, + AddressSerializer $addressSerializer, + ConfigHelper $configHelper, + ProductSerializer $productSerializer, + CartRepositoryInterface $cartRepository, + Http $request, + CustomerRepository $customerRepository, + \Remarkety\Mgconnector\Model\QueueFactory $queueFactory, + CustomerRegistry $customerRegistry, + RemoteAddress $remoteAddress ){ - parent::__construct($registry, $subscriber, $customerGroupModel, $remarketyQueue, $store, $scopeConfig); + parent::__construct($logger, $registry, $subscriber, $customerGroupModel, $remarketyQueueRepo, $queueFactory, $store, $scopeConfig, $orderSerializer, $customerSerializer, $addressSerializer, $configHelper, $productSerializer, $request, $customerRepository, $customerRegistry); $this->session = $customerSession; $this->_checkoutSession = $CheckoutSession; $this->_store = $sManager->getStore(); + $this->cartRepository = $cartRepository; + $this->remoteAddress = $remoteAddress; } /** * Apply catalog price rules to product in admin @@ -42,31 +69,53 @@ public function __construct( * @return $this */ public function execute(\Magento\Framework\Event\Observer $observer){ - $this->_subscriber = $observer->getEvent()->getSubscriber(); + try { + /** + * @var $subscriber Subscriber + */ + $subscriber = $observer->getEvent()->getSubscriber(); - if(!$this->_coreRegistry->registry('subscriber_object_data_observer')) - $this->_coreRegistry->register('subscriber_object_data_observer', $this->_subscriber); + if(!$this->_coreRegistry->registry('subscriber_object_data_observer')) + $this->_coreRegistry->register('subscriber_object_data_observer', 1); - if($this->_subscriber->getId() && !$this->session->isLoggedIn()) { - if($this->_subscriber->getCustomerId() && $this->_coreRegistry->registry('remarkety_customer_save_observer_executed_'.$this->_subscriber->getCustomerId())) { - return $this; - } - if ($this->_coreRegistry->registry('remarkety_subscriber_deleted')) - return $this; - $this->makeRequest('customers/create', $this->_prepareCustomerSubscribtionUpdateData()); + if($subscriber->getId()) { + if ($this->_coreRegistry->registry('remarkety_subscriber_deleted_' . $subscriber->getSubscriberEmail())) + return $this; - $email = $this->_subscriber->getSubscriberEmail(); - if(!empty($email)){ - //for webtracking use - $this->session->setSubscriberEmail($email); - //add email to cart - $cart = $this->_checkoutSession->getQuote(); - if($cart && !is_null($cart->getId()) && is_null($cart->getCustomerEmail())){ - $cart->setCustomerEmail($email)->save(); + $status = $subscriber->getStatus(); + $eventType = 'newsletter/subscribed'; + switch($status){ + case Subscriber::STATUS_SUBSCRIBED: + $eventType = 'newsletter/subscribed'; + break; + case Subscriber::STATUS_UNSUBSCRIBED: + $eventType = 'newsletter/unsubscribed'; + break; + case Subscriber::STATUS_UNCONFIRMED: + return $this; + case Subscriber::STATUS_NOT_ACTIVE: + return $this; + } + + $this->makeRequest($eventType, $this->_prepareCustomerSubscribtionUpdateData($subscriber, $this->remoteAddress->getRemoteAddress())); + + if($this->_store->getId() != 0){ + $email = $subscriber->getSubscriberEmail(); + if(!empty($email)){ + //for webtracking use + $this->session->setSubscriberEmail($email); + //add email to cart + $cart = $this->_checkoutSession->getQuote(); + if($cart && !is_null($cart->getId()) && is_null($cart->getCustomerEmail())){ + $cart->setCustomerEmail($email); + $this->cartRepository->save($cart); + } + } } } + } catch (\Exception $ex){ + $this->logError($ex); } - return $this; } } diff --git a/Observer/TriggerSubtractQuoteInventory.php b/Observer/TriggerSubtractQuoteInventory.php new file mode 100644 index 0000000..5c7bfd7 --- /dev/null +++ b/Observer/TriggerSubtractQuoteInventory.php @@ -0,0 +1,47 @@ +shouldSendProductUpdates()){ + return; + } + + /** + * @var $order Order + */ + $order = $observer->getEvent()->getOrder(); + if($order) { + foreach ($order->getAllItems() as $item) { + $product = $this->productSerializer->loadProduct($item->getProductId()); + $storeIds = $product->getStoreIds(); + if (!empty($storeIds)) { + foreach ($storeIds as $storeId) { + if ($this->isWebhooksEnabled($storeId)) { + $data = $this->productSerializer->serialize($product, $storeId); + $this->makeRequest(self::EVENT_PRODUCTS_UPDATED, $data, $storeId); + } + } + } + } + } + } catch (\Exception $ex){ + $this->logError($ex); + } + } +} diff --git a/Serializer/AddressSerializer.php b/Serializer/AddressSerializer.php new file mode 100644 index 0000000..a5ec607 --- /dev/null +++ b/Serializer/AddressSerializer.php @@ -0,0 +1,43 @@ +_countryFactory = $countryFactory; + } + + /** + * @param \Magento\Sales\Model\Order\Address|\Magento\Customer\Api\Data\AddressInterface $address + * @return array + */ + public function serialize($address){ + $country = $this->_countryFactory->create()->loadByCode($address->getCountryId()); + $region = $address->getRegion(); + $data = [ + 'first_name' => $address->getFirstname(), + 'last_name' => $address->getLastname(), + 'city' => $address->getCity(), + 'street' => implode(PHP_EOL, $address->getStreet()), + 'country_code' => $address->getCountryId(), + 'country' => $country->getName(), + 'zip' => $address->getPostcode(), + 'phone' => $address->getTelephone(), + 'region' => !empty($region) ? $region->getRegionCode() : null + ]; + return $data; + } +} diff --git a/Serializer/CustomerSerializer.php b/Serializer/CustomerSerializer.php new file mode 100644 index 0000000..037f46e --- /dev/null +++ b/Serializer/CustomerSerializer.php @@ -0,0 +1,73 @@ +subscriber = $subscriber; + $this->addressSerializer = $addressSerializer; + $this->customerGroupRepository = $customerGroupRepository; + } + public function serialize(\Magento\Customer\Api\Data\CustomerInterface $customer){ + $checkSubscriber = $this->subscriber->loadByEmail($customer->getEmail()); + + $created_at = new \DateTime($customer->getCreatedAt()); + $updated_at = new \DateTime($customer->getUpdatedAt()); + + $groups = []; + if(!empty($customer->getGroupId())){ + $group = $this->customerGroupRepository->getById($customer->getGroupId()); + $groups[] = [ + 'id' => $group->getId(), + 'name' => $group->getCode(), + ]; + } + $gender = null; + switch($customer->getGender()){ + case 1: + $gender = 'male'; + break; + case 2: + $gender = 'female'; + break; + } + + $address = $customer->getAddresses(); + $customerInfo = [ + 'email' => $customer->getEmail(), + 'accepts_marketing' => $checkSubscriber->isSubscribed(), + 'title' => $customer->getPrefix(), + 'first_name' => $customer->getFirstname(), + 'last_name' => $customer->getLastname(), + 'created_at' => $created_at->format(\DateTime::ATOM ), + 'updated_at' => $updated_at->format(\DateTime::ATOM ), + 'guest' => false, + 'default_address' => empty($address) ? null : $this->addressSerializer->serialize($address[0]), + 'groups' => $groups, + 'gender' => $gender, + 'birthdate' => $customer->getDob() + ]; + + return $customerInfo; + } +} diff --git a/Serializer/OrderSerializer.php b/Serializer/OrderSerializer.php new file mode 100644 index 0000000..6312c8e --- /dev/null +++ b/Serializer/OrderSerializer.php @@ -0,0 +1,143 @@ +customerRepository = $customerRepository; + $this->statusCollection = $statusCollection; + $this->remarketyHelper = $remarketyHelper; + $this->addressSerializer = $addressSerializer; + $this->customerSerializer = $customerSerializer; + $this->subscriber = $subscriber; + } + + public function serialize(\Magento\Sales\Model\Order $order){ + $status = $this->statusCollection->getItemByColumnValue('status', $order->getStatus()); + /** + * @var $items \Magento\Sales\Model\Order\Item[] + */ + $items = $order->getAllVisibleItems(); + $line_items = []; + foreach($items as $item){ + $itemArr = [ + //'product_parent_id' => $rmCore->getProductParentId($item->getProduct()), + 'product_id' => $item->getProductId(), + 'sku' => $item->getSku(), + 'quantity' => (float)$item->getQtyOrdered(), + 'quantity_refunded' => $item->getQtyRefunded(), + 'quantity_shipped' => $item->getQtyShipped(), + 'name' => $item->getName(), + 'title' => $item->getProduct()->getName(), + 'price' => (float)$item->getPrice(), + 'url' => $item->getProduct()->getProductUrl(), + 'images' => $this->remarketyHelper->getMediaGalleryImages($item->getProduct()) + ]; + + $line_items[] = $itemArr; + } + + $created_at = new \DateTime($order->getCreatedAt()); + $updated_at = new \DateTime($order->getUpdatedAt()); + + $customerId = $order->getCustomerId(); + if(!$order->getCustomerIsGuest()){ + $customer = $this->customerRepository->getById($order->getCustomerId()); + $customerInfo = $this->customerSerializer->serialize($customer); + } else { + $checkSubscriber = $this->subscriber->loadByEmail($order->getCustomerEmail()); + + $customerInfo = [ + 'accepts_marketing' => $checkSubscriber->isSubscribed(), + 'email' => $order->getCustomerEmail(), + 'title' => $order->getBillingAddress()->getPrefix(), + 'first_name' => $order->getBillingAddress()->getFirstname(), + 'last_name' => $order->getBillingAddress()->getLastname(), + 'created_at' => $created_at->format(\DateTime::ATOM ), + 'updated_at' => $created_at->format(\DateTime::ATOM ), + 'guest' => true, + 'default_address' => $this->addressSerializer->serialize($order->getBillingAddress()) + ]; + } + + $shipping_lines = []; + /** + * @var $shipments Shipment[] + */ + $shipments = $order->getShipmentsCollection(); + foreach($shipments as $shipment){ + /** + * @var $trackings Shipment\Track[] + */ + $trackings = $shipment->getAllTracks(); + foreach($trackings as $tracking){ + $shipping_lines[] = [ + 'tracking_number' => $tracking->getTrackNumber(), + 'title' => $tracking->getTitle() + ]; + } + } + + $payment = $order->getPayment(); + $method = $payment->getMethodInstance(); + $paymentMethodTitle = $method->getTitle(); + + $discount_codes = []; + $coupon = $order->getCouponCode(); + if(!empty($coupon)){ + $discount_codes[] = [ + 'code' => $coupon, + 'amount' => (float)$order->getDiscountAmount() + ]; + } + + $data = [ + 'id' => empty($order->getOriginalIncrementId()) ? $order->getIncrementId() : $order->getOriginalIncrementId(), + 'name' => $order->getIncrementId(), + 'created_at' => $created_at->format(\DateTime::ATOM ), + 'updated_at' => $updated_at->format(\DateTime::ATOM ), + 'currency' => $order->getOrderCurrencyCode(), + 'email' => $order->getCustomerEmail(), + 'discount_codes' => $discount_codes, + 'payment_method' => $paymentMethodTitle, + 'note' => $order->getCustomerNote(), + 'status' => [ + 'code' => $status->getStatus(), + 'name' => $status->getLabel() + ], + 'subtotal_price' => (float)$order->getSubtotal(), + 'total_discounts' => (float)$order->getDiscountAmount(), + 'total_price' => (float)$order->getGrandTotal(), + 'total_shipping' => (float)$order->getShippingAmount(), + 'total_tax' => (float)$order->getTaxAmount(), + 'customer' => $customerInfo, + 'shipping_address' => $this->addressSerializer->serialize($order->getShippingAddress()), + 'billing_address' => $this->addressSerializer->serialize($order->getBillingAddress()), + 'shipping_lines' => $shipping_lines, + 'line_items' => $line_items + ]; + return $data; + } +} diff --git a/Serializer/ProductSerializer.php b/Serializer/ProductSerializer.php new file mode 100644 index 0000000..cc56002 --- /dev/null +++ b/Serializer/ProductSerializer.php @@ -0,0 +1,182 @@ +categoryFactory = $categoryFactory; + $this->catalogProductTypeConfigurable = $catalogProductTypeConfigurable; + $this->productRepository = $productRepository; + $this->dataHelper = $dataHelper; + $this->urlModel = $urlModel; + $this->stockRegistry = $stockRegistry; + } + + public function loadProduct($product_id){ + return $this->productRepository->getById($product_id); + } + + public function serialize(ProductInterface $product, $storeId){ + + $parent_id = null; + if($product->getTypeId() == 'simple'){ + $parent_id = $this->dataHelper->getParentId($product->getId()); + if(!empty($parent_id)) { + $parentProduct = $this->loadProduct($parent_id); + } + } + + $created_at = new \DateTime($product->getCreatedAt()); + $updated_at = new \DateTime($product->getUpdatedAt()); + + $enabled = $product->getStatus() == Status::STATUS_ENABLED && $product->getVisibility() != Visibility::VISIBILITY_NOT_VISIBLE; + + $variants = []; + + if(!empty($parentProduct)){ + $parentProduct->setStoreId($storeId); + $url = $parentProduct->getProductUrl(false); + $images = $this->dataHelper->getMediaGalleryImages($parentProduct); + $categoryIds = $parentProduct->getCategoryIds(); + + //contain only the current product stock level + $stock = $this->stockRegistry->getStockItem($product->getId()); + $variants[] = [ + 'inventory_quantity' => $stock->getQty(), + 'price' => (float)$product->getPrice() + ]; + + } else { + $product->setStoreId($storeId); + $categoryIds = $product->getCategoryIds(); + $url = $product->getProductUrl(false); + $images = $this->dataHelper->getMediaGalleryImages($product); + + if($product->getTypeId() == Configurable::TYPE_CODE){ + //configurable products sends variants + $childrenIdsGroups = $this->catalogProductTypeConfigurable->getChildrenIds($product->getId()); + if(isset($childrenIdsGroups[0])) { + $childrenIds = $childrenIdsGroups[0]; + foreach ($childrenIds as $childId) { + $childProd = $this->loadProduct($childId); + $stock = $this->stockRegistry->getStockItem($childId); + + $created_at_child = new \DateTime($childProd->getCreatedAt()); + $updated_at_child = new \DateTime($childProd->getUpdatedAt()); + + $variants[] = [ + 'id' => $childProd->getId(), + 'sku' => $childProd->getSku(), + 'title' => $childProd->getName(), + 'created_at' => $created_at_child->format(\DateTime::ATOM), + 'updated_at' => $updated_at_child->format(\DateTime::ATOM), + 'inventory_quantity' => $stock->getQty(), + 'price' => (float)$childProd->getPrice() + ]; + } + } + } else { + $stock = $this->stockRegistry->getStockItem($product->getId()); + $variants[] = [ + 'inventory_quantity' => $stock->getQty(), + 'price' => (float)$product->getPrice() + ]; + } + + } + + $categories = []; + if(!empty($categoryIds)){ + foreach($categoryIds as $categoryId){ + $categories[] = $this->dataHelper->getCategory($categoryId); + } + } + + + $options = []; + + $data = [ + 'id' => $product->getId(), + 'sku' => $product->getSku(), + 'title' => $product->getName(), + 'categories' => $categories, + 'created_at' => $created_at->format(\DateTime::ATOM ), + 'updated_at' => $updated_at->format(\DateTime::ATOM ), + 'images' => $images, + 'enabled' => $enabled, + 'price' => (float)$product->getPrice(), + 'url' => $url, + 'variants' => $variants, + 'options' => $options + ]; + if(!empty($parent_id)){ + $data['parent_id'] = $parent_id; + } + return $data; + + /** + * $data = array( + 'id' => $product->getId(), + 'sku' => $product->getSku(), + 'title' => $rmCore->getProductName($product, $storeId), + 'body_html' => '', + 'categories' => $categories, + 'created_at' => $product->getCreatedAt(), + 'updated_at' => $product->getUpdatedAt(), + 'images' => $this->getProductImages($product), + 'enabled' => $enabled, + 'price' => $price, + 'special_price' => $special_price, + 'url' => $url, + 'parent_id' => $rmCore->getProductParentId($product), + 'variants' => array( + array( + 'inventory_quantity' => $stocklevel, + 'price' => $price + ) + ) + ); + */ + } + + public function getParentId($id) + { + $parentByChild = $this->_catalogProductTypeConfigurable->getParentIdsByChild($id); + if (isset($parentByChild[0])) { + $id = $parentByChild[0]; + return $id; + } + return false; + } +} diff --git a/Setup/UpgradeSchema.php b/Setup/UpgradeSchema.php new file mode 100644 index 0000000..246e272 --- /dev/null +++ b/Setup/UpgradeSchema.php @@ -0,0 +1,36 @@ +startSetup(); + $tableName = $setup->getTable('mgconnector_queue'); + if (version_compare($context->getVersion(), '2.2.0', '<')) { + if ($setup->getConnection()->isTableExists($tableName) == true) { + $connection = $setup->getConnection(); + $connection->addColumn( + $tableName, + 'store_id', + ['type' => Table::TYPE_INTEGER,'nullable' => false, 'default' => 0, 'afters' => 'queue_id', 'comment' => 'Magento store id'] + ); + $connection->addColumn( + $tableName, + 'last_error_message', + ['type' => Table::TYPE_TEXT,'nullable' => false, 'default' => '', 'comment' => 'last error message'] + ); + } + } + + + $setup->endSetup(); + + } +} diff --git a/composer.json b/composer.json index 4d84b11..403a8b4 100644 --- a/composer.json +++ b/composer.json @@ -10,7 +10,7 @@ "lib-libxml": "*" }, "type": "magento2-module", - "version": "2.1.9-p4", + "version": "2.2.0", "license": [ "OSL-3.0", "AFL-3.0" diff --git a/etc/events.xml b/etc/events.xml index 1d0471b..50a450f 100644 --- a/etc/events.xml +++ b/etc/events.xml @@ -3,13 +3,13 @@ - + - + @@ -18,4 +18,40 @@ - \ No newline at end of file + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/etc/module.xml b/etc/module.xml index 18e3dad..4d78fd6 100644 --- a/etc/module.xml +++ b/etc/module.xml @@ -1,5 +1,5 @@ - + diff --git a/etc/webapi.xml b/etc/webapi.xml index dba2a85..ca8f5de 100644 --- a/etc/webapi.xml +++ b/etc/webapi.xml @@ -55,4 +55,40 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/view/adminhtml/layout/mgconnector_install_install.xml b/view/adminhtml/layout/mgconnector_install_install.xml index 7da77b1..3827505 100644 --- a/view/adminhtml/layout/mgconnector_install_install.xml +++ b/view/adminhtml/layout/mgconnector_install_install.xml @@ -6,10 +6,9 @@ - - \ No newline at end of file + diff --git a/view/adminhtml/templates/a.phtml b/view/adminhtml/templates/a.phtml index b856054..25c56d2 100644 --- a/view/adminhtml/templates/a.phtml +++ b/view/adminhtml/templates/a.phtml @@ -13,11 +13,28 @@ if($this->getHelperMode() == 'complete'){ echo $block->getChildHtml('remarkety_complete'); } - if($this->getHelperMode() == 'welcome') { - echo $block->getChildHtml('remarkety_welcome'); - echo $block->getChildHtml('remarkety_store'); - } - ?> + if($this->getHelperMode() == 'welcome'): ?> + getChildHtml('remarkety_welcome'); ?> + +
+ configHelper->isWebhooksGloballyEnabled()): ?> + + + + + + +
+ + getStoresGrid(); ?> + +