/** * 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(); }