/**
  * Execute method.
  *
  * @param \Magento\Framework\Event\Observer $observer
  *
  * @return $this
  * @codingStandardsIgnoreStart
  */
 public function execute(\Magento\Framework\Event\Observer $observer)
 {
     //@codingStandardsIgnoreEnd
     $groups = $this->context->getRequest()->getPost('groups');
     if (isset($groups['api']['fields']['username']['inherit']) || isset($groups['api']['fields']['password']['inherit'])) {
         return $this;
     }
     $apiUsername = isset($groups['api']['fields']['username']['value']) ? $groups['api']['fields']['username']['value'] : false;
     $apiPassword = isset($groups['api']['fields']['password']['value']) ? $groups['api']['fields']['password']['value'] : false;
     //skip if the inherit option is selected
     if ($apiUsername && $apiPassword) {
         $this->helper->log('----VALIDATING ACCOUNT---');
         $isValid = $this->test->validate($apiUsername, $apiPassword);
         if ($isValid) {
             //save endpoint for account
             foreach ($isValid->properties as $property) {
                 if ($property->name == 'ApiEndpoint' && !empty($property->value)) {
                     $this->saveApiEndpoint($property->value);
                     break;
                 }
             }
             $this->messageManager->addSuccessMessage(__('API Credentials Valid.'));
         } else {
             $this->messageManager->addWarningMessage(__('Authorization has been denied for this request.'));
         }
     }
     return $this;
 }
 /**
  * Products collection.
  *
  * @return array
  */
 public function getLoadedProductCollection()
 {
     $productsToDisplay = [];
     $mode = $this->getRequest()->getActionName();
     $customerId = $this->getRequest()->getParam('customer_id');
     $limit = $this->recommnededHelper->getDisplayLimitByMode($mode);
     //login customer to receive the recent products
     $session = $this->sessionFactory->create();
     $isLoggedIn = $session->loginById($customerId);
     $collection = $this->viewed;
     $productItems = $collection->getItemsCollection()->setPageSize($limit);
     //get the product ids from items collection
     $productIds = $productItems->getColumnValues('product_id');
     //get product collection to check for salable
     $productCollection = $this->productFactory->create()->getCollection()->addAttributeToSelect('*')->addFieldToFilter('entity_id', ['in' => $productIds]);
     //show products only if is salable
     foreach ($productCollection as $product) {
         if ($product->isSalable()) {
             $productsToDisplay[$product->getId()] = $product;
         }
     }
     $this->helper->log('Recentlyviewed customer  : ' . $customerId . ', mode ' . $mode . ', limit : ' . $limit . ', items found : ' . count($productItems) . ', is customer logged in : ' . $isLoggedIn . ', products :' . count($productsToDisplay));
     $session->logout();
     return $productsToDisplay;
 }
 /**
  * If it's configured to capture on shipment - do this.
  *
  * @param \Magento\Framework\Event\Observer $observer
  *
  * @return $this
  */
 public function execute(\Magento\Framework\Event\Observer $observer)
 {
     $customer = $observer->getEvent()->getCustomer();
     $email = $customer->getEmail();
     $websiteId = $customer->getWebsiteId();
     $customerId = $customer->getEntityId();
     $isSubscribed = $customer->getIsSubscribed();
     try {
         // fix for a multiple hit of the observer
         $emailReg = $this->registry->registry($email . '_customer_save');
         if ($emailReg) {
             return $this;
         }
         $this->registry->register($email . '_customer_save', $email);
         $emailBefore = $this->customerFactory->create()->load($customer->getId())->getEmail();
         $contactModel = $this->contactFactory->create()->loadByCustomerEmail($emailBefore, $websiteId);
         //email change detection
         if ($email != $emailBefore) {
             $this->helper->log('email change detected : ' . $email . ', after : ' . $emailBefore . ', website id : ' . $websiteId);
             $data = ['emailBefore' => $emailBefore, 'email' => $email, 'isSubscribed' => $isSubscribed];
             $this->importerFactory->registerQueue(\Dotdigitalgroup\Email\Model\Importer::IMPORT_TYPE_CONTACT_UPDATE, $data, \Dotdigitalgroup\Email\Model\Importer::MODE_CONTACT_EMAIL_UPDATE, $websiteId);
         } elseif (!$emailBefore) {
             //for new contacts update email
             $contactModel->setEmail($email);
         }
         $contactModel->setEmailImported(\Dotdigitalgroup\Email\Model\Contact::EMAIL_CONTACT_NOT_IMPORTED)->setCustomerId($customerId)->save();
     } catch (\Exception $e) {
         $this->helper->debug((string) $e, []);
     }
     return $this;
 }
 /**
  * Export guests for a website.
  *
  * @param $website
  *
  * @throws \Magento\Framework\Exception\LocalizedException
  */
 public function exportGuestPerWebsite($website)
 {
     $guests = $this->contactFactory->create()->getGuests($website);
     //found some guests
     if ($guests->getSize()) {
         $guestFilename = strtolower($website->getCode() . '_guest_' . date('d_m_Y_Hi') . '.csv');
         $this->helper->log('Guest file: ' . $guestFilename);
         $storeName = $this->helper->getMappedStoreName($website);
         $this->file->outputCSV($this->file->getFilePath($guestFilename), ['Email', 'emailType', $storeName]);
         foreach ($guests as $guest) {
             $email = $guest->getEmail();
             try {
                 //@codingStandardsIgnoreStart
                 $guest->setEmailImported(\Dotdigitalgroup\Email\Model\Contact::EMAIL_CONTACT_IMPORTED);
                 $guest->getResource()->save($guest);
                 //@codingStandardsIgnoreEnd
                 $storeName = $website->getName();
                 // save data for guests
                 $this->file->outputCSV($this->file->getFilePath($guestFilename), [$email, 'Html', $storeName]);
                 ++$this->countGuests;
             } catch (\Exception $e) {
                 throw new \Magento\Framework\Exception\LocalizedException(__($e->getMessage()));
             }
         }
         if ($this->countGuests) {
             //register in queue with importer
             $this->importerFactory->create()->registerQueue(\Dotdigitalgroup\Email\Model\Importer::IMPORT_TYPE_GUEST, '', \Dotdigitalgroup\Email\Model\Importer::MODE_BULK, $website->getId(), $guestFilename);
         }
     }
 }
 /**
  * Execute method.
  *
  * @param \Magento\Framework\Event\Observer $observer
  *
  * @return $this
  * @codingStandardsIgnoreStart
  */
 public function execute(\Magento\Framework\Event\Observer $observer)
 {
     //@codingStandardsIgnoreEnd
     $contactModel = $this->contactResourceFactory->create();
     $numImported = $this->contactFactory->create()->getNumberOfImportedContacs();
     $updated = $contactModel->resetAllContacts();
     $this->helper->log('-- Imported contacts: ' . $numImported . ' reseted :  ' . $updated . ' --');
     return $this;
 }
 /**
  * Export subscribers per website.
  *
  * @param $website
  *
  * @return int
  *
  * @throws LocalizedException
  */
 public function exportSubscribersPerWebsite($website)
 {
     $updated = 0;
     $limit = $this->helper->getSyncLimit($website->getId());
     //subscriber collection to import
     $subscribers = $this->contactFactory->create()->getSubscribersToImport($website, $limit);
     if ($subscribers->getSize()) {
         $subscribersFilename = strtolower($website->getCode() . '_subscribers_' . date('d_m_Y_Hi') . '.csv');
         //get mapped storename
         $subscriberStoreName = $this->helper->getMappedStoreName($website);
         //file headers
         $this->file->outputCSV($this->file->getFilePath($subscribersFilename), ['Email', 'emailType', $subscriberStoreName]);
         $emails = $subscribers->getColumnValues('email');
         $subscriberFactory = $this->subscriberFactory->create();
         $subscribersData = $subscriberFactory->getCollection()->addFieldToFilter('subscriber_email', ['in' => $emails])->addFieldToSelect(['subscriber_email', 'store_id'])->toArray();
         foreach ($subscribers as $subscriber) {
             $email = $subscriber->getEmail();
             $storeId = $this->getStoreIdForSubscriber($email, $subscribersData['items']);
             $storeName = $this->storeManager->getStore($storeId)->getName();
             // save data for subscribers
             $this->file->outputCSV($this->file->getFilePath($subscribersFilename), [$email, 'Html', $storeName]);
             //@codingStandardsIgnoreStart
             $subscriber->setSubscriberImported(1)->save();
             //@codingStandardsIgnoreEnd
             ++$updated;
         }
         $this->helper->log('Subscriber filename: ' . $subscribersFilename);
         //register in queue with importer
         $this->importerFactory->create()->registerQueue(\Dotdigitalgroup\Email\Model\Importer::IMPORT_TYPE_SUBSCRIBERS, '', \Dotdigitalgroup\Email\Model\Importer::MODE_BULK, $website->getId(), $subscribersFilename);
     }
     //add updated number for the website
     $this->countSubscriber += $updated;
     return $updated;
 }
 /**
  * Sync reviews.
  *
  * @return array
  */
 public function sync()
 {
     $response = ['success' => true, 'message' => 'Done.'];
     $this->countReviews = 0;
     $this->reviews = [];
     $this->start = microtime(true);
     $websites = $this->helper->getwebsites(true);
     foreach ($websites as $website) {
         $apiEnabled = $this->helper->isEnabled($website);
         $reviewEnabled = $this->helper->getWebsiteConfig(\Dotdigitalgroup\Email\Helper\Config::XML_PATH_CONNECTOR_SYNC_REVIEW_ENABLED, $website);
         $storeIds = $website->getStoreIds();
         if ($apiEnabled && $reviewEnabled && !empty($storeIds)) {
             $this->_exportReviewsForWebsite($website);
         }
         if (isset($this->reviews[$website->getId()])) {
             $reviews = $this->reviews[$website->getId()];
             //send reviews as transactional data
             //register in queue with importer
             $this->importerFactory->create()->registerQueue(\Dotdigitalgroup\Email\Model\Importer::IMPORT_TYPE_REVIEWS, $reviews, \Dotdigitalgroup\Email\Model\Importer::MODE_BULK, $website->getId());
             //if no error then set imported
             $this->_setImported($this->reviewIds);
             //@codingStandardsIgnoreStart
             $this->countReviews += count($reviews);
             //@codingStandardsIgnoreStop
         }
     }
     if ($this->countReviews) {
         $message = 'Total time for sync : ' . gmdate('H:i:s', microtime(true) - $this->start) . ', Total synced = ' . $this->countReviews;
         $this->helper->log($message);
         $response['message'] = $message;
     }
     return $response;
 }
 /**
  * Easy email capture for Newsletter and Checkout.
  */
 public function execute()
 {
     if ($this->getRequest()->getParam('email') && ($quote = $this->checkoutSession->getQuote())) {
         $email = $this->getRequest()->getParam('email');
         if ($quote->hasItems()) {
             try {
                 $quote->setCustomerEmail($email);
                 $quote->getResource()->save($quote);
                 $this->helper->log('ajax emailCapture email: ' . $email);
             } catch (\Exception $e) {
                 $this->helper->debug((string) $e, []);
                 $this->helper->log('ajax emailCapture fail for email: ' . $email);
             }
         }
     }
 }
 /**
  * Sync Wishlists.
  *
  * @return array
  *
  * @throws \Magento\Framework\Exception\LocalizedException
  */
 public function sync()
 {
     $response = ['success' => true, 'message' => 'Done.'];
     $websites = $this->helper->getWebsites();
     foreach ($websites as $website) {
         $wishlistEnabled = $this->helper->getWebsiteConfig(\Dotdigitalgroup\Email\Helper\Config::XML_PATH_CONNECTOR_SYNC_WISHLIST_ENABLED, $website);
         $apiEnabled = $this->helper->isEnabled($website);
         $storeIds = $website->getStoreIds();
         if ($wishlistEnabled && $apiEnabled && !empty($storeIds)) {
             //using bulk api
             $this->start = microtime(true);
             $this->exportWishlistForWebsite($website);
             //send wishlist as transactional data
             if (isset($this->wishlists[$website->getId()])) {
                 $websiteWishlists = $this->wishlists[$website->getId()];
                 //register in queue with importer
                 $this->importerFactory->create()->registerQueue(\Dotdigitalgroup\Email\Model\Importer::IMPORT_TYPE_WISHLIST, $websiteWishlists, \Dotdigitalgroup\Email\Model\Importer::MODE_BULK, $website->getId());
                 //mark connector wishlist as  imported
                 $this->setImported($this->wishlistIds);
             }
             if (!empty($this->wishlists)) {
                 $message = 'Total time for wishlist bulk sync : ' . gmdate('H:i:s', microtime(true) - $this->start);
                 $this->helper->log($message);
             }
             //using single api
             $this->exportWishlistForWebsiteInSingle($website);
         }
     }
     $response['message'] = 'wishlists updated: ' . $this->countWishlists;
     return $response;
 }
 /**
  * Create certain address books.
  *
  * @param $username
  * @param $password
  *
  * @return bool
  */
 public function createAddressBooks($username, $password)
 {
     $addressBooks = [['name' => 'Magento_Customers', 'visibility' => 'Private'], ['name' => 'Magento_Subscribers', 'visibility' => 'Private'], ['name' => 'Magento_Guests', 'visibility' => 'Private']];
     $addressBookMap = ['Magento_Customers' => Config::XML_PATH_CONNECTOR_CUSTOMERS_ADDRESS_BOOK_ID, 'Magento_Subscribers' => Config::XML_PATH_CONNECTOR_SUBSCRIBERS_ADDRESS_BOOK_ID, 'Magento_Guests' => Config::XML_PATH_CONNECTOR_GUEST_ADDRESS_BOOK_ID];
     $error = false;
     $client = false;
     if ($this->helper->isEnabled()) {
         $client = $this->helper->getWebsiteApiClient(0, $username, $password);
     }
     if (!$client) {
         $error = true;
         $this->helper->log('createAddressBooks client is not enabled');
     } else {
         foreach ($addressBooks as $addressBook) {
             $addressBookName = $addressBook['name'];
             $visibility = $addressBook['visibility'];
             if (!empty($addressBookName)) {
                 $response = $client->postAddressBooks($addressBookName, $visibility);
                 if (isset($response->message)) {
                     $error = true;
                 } else {
                     //map the successfully created address book
                     $this->helper->saveConfigData($addressBookMap[$addressBookName], $response->id, 'default', 0);
                     $this->helper->log('successfully connected address book : ' . $addressBookName);
                 }
             }
         }
     }
     return $error == true ? false : true;
 }
 /**
  * Validate apiuser on save.
  *
  * @param string $apiUsername
  * @param string $apiPassword
  *
  * @return bool|mixed
  */
 public function validate($apiUsername, $apiPassword)
 {
     if (!$this->helper->isEnabled()) {
         return false;
     }
     $client = $this->helper->getWebsiteApiClient();
     if ($apiUsername && $apiPassword) {
         $client->setApiUsername($apiUsername)->setApiPassword($apiPassword);
         $accountInfo = $client->getAccountInfo();
         if (isset($accountInfo->message)) {
             $this->helper->log('VALIDATION ERROR :  ' . $accountInfo->message);
             return false;
         }
         return $accountInfo;
     }
     return false;
 }
 /**
  * Initial sync the transactional data.
  *
  * @return array
  *
  * @throws \Magento\Framework\Exception\LocalizedException
  */
 public function sync()
 {
     $response = ['success' => true, 'message' => 'Done.'];
     // Initialise a return hash containing results of our sync attempt
     $this->_searchAccounts();
     foreach ($this->accounts as $account) {
         $orders = $account->getOrders();
         $orderIds = $account->getOrderIds();
         $ordersForSingleSync = $account->getOrdersForSingleSync();
         $orderIdsForSingleSync = $account->getOrderIdsForSingleSync();
         //@codingStandardsIgnoreStart
         $numOrdersForSingleSync = count($ordersForSingleSync);
         $website = $account->getWebsites();
         $numOrders = count($orders);
         //@codingStandardsIgnoreEnd
         $this->countOrders += $numOrders;
         $this->countOrders += $numOrdersForSingleSync;
         //send transactional for any number of orders set
         if ($numOrders) {
             $this->helper->log('--------- Order sync ---------- : ' . $numOrders);
             //queue order into importer
             $this->helper->error('orders', $orders);
             try {
                 $this->importerFactory->create()->registerQueue(\Dotdigitalgroup\Email\Model\Importer::IMPORT_TYPE_ORDERS, $orders, \Dotdigitalgroup\Email\Model\Importer::MODE_BULK, $website[0]);
             } catch (\Exception $e) {
                 $this->helper->debug((string) $e, []);
             }
             $this->_setImported($orderIds);
             $this->helper->log('----------end order sync----------');
         }
         if ($numOrdersForSingleSync) {
             $error = false;
             foreach ($ordersForSingleSync as $order) {
                 $this->helper->log('--------- register Order sync in single with importer ---------- : ');
                 //register in queue with importer
                 $this->importerFactory->create()->registerQueue(\Dotdigitalgroup\Email\Model\Importer::IMPORT_TYPE_ORDERS, $order, \Dotdigitalgroup\Email\Model\Importer::MODE_SINGLE, $website[0]);
                 $this->helper->log('----------end order sync in single----------');
             }
             //if no error then set imported
             if (!$error) {
                 $this->_setImported($orderIdsForSingleSync, true);
             }
         }
         unset($this->accounts[$account->getApiUsername()]);
     }
     /**
      * Add guest to contacts table.
      */
     if (!empty($this->guests)) {
         $this->contactFactory->create()->insert($this->guests);
     }
     if ($this->countOrders) {
         $response['message'] = 'Orders updated ' . $this->countOrders;
     }
     return $response;
 }
 /**
  * Execute method.
  */
 public function execute()
 {
     $result = ['errors' => false, 'message' => ''];
     $website = $this->getRequest()->getParam('website', 0);
     $client = false;
     if ($this->data->isEnabled()) {
         $client = $this->data->getWebsiteApiClient($website);
     }
     $redirectUrl = $this->getUrl('adminhtml/system_config/edit', ['section' => 'connector_developer_settings']);
     if (!$client) {
         $this->messageManager->addNoticeMessage('Please enable api first.');
     } else {
         // get all possible datatifileds
         $datafields = $this->datafield->getContactDatafields();
         foreach ($datafields as $key => $datafield) {
             $response = $client->postDataFields($datafield);
             //ignore existing datafields message
             if (isset($response->message) && $response->message != \Dotdigitalgroup\Email\Model\Apiconnector\Client::API_ERROR_DATAFIELD_EXISTS) {
                 $result['errors'] = true;
                 $result['message'] .= ' Datafield ' . $datafield['name'] . ' - ' . $response->message . '</br>';
             } else {
                 if ($website) {
                     $scope = 'websites';
                     $scopeId = $website;
                 } else {
                     $scope = 'default';
                     $scopeId = '0';
                 }
                 /*
                  * map the succesful created datafield
                  */
                 $this->data->saveConfigData('connector_data_mapping/customer_data/' . $key, strtoupper($datafield['name']), $scope, $scopeId);
                 $this->data->log('successfully connected : ' . $datafield['name']);
             }
         }
         if ($result['errors']) {
             $this->messageManager->addNoticeMessage($result['message']);
         } else {
             $this->messageManager->addSuccessMessage('All Datafields Created And Mapped.');
         }
     }
     $this->_redirect($redirectUrl);
 }
 /**
  * @return bool
  */
 public function getCurlError()
 {
     //if curl error
     if (!empty($this->curlError)) {
         //log curl error
         $message = 'CURL ERROR ' . $this->curlError;
         $this->helper->log($message);
         return $this->curlError;
     }
     return false;
 }
 /**
  * Generates the coupon code based on the code id.
  *
  * @return bool
  */
 public function generateCoupon()
 {
     $params = $this->getRequest()->getParams();
     //check for param code and id
     if (!isset($params['id']) || !isset($params['code'])) {
         $this->helper->log('Coupon no id or code is set');
         return false;
     }
     //coupon rule id
     $couponCodeId = $params['id'];
     if ($couponCodeId) {
         $rule = $this->ruleFactory->create()->load($couponCodeId);
         $generator = $this->massGeneratorFactory->create();
         $generator->setFormat(\Magento\SalesRule\Helper\Coupon::COUPON_FORMAT_ALPHANUMERIC);
         $generator->setRuleId($couponCodeId);
         $generator->setUsesPerCoupon(1);
         $generator->setDash(3);
         $generator->setLength(9);
         $generator->setPrefix('DOT-');
         $generator->setSuffix('');
         //set the generation settings
         $rule->setCouponCodeGenerator($generator);
         $rule->setCouponType(\Magento\SalesRule\Model\Rule::COUPON_TYPE_AUTO);
         //generate the coupon
         $coupon = $rule->acquireCoupon();
         $couponCode = $coupon->getCode();
         //save the type of coupon
         /** @var \Magento\SalesRule\Model\Coupon $couponModel */
         $couponModel = $this->couponFactory->create()->loadByCode($couponCode);
         $couponModel->setType(\Magento\SalesRule\Model\Rule::COUPON_TYPE_NO_COUPON)->setGeneratedByDotmailer(1);
         if (is_numeric($params['expire_days'])) {
             $expireDate = $this->_localeDate->date()->add(new \DateInterval(sprintf('P%sD', $params['expire_days'])));
             $couponModel->setExpirationDate($expireDate);
         } elseif ($rule->getToDate()) {
             $couponModel->setExpirationDate($rule->getToDate());
         }
         $this->coupon->save($couponModel);
         return $couponCode;
     }
     return false;
 }
 /**
  * Basket items.
  *
  * @return mixed
  */
 public function getBasketItems()
 {
     $params = $this->getRequest()->getParams();
     if (!isset($params['quote_id']) || !isset($params['code'])) {
         $this->helper->log('Basket no quote id or code is set');
         return false;
     }
     $quoteId = $params['quote_id'];
     $quoteModel = $this->quoteFactory->create()->loadByIdWithoutStore($quoteId);
     //check for any quote for this email, don't want to render further
     if (!$quoteModel->getId()) {
         $this->helper->log('no quote found for ' . $quoteId);
         return false;
     }
     if (!$quoteModel->getIsActive()) {
         $this->helper->log('Cart is not active : ' . $quoteId);
         return false;
     }
     $this->quote = $quoteModel;
     //Start environment emulation of the specified store
     $storeId = $quoteModel->getStoreId();
     $appEmulation = $this->emulationFactory->create();
     $appEmulation->startEnvironmentEmulation($storeId);
     $quoteItems = $quoteModel->getAllItems();
     $itemsData = [];
     foreach ($quoteItems as $quoteItem) {
         //skip configurable products
         if ($quoteItem->getParentItemId() != null) {
             continue;
         }
         $_product = $quoteItem->getProduct();
         $inStock = $_product->isInStock() ? 'In Stock' : 'Out of stock';
         $total = $this->priceHelper->currency($quoteItem->getPrice());
         $productUrl = $_product->getProductUrl();
         $grandTotal = $this->priceHelper->currency($this->getGrandTotal());
         $itemsData[] = ['grandTotal' => $grandTotal, 'total' => $total, 'inStock' => $inStock, 'productUrl' => $productUrl, 'product' => $_product, 'qty' => $quoteItem->getQty()];
     }
     return $itemsData;
 }
 /**
  * @param \Magento\Framework\Event\Observer $observer
  *
  * @return $this
  */
 public function execute(\Magento\Framework\Event\Observer $observer)
 {
     $creditmemo = $observer->getEvent()->getCreditmemo();
     $storeId = $creditmemo->getStoreId();
     $order = $creditmemo->getOrder();
     $orderId = $order->getEntityId();
     $quoteId = $order->getQuoteId();
     try {
         /*
          * Reimport transactional data.
          */
         $emailOrder = $this->emailOrderFactory->create()->loadByOrderId($orderId, $quoteId, $storeId);
         if (!$emailOrder->getId()) {
             $this->helper->log('ERROR Creditmemmo Order not found :' . $orderId . ', quote id : ' . $quoteId . ', store id ' . $storeId);
             return $this;
         }
         $emailOrder->setEmailImported(\Dotdigitalgroup\Email\Model\Contact::EMAIL_CONTACT_NOT_IMPORTED)->save();
     } catch (\Exception $e) {
         $this->helper->debug((string) $e, []);
     }
     return $this;
 }
 /**
  * save enrolment to queue for cron automation enrolment
  *
  * @param $data
  */
 public function doAutomationEnrolment($data)
 {
     //the program is not mapped
     if (!$data['programId']) {
         $this->helper->log('automation type : ' . $data['automationType'] . ' program id not found');
     } else {
         try {
             $this->automationFactory->create()->setEmail($data['email'])->setAutomationType($data['automationType'])->setEnrolmentStatus(\Dotdigitalgroup\Email\Model\Sync\Automation::AUTOMATION_STATUS_PENDING)->setTypeId($data['order_id'])->setWebsiteId($data['website_id'])->setStoreName($data['store_name'])->setProgramId($data['programId'])->save();
         } catch (\Exception $e) {
             $this->helper->debug((string) $e, []);
         }
     }
 }
 /**
  * Get product collection.
  *
  * @return array
  */
 public function getLoadedProductCollection()
 {
     $productsToDisplay = [];
     $mode = $this->getRequest()->getActionName();
     $limit = $this->recommnededHelper->getDisplayLimitByMode($mode);
     $from = $this->recommnededHelper->getTimeFromConfig($mode);
     $to = $this->_localeDate->date()->format(\Zend_Date::ISO_8601);
     $reportProductCollection = $this->reportProductCollection->create()->addViewsCount($from, $to)->setPageSize($limit);
     //filter collection by category by category_id
     if ($catId = $this->getRequest()->getParam('category_id')) {
         $category = $this->categoryFactory->create()->load($catId);
         if ($category->getId()) {
             $reportProductCollection->getSelect()->joinLeft(['ccpi' => $this->coreResource->getTableName('catalog_category_product_index')], 'e.entity_id = ccpi.product_id', ['category_id'])->where('ccpi.category_id =?', $catId);
         } else {
             $this->helper->log('Most viewed. Category id ' . $catId . ' is invalid. It does not exist.');
         }
     }
     //filter collection by category by category_name
     if ($catName = $this->getRequest()->getParam('category_name')) {
         $category = $this->categoryFactory->create()->loadByAttribute('name', $catName);
         if ($category) {
             $reportProductCollection->getSelect()->joinLeft(['ccpi' => $this->coreResource->getTableName('catalog_category_product_index')], 'e.entity_id  = ccpi.product_id', ['category_id'])->where('ccpi.category_id =?', $category->getId());
         } else {
             $this->helper->log('Most viewed. Category name ' . $catName . ' is invalid. It does not exist.');
         }
     }
     //product ids from the report product collection
     $productIds = $reportProductCollection->getColumnValues('entity_id');
     $productCollectionFactory = $this->productCollectionFactory->create();
     $productCollectionFactory->addIdFilter($productIds)->addAttributeToSelect(['product_url', 'name', 'store_id', 'small_image', 'price']);
     //product collection
     foreach ($productCollectionFactory as $_product) {
         //add only saleable products
         if ($_product->isSalable()) {
             $productsToDisplay[] = $_product;
         }
     }
     return $productsToDisplay;
 }
 /**
  * Cleaning for csv files and connector tables.
  *
  * @return string
  */
 public function cleaning()
 {
     //Clean tables
     $tables = ['automation' => 'email_automation', 'importer' => 'email_importer', 'campaign' => 'email_campaign'];
     $message = 'Cleaning cron job result :';
     foreach ($tables as $key => $table) {
         $result = $this->importerResource->cleanup($table);
         $message .= " {$result} records removed from {$key} .";
     }
     $archivedFolder = $this->fileHelper->getArchiveFolder();
     $result = $this->fileHelper->deleteDir($archivedFolder);
     $message .= ' Deleting archived folder result : ' . $result;
     $this->helper->log($message);
     return $message;
 }
 /**
  * Get report info for contacts sync.
  *
  * @param int $id
  * @param int $websiteId
  *
  * @throws \Magento\Framework\Exception\LocalizedException
  */
 public function _processContactImportReportFaults($id, $websiteId)
 {
     $client = $this->helper->getWebsiteApiClient($websiteId);
     $response = $client->getContactImportReportFaults($id);
     if ($response) {
         $data = $this->_removeUtf8Bom($response);
         $fileName = $this->directoryList->getPath('var') . DIRECTORY_SEPARATOR . 'DmTempCsvFromApi.csv';
         $this->file->open();
         $check = $this->file->write($fileName, $data);
         if ($check) {
             $csvArray = $this->_csvToArray($fileName);
             $this->file->rm($fileName);
             $this->contact->unsubscribe($csvArray);
         } else {
             $this->helper->log('_processContactImportReportFaults: cannot save data to CSV file.');
         }
     }
 }
 /**
  * Export in single.
  *
  * @param $store
  * @param $collectionName
  * @param $websiteId
  */
 public function _exportInSingle($store, $collectionName, $websiteId)
 {
     $this->productIds = [];
     $products = $this->_getProductsToExport($store, true);
     if ($products) {
         foreach ($products as $product) {
             $connectorProduct = $this->connectorProductFactory->create();
             $connectorProduct->setProduct($product);
             $this->helper->log('---------- Start catalog single sync ----------');
             //register in queue with importer
             $this->importerFactory->create()->registerQueue($collectionName, $connectorProduct, \Dotdigitalgroup\Email\Model\Importer::MODE_SINGLE, $websiteId);
             $this->productIds[] = $product->getId();
         }
     }
     if (!empty($this->productIds)) {
         $this->_setImported($this->productIds, true);
         $this->countProducts += count($this->productIds);
     }
 }
 /**
  * Register review campaign.
  *
  * @param $collection
  * @param $websiteId
  */
 public function registerCampaign($collection, $websiteId)
 {
     //review campaign id
     $campaignId = $this->helper->getCampaign($websiteId);
     if ($campaignId) {
         foreach ($collection as $order) {
             $this->helper->log('-- Order Review: ' . $order->getIncrementId() . ' Campaign Id: ' . $campaignId);
             try {
                 $emailCampaign = $this->campaignFactory->create()->setEmail($order->getCustomerEmail())->setStoreId($order->getStoreId())->setCampaignId($campaignId)->setEventName('Order Review')->setCreatedAt($this->dateTime->formatDate(true))->setOrderIncrementId($order->getIncrementId())->setQuoteId($order->getQuoteId());
                 if ($order->getCustomerId()) {
                     $emailCampaign->setCustomerId($order->getCustomerId());
                 }
                 //@codingStandardsIgnoreStart
                 $emailCampaign->getResource()->save($emailCampaign);
                 //@codingStandardsIgnoreEnd
             } catch (\Exception $e) {
                 $this->helper->debug((string) $e, []);
             }
         }
     }
 }
 /**
  * Get access token.
  *
  * @param string $url
  * @param array $params
  *
  * @return string/object
  */
 public function getAccessToken($url, $params)
 {
     //@codingStandardsIgnoreStart
     $ch = curl_init();
     curl_setopt($ch, CURLOPT_URL, $url);
     curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
     curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
     curl_setopt($ch, CURLOPT_TIMEOUT, 5);
     curl_setopt($ch, CURLOPT_CUSTOMREQUEST, 'POST');
     curl_setopt($ch, CURLOPT_POST, count($params));
     curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
     curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: application/x-www-form-urlencoded'));
     $response = json_decode(curl_exec($ch));
     if (isset($response->error)) {
         $this->helper->log('Token Error Number:' . curl_errno($ch) . 'Error String:' . curl_error($ch));
     }
     curl_close($ch);
     if (!isset($response->message) && isset($response->access_token)) {
         return $response->access_token;
     }
     //@codingStandardsIgnoreEnd
     return $response;
 }
 /**
  * Proccess abandoned carts.
  *
  * @param string $mode
  */
 public function proccessAbandonedCarts($mode = 'all')
 {
     /*
      * Save lost baskets to be send in Send table.
      */
     $stores = $this->_helper->getStores();
     foreach ($stores as $store) {
         $storeId = $store->getId();
         if ($mode == 'all' || $mode == 'customers') {
             /*
              * Customers campaigns
              */
             foreach ($this->lostBasketCustomers as $num) {
                 //customer enabled
                 if ($this->_isLostBasketCustomerEnabled($num, $storeId)) {
                     //number of the campaign use minutes
                     if ($num == 1) {
                         $minutes = $this->_getLostBasketCustomerInterval($num, $storeId);
                         $interval = new \DateInterval('PT' . $minutes . 'M');
                     } else {
                         $hours = (int) $this->_getLostBasketCustomerInterval($num, $storeId);
                         $interval = new \DateInterval('PT' . $hours . 'H');
                     }
                     $fromTime = new \DateTime('now', new \DateTimeZone('UTC'));
                     $fromTime->sub($interval);
                     $toTime = clone $fromTime;
                     $fromTime->sub(new \DateInterval('PT5M'));
                     //format time
                     $fromDate = $fromTime->format('Y-m-d H:i:s');
                     $toDate = $toTime->format('Y-m-d H:i:s');
                     //active quotes
                     $quoteCollection = $this->_getStoreQuotes($fromDate, $toDate, $guest = false, $storeId);
                     //found abandoned carts
                     if ($quoteCollection->getSize()) {
                         $this->_helper->log('Customer cart : ' . $num . ', from : ' . $fromDate . ' ,to ' . $toDate);
                     }
                     //campaign id for customers
                     $campaignId = $this->_getLostBasketCustomerCampaignId($num, $storeId);
                     foreach ($quoteCollection as $quote) {
                         $email = $quote->getCustomerEmail();
                         $websiteId = $store->getWebsiteId();
                         $quoteId = $quote->getId();
                         //api - set the last quote id for customer
                         $this->_helper->updateLastQuoteId($quoteId, $email, $websiteId);
                         $items = $quote->getAllItems();
                         $mostExpensiveItem = false;
                         foreach ($items as $item) {
                             if ($mostExpensiveItem == false) {
                                 $mostExpensiveItem = $item;
                             } elseif ($item->getPrice() > $mostExpensiveItem->getPrice()) {
                                 $mostExpensiveItem = $item;
                             }
                         }
                         //api-send the most expensive product for abandoned cart
                         if ($mostExpensiveItem) {
                             $this->_helper->updateAbandonedProductName($mostExpensiveItem->getName(), $email, $websiteId);
                         }
                         //send email only if the interval limit passed, no emails during this interval
                         $intervalLimit = $this->_checkCustomerCartLimit($email, $storeId);
                         //no campign found for interval pass
                         if (!$intervalLimit) {
                             //save lost basket for sending
                             //@codingStandardsIgnoreStart
                             $this->_campaignFactory->create()->setEmail($email)->setCustomerId($quote->getCustomerId())->setEventName('Lost Basket')->setQuoteId($quoteId)->setMessage('Abandoned Cart ' . $num)->setCampaignId($campaignId)->setStoreId($storeId)->setWebsiteId($websiteId)->setIsSent(null)->save();
                             //@codingStandardsIgnoreEnd
                         }
                     }
                 }
             }
         }
         if ($mode == 'all' || $mode == 'guests') {
             /*
              * Guests campaigns
              */
             foreach ($this->lostBasketGuests as $num) {
                 if ($this->_isLostBasketGuestEnabled($num, $storeId)) {
                     //for the  first cart which use the minutes
                     if ($num == 1) {
                         $minutes = $this->_getLostBasketGuestIterval($num, $storeId);
                         $interval = new \DateInterval('PT' . $minutes . 'M');
                     } else {
                         $hours = $this->_getLostBasketGuestIterval($num, $storeId);
                         $interval = new \DateInterval('PT' . $hours . 'H');
                     }
                     $fromTime = new \DateTime('now', new \DateTimeZone('UTC'));
                     $fromTime->sub($interval);
                     $toTime = clone $fromTime;
                     $fromTime->sub(new \DateInterval('PT5M'));
                     //format time
                     $fromDate = $fromTime->format('Y-m-d H:i:s');
                     $toDate = $toTime->format('Y-m-d H:i:s');
                     //active guest quotes
                     $quoteCollection = $this->_getStoreQuotes($fromDate, $toDate, $guest = true, $storeId);
                     //log the time for carts found
                     if ($quoteCollection->getSize()) {
                         $this->_helper->log('Guest cart : ' . $num . ', from : ' . $fromDate . ' ,to : ' . $toDate);
                     }
                     $guestCampaignId = $this->_getLostBasketGuestCampaignId($num, $storeId);
                     foreach ($quoteCollection as $quote) {
                         $email = $quote->getCustomerEmail();
                         $websiteId = $store->getWebsiteId();
                         $quoteId = $quote->getId();
                         // upate last quote id for the contact
                         $this->_helper->updateLastQuoteId($quoteId, $email, $websiteId);
                         // update abandoned product name for contact
                         $items = $quote->getAllItems();
                         $mostExpensiveItem = false;
                         foreach ($items as $item) {
                             if ($mostExpensiveItem == false) {
                                 $mostExpensiveItem = $item;
                             } elseif ($item->getPrice() > $mostExpensiveItem->getPrice()) {
                                 $mostExpensiveItem = $item;
                             }
                         }
                         //api- set the most expensive product to datafield
                         if ($mostExpensiveItem) {
                             $this->_helper->updateAbandonedProductName($mostExpensiveItem->getName(), $email, $websiteId);
                         }
                         //send email only if the interval limit passed, no emails during this interval
                         $campignFound = $this->_checkCustomerCartLimit($email, $storeId);
                         //no campign found for interval pass
                         if (!$campignFound) {
                             //save lost basket for sending
                             //@codingStandardsIgnoreStart
                             $this->_campaignFactory->create()->setEmail($email)->setEventName('Lost Basket')->setQuoteId($quoteId)->setCheckoutMethod('Guest')->setMessage('Guest Abandoned Cart ' . $num)->setCampaignId($guestCampaignId)->setStoreId($storeId)->setWebsiteId($websiteId)->setIsSent(null)->save();
                             //@codingStandardsIgnoreEnd
                         }
                     }
                 }
             }
         }
     }
 }
 /**
  * Get the products to display for table.
  *
  * @return array
  */
 public function getLoadedProductCollection()
 {
     //products to be diplayd for recommended pages
     $productsToDisplay = [];
     $productsToDisplayCounter = 0;
     $quoteId = $this->getRequest()->getParam('quote_id');
     //display mode based on the action name
     $mode = $this->getRequest()->getActionName();
     $quoteModel = $this->quoteFactory->create()->load($quoteId);
     //number of product items to be displayed
     $limit = $this->recommendedHelper->getDisplayLimitByMode($mode);
     $quoteItems = $quoteModel->getAllItems();
     $numItems = count($quoteItems);
     //no product found to display
     if ($numItems == 0 || !$limit) {
         return [];
     } elseif ($numItems > $limit) {
         $maxPerChild = 1;
     } else {
         $maxPerChild = number_format($limit / $numItems);
     }
     $this->helper->log('DYNAMIC QUOTE PRODUCTS : limit ' . $limit . ' products : ' . $numItems . ', max per child : ' . $maxPerChild);
     foreach ($quoteItems as $item) {
         $i = 0;
         //parent product
         $productModel = $item->getProduct();
         //check for product exists
         if ($productModel->getId()) {
             //get single product for current mode
             $recommendedProducts = $this->_getRecommendedProduct($productModel, $mode);
             foreach ($recommendedProducts as $product) {
                 //check if still exists
                 if ($product->getId() && $productsToDisplayCounter < $limit && $i <= $maxPerChild && $product->isSaleable() && !$product->getParentId()) {
                     //we have a product to display
                     $productsToDisplay[$product->getId()] = $product;
                     $i++;
                     $productsToDisplayCounter++;
                 }
             }
         }
         //have reached the limit don't loop for more
         if ($productsToDisplayCounter == $limit) {
             break;
         }
     }
     //check for more space to fill up the table with fallback products
     if ($productsToDisplayCounter < $limit) {
         $fallbackIds = $this->recommendedHelper->getFallbackIds();
         $productCollection = $this->productFactory->create()->getCollection()->addIdFilter($fallbackIds)->addAttributeToSelect(['product_url', 'name', 'store_id', 'small_image', 'price']);
         foreach ($productCollection as $product) {
             if ($product->isSaleable()) {
                 $productsToDisplay[$product->getId()] = $product;
             }
             //stop the limit was reached
             //@codingStandardsIgnoreStart
             if (count($productsToDisplay) == $limit) {
                 break;
             }
             //@codingStandardsIgnoreEnd
         }
     }
     $this->helper->log('quote - loaded product to display ' . count($productsToDisplay));
     return $productsToDisplay;
 }
 /**
  * Sync.
  *
  * @throws \Magento\Framework\Exception\LocalizedException
  */
 public function sync()
 {
     $automationOrderStatusCollection = $this->automationFactory->create()->addFieldToFilter('enrolment_status', self::AUTOMATION_STATUS_PENDING);
     $automationOrderStatusCollection->addFieldToFilter('automation_type', ['like' => '%' . self::ORDER_STATUS_AUTOMATION . '%'])->getSelect()->group('automation_type');
     $statusTypes = $automationOrderStatusCollection->getColumnValues('automation_type');
     foreach ($statusTypes as $type) {
         $this->automationTypes[$type] = \Dotdigitalgroup\Email\Helper\Config::XML_PATH_CONNECTOR_AUTOMATION_STUDIO_ORDER_STATUS;
     }
     //send the campaign by each types
     foreach ($this->automationTypes as $type => $config) {
         $contacts = [];
         $websites = $this->helper->getWebsites(true);
         foreach ($websites as $website) {
             if (strpos($type, self::ORDER_STATUS_AUTOMATION) !== false) {
                 //@codingStandardsIgnoreStart
                 $configValue = unserialize($this->helper->getWebsiteConfig($config, $website));
                 //@codingStandardsIgnoreEnd
                 if (is_array($configValue) && !empty($configValue)) {
                     foreach ($configValue as $one) {
                         if (strpos($type, $one['status']) !== false) {
                             $contacts[$website->getId()]['programId'] = $one['automation'];
                         }
                     }
                 }
             } else {
                 $contacts[$website->getId()]['programId'] = $this->helper->getWebsiteConfig($config, $website);
             }
         }
         //get collection from type
         $automationCollection = $this->automationFactory->create();
         $automationCollection->addFieldToFilter('enrolment_status', self::AUTOMATION_STATUS_PENDING);
         $automationCollection->addFieldToFilter('automation_type', $type);
         //limit because of the each contact request to get the id
         $automationCollection->getSelect()->limit($this->limit);
         foreach ($automationCollection as $automation) {
             $type = $automation->getAutomationType();
             //customerid, subscriberid, wishlistid..
             $email = $automation->getEmail();
             $this->typeId = $automation->getTypeId();
             $this->websiteId = $automation->getWebsiteId();
             $this->storeName = $automation->getStoreName();
             $typeDouble = $type;
             //Set type to generic automation status if type contains constant value
             if (strpos($typeDouble, self::ORDER_STATUS_AUTOMATION) !== false) {
                 $typeDouble = self::ORDER_STATUS_AUTOMATION;
             }
             $contactId = $this->helper->getContactId($email, $this->websiteId);
             //contact id is valid, can update datafields
             if ($contactId) {
                 //need to update datafields
                 $this->updateDatafieldsByType($typeDouble, $email);
                 $contacts[$automation->getWebsiteId()]['contacts'][$automation->getId()] = $contactId;
             } else {
                 // the contact is suppressed or the request failed
                 //@codingStandardsIgnoreStart
                 $automation->setEnrolmentStatus('Suppressed')->save();
                 //@codingStandardsIgnoreEnd
             }
         }
         foreach ($contacts as $websiteId => $websiteContacts) {
             if (isset($websiteContacts['contacts'])) {
                 $this->programId = $websiteContacts['programId'];
                 $contactsArray = $websiteContacts['contacts'];
                 //only for subscribed contacts
                 if (!empty($contactsArray) && $this->_checkCampignEnrolmentActive($this->programId)) {
                     $result = $this->sendContactsToAutomation(array_values($contactsArray), $websiteId);
                     //check for error message
                     if (isset($result->message)) {
                         $this->programStatus = 'Failed';
                         $this->programMessage = $result->message;
                     }
                     //program is not active
                 } elseif ($this->programMessage == 'Error: ERROR_PROGRAM_NOT_ACTIVE ') {
                     $this->programStatus = 'Deactivated';
                 }
                 //update contacts with the new status, and log the error message if failes
                 $coreResource = $this->resource;
                 $conn = $coreResource->getConnection('core_write');
                 try {
                     $contactIds = array_keys($contactsArray);
                     $bind = ['enrolment_status' => $this->programStatus, 'message' => $this->programMessage, 'updated_at' => $this->localeDate->date(null, null, false)->format('Y-m-d H:i:s')];
                     $where = ['id IN(?)' => $contactIds];
                     $num = $conn->update($coreResource->getTableName('email_automation'), $bind, $where);
                     //number of updated records
                     if ($num) {
                         $this->helper->log('Automation type : ' . $type . ', updated : ' . $num);
                     }
                 } catch (\Exception $e) {
                     throw new \Magento\Framework\Exception\LocalizedException(__($e->getMessage()));
                 }
             }
         }
     }
 }
 /**
  * Sync a single contact.
  *
  * @param null $contactId
  *
  * @return mixed
  */
 public function syncContact($contactId = null)
 {
     if ($contactId) {
         $contact = $this->contactFactory->create()->load($contactId);
     } else {
         $contact = $this->registry->registry('current_contact');
     }
     if (!$contact->getId()) {
         $this->messageManager->addErrorMessage('No contact found!');
         return false;
     }
     $websiteId = $contact->getWebsiteId();
     $website = $this->storeManager->getWebsite($websiteId);
     $updated = 0;
     $customers = $headers = $allMappedHash = [];
     $this->helper->log('---------- Start single customer sync ----------');
     //skip if the mapping field is missing
     if (!$this->helper->getCustomerAddressBook($website)) {
         return false;
     }
     $customerId = $contact->getCustomerId();
     if (!$customerId) {
         $this->messageManager->addErrorMessage('Cannot manually sync guests!');
         return false;
     }
     if (!$this->helper->isEnabled($websiteId)) {
         $this->messageManager->addErrorMessage('Api is not enabled');
         return false;
     }
     $client = $this->helper->getWebsiteApiClient($website);
     //create customer filename
     $customersFile = strtolower($website->getCode() . '_customers_' . date('d_m_Y_Hi') . '.csv');
     $this->helper->log('Customers file : ' . $customersFile);
     /*
      * HEADERS.
      */
     $mappedHash = $this->helper->getWebsiteCustomerMappingDatafields($website);
     $headers = $mappedHash;
     //custom customer attributes
     $customAttributes = $this->helper->getCustomAttributes($website);
     foreach ($customAttributes as $data) {
         $headers[] = $data['datafield'];
         $allMappedHash[$data['attribute']] = $data['datafield'];
     }
     $headers[] = 'Email';
     $headers[] = 'EmailType';
     $this->file->outputCSV($this->file->getFilePath($customersFile), $headers);
     /*
      * END HEADERS.
      */
     $customerCollection = $this->_getCustomerCollection([$customerId], $website->getId());
     foreach ($customerCollection as $customer) {
         $contactModel = $this->contactFactory->create()->loadByCustomerEmail($customer->getEmail(), $websiteId);
         //contact with this email not found
         if (!$contactModel->getId()) {
             continue;
         }
         /*
          * DATA.
          */
         $connectorCustomer = $this->emailCustomer->create()->setMappingHash($mappedHash)->setCustomerData($customer);
         $customers[] = $connectorCustomer;
         foreach ($customAttributes as $data) {
             $attribute = $data['attribute'];
             $value = $customer->getData($attribute);
             $connectorCustomer->setData($value);
         }
         //contact email and email type
         $connectorCustomer->setData($customer->getEmail());
         $connectorCustomer->setData('Html');
         // save csv file data for customers
         $this->file->outputCSV($this->file->getFilePath($customersFile), $connectorCustomer->toCSVArray());
         /*
          * END DATA.
          */
         //mark the contact as imported
         $contactModel->setEmailImported(\Dotdigitalgroup\Email\Model\Contact::EMAIL_CONTACT_IMPORTED);
         $subscriber = $this->subscriberFactory->create()->loadByEmail($customer->getEmail());
         if ($subscriber->isSubscribed()) {
             $contactModel->setIsSubscriber('1')->setSubscriberStatus($subscriber->getSubscriberStatus());
         }
         //@codingStandardsIgnoreStart
         $contactModel->getResource()->save($contactModel);
         ++$updated;
     }
     if (is_file($this->file->getFilePath($customersFile))) {
         //@codingStandardsIgnoreEnd
         //import contacts
         if ($updated > 0) {
             //register in queue with importer
             $this->importerFactory->create()->registerQueue(\Dotdigitalgroup\Email\Model\Importer::IMPORT_TYPE_CONTACT, '', \Dotdigitalgroup\Email\Model\Importer::MODE_BULK, $website->getId(), $customersFile);
             $client->postAddressBookContactsImport($customersFile, $this->helper->getCustomerAddressBook($website));
         }
     }
     return $contact->getEmail();
 }