name = 'cartsguru'; $this->tab = 'advertising_marketing'; $this->version = '1.4.16'; $this->author = 'LINKT IT'; $this->module_key = 'f841e8edc4514a141082e10c797c7c57'; $this->bootstrap = true; $this->views_url = _PS_ROOT_DIR_ . '/' . basename(_PS_MODULE_DIR_) . '/' . $this->name . '/views'; $this->module_url = __PS_BASE_URI__ . basename(_PS_MODULE_DIR_) . '/' . $this->name; $this->images_url = $this->module_url . '/views/img/'; $this->cg_debug = defined('CARTSGURU_DEBUG') ? CARTSGURU_DEBUG : false; parent::__construct(); $this->displayName = $this->l('Carts Guru'); $this->description = $this->l('Your multichannel solution for easily recovering your abandoned shopping carts. Use Email & SMS Retargeting, Automatic Calls and Social Media!'); if (!$this->_isCurlAvailable()) { $this->warning = $this->l('cURL library is not available.'); } if (version_compare(_PS_VERSION_, '1.5.0', '<')) { require(_PS_MODULE_DIR_.$this->name.'/backward_compatibility/backward.php'); } if (!(int)Configuration::get('CARTSG_API_SUCCESS') && $this->canConfigure()) { $this->warning = $this->l('The module is not configured'); } } /** * Log message in file */ private function logDebug($message) { if ($this->cg_debug) { if (!$this->logger) { $this->logger = new FileLogger(0); $this->logger->setFilename(_PS_ROOT_DIR_.'/log/debug_cartguru_'.date('Ymd').'.log'); } $this->logger->logDebug($message); } } /** * Module installation * * @see Module->install * @param bool|true $delete_params * use for reinitialisation data * @return bool */ public function install($delete_params = true) { if ($delete_params) { if (! Configuration::updateValue('CARTSG_TOKEN', $this->generateCode('', 15)) || ! Configuration::updateValue('CARTSG_IMAGE_GENERATE', 0)) { return false; } //Images CartsGuruImageManager::initProductThumbnail(); } if (parent::install() == false) { return false; } if (version_compare(_PS_VERSION_, '1.5.0', '<')) { if (! $this->registerHook('newOrder') || ! $this->registerHook('postUpdateOrderStatus') || ! $this->registerHook('cart') || ! $this->registerHook('createAccount') || ! $this->registerHook('backOfficeHeader')) { return false; } } else { if (! $this->registerHook('actionValidateOrder') || ! $this->registerHook('actionObjectOrderUpdateAfter') || ! $this->registerHook('actionCartSave') || ! $this->registerHook('actionCustomerAccountAdd') || ! $this->registerHook('actionObjectCustomerUpdateAfter') || ! $this->registerHook('actionObjectAddressAddAfter') || ! $this->registerHook('actionObjectAddressUpdateAfter') || ! $this->registerHook('backOfficeHeader')) { return false; } } if (! $this->registerHeaderAndOrderConfirmationHooks()) { return false; } //Register dashboard widget on > 1.6 if (! $this->registerDashboarHooks()) { return false; } $this->followProgress('installed'); return true; } /** * Called when module update to 1.2.0 * @return bool */ public function registerHeaderAndOrderConfirmationHooks() { if (version_compare(_PS_VERSION_, '1.5.0', '<')) { if (! $this->registerHook('header') || ! $this->registerHook('orderConfirmation')) { return false; } } else { if (! $this->registerHook('displayHeader') || ! $this->registerHook('displayOrderConfirmation')) { return false; } } return true; } /** * Called on install or on update to 1.2.1 * @return bool */ public function registerDashboarHooks() { if (version_compare(_PS_VERSION_, '1.6.0', '>=')) { if (!$this->registerHook('dashboardZoneOne') || !$this->registerHook('dashboardData')) { return false; } } return true; } /** * Uninstall the module * * @see * * * * * @param bool|true $delete_params * is use for delete all data in db * @return bool */ public function uninstall($delete_params = true) { if (! parent::uninstall()) { return false; } if ($delete_params && (! Configuration::deleteByName('CARTSG_TOKEN') || ! Configuration::deleteByName('CARTSG_API_AUTH_KEY') || ! Configuration::deleteByName('CARTSG_SITE_ID') || ! Configuration::deleteByName('CARTSG_FEATURE_FB') || ! Configuration::deleteByName('CARTSG_FB_PIXEL') || ! Configuration::deleteByName('CARTSG_FB_CATALOGID') || ! Configuration::deleteByName('CARTSG_API_SUCCESS') || ! Configuration::deleteByName('CARTSG_IMAGE_GENERATE')|| ! Configuration::deleteByName('CARTSG_IMAGE_TYPE'))) { return false; } elseif ($delete_params) { if (!CartsGuruImageManager::deleteCartsGuruImageType()) { return false; } } $this->followProgress('uninstalled'); return true; } /** * reset the module, no data is deleted * * @return bool */ public function reset() { if (! $this->uninstall(false)) { return false; } if (! $this->install(false)) { return false; } return true; } /** * Get the admin module url * @return string */ protected function getConfigModuleUrl() { if (version_compare(_PS_VERSION_, '1.5', '<')) { $admin_base = 'index.php?tab=AdminModules'; } else { $admin_base = $this->context->link->getAdminLink('AdminModules', false); } return $admin_base . '&configure=' . $this->name . '&tab_module=' . $this->tab . '&module_name=' . $this->name . '&token=' . Tools::getAdminTokenLite('AdminModules'); } /** * Generate Admin url for plugin * @return String */ public function getAdminUrl() { $adminUrl = (version_compare(_PS_VERSION_, '1.5.0', '<') ? _PS_BASE_URL_.__PS_BASE_URI__ . 'modules/cartsguru/controllers14/admin.php' : $this->context->link->getModuleLink('cartsguru', 'admin')); if (strrpos($adminUrl, '?') === false) { $adminUrl .= '?cartsguru_admin_action='; } else { $adminUrl .= '&cartsguru_admin_action='; } return $adminUrl; } /** * Registrs the new plugin version after update * @return Boolean */ public function registerPluginAfterUpdate() { if ($this->canConfigure()) { $configs = $this->getConfigFieldsValues(); if (! empty($configs['CARTSG_API_AUTH_KEY']) && ! empty($configs['CARTSG_SITE_ID'])) { if (!$this->_isCurlAvailable()) { $this->displayWarn($this->l('Curl is not usable or is missing so it is not possible to call Carts Guru. Please install it and try again')); return false; } $api = new CartsGuruRAPI($configs['CARTSG_SITE_ID'], $configs['CARTSG_API_AUTH_KEY']); $adminUrl = $this->getAdminUrl(); $result = $api->checkAccess($adminUrl); return ($result ? ($result->info->http_code == 200) : false); } } return false; } /** * Add the CSS & JavaScript files you want to be loaded in the BO. */ public function hookBackOfficeHeader() { $scripts = ''; if (Tools::getValue('configure') == $this->name) { if (version_compare(_PS_VERSION_, '1.6', '<')) { Context::getContext()->smarty->assign( array( 'path' => $this->module_url . '/views' ) ); $tplPath = $this->views_url . '/templates/admin/header.tpl'; $scripts = Context::getContext()->smarty->fetch($tplPath); } else { $this->context->controller->addJquery(); $this->context->controller->addJS($this->views_url . '/js/admin.js'); $this->context->controller->addCSS($this->views_url . '/css/admin.css'); } } return $scripts; } /** * * @return String */ public function getContent() { $html = ''; $html .= $this->postProcess(); $html .= $this->renderWelcomeView(); return $html; } /** * Configuration update settings */ protected function postProcess() { $html = ''; if (Tools::isSubmit('submitConnect')) { $api_auth_key = Tools::getValue('authkey'); $site_id = Tools::getValue('siteid'); Configuration::updateValue('CARTSG_API_AUTH_KEY', $api_auth_key); Configuration::updateValue('CARTSG_SITE_ID', $site_id); $html .= $this->displayConfirmation($this->l('Settings updated')); $html .= $this->registerSite(); } if (Tools::isSubmit('submitSubscribe')) { $html .= $this->subscribe(); } if (Tools::isSubmit('submitHasNoAccount')) { $this->followProgress('subscribing'); } return $html; } protected function generateProductImages($erase = false) { $html = ''; if ($erase) { CartsGuruImageManager::deleteProductImageCG(); } $img_generated = CartsGuruImageManager::generateProductImageCG(); if ($img_generated === true) { $html .= $this->displayConfirmation($this->l('Image product for Cart Guru were successfully generated.')); } else { //Handle errors foreach ($img_generated as $error) { if ($error === 'timeout') { $html .= $this->displayWarn( $this->l('Only part of the images have been generated. The server timed out before finishing.') ); } else { $this->post_errors[] = $error; } } } return $html; } protected function followProgress($step, $data = null) { $configs = $this->getConfigFieldsValues(); $employee = $this->context->employee; $fields = array( 'email' => $employee->email, 'siteId' => $configs['CARTSG_SITE_ID'] ? $configs['CARTSG_SITE_ID'] : '', 'pluginVersion' => _CARTSGURU_VERSION_, 'storeVersion' => _PS_VERSION_, 'step' => $step ); if ($step === 'installed') { $fields = array_merge($fields, $this->getStoreInformation()); } if ($step === 'subscribed' || $step === 'registered') { $fields = array_merge($fields, $this->getOrderStatistics()); } if ($data) { $fields = array_merge($fields, $data); } if (isset($fields['country'])) { $fields['country'] = CountryCore::getIsoById($fields['country']); } if (!$this->_isCurlAvailable()) { $this->displayWarn($this->l('Curl is not usable or is missing so it is not possible to call Carts Guru. Please install it and try again')); return false; } $api = new CartsGuruRAPI(); $api->post(CartsGuruRAPI::API_PATH_PROGRESS, $fields); } protected function subscribe() { $html = ''; if (!$this->_isCurlAvailable()) { return $this->displayWarn($this->l('Curl is not usable or is missing so it is not possible to call Carts Guru. Please install it and try again')); } $api = new CartsGuruRAPI(); $fields = array( 'country' => Tools::getValue('country'), 'phoneNumber' => Tools::getValue('phoneNumber'), 'website' => Tools::getValue('website'), 'email' => Tools::getValue('email'), 'lastname' =>Tools::getValue('lastname'), 'firstname' => Tools::getValue('firstname'), 'password' => Tools::getValue('password'), 'title' => Configuration::get('PS_SHOP_NAME'), 'adminUrl' => $this->getAdminUrl() ); $request = $api->subscribe($fields); $response = $request->decodeResponse(); if (!$request || $request->info->http_code != 200) { if ($response->error == 'Country not supported') { $this->followProgress('subscribe-other-country', $fields); return $this->displayWarn($this->l('Your country is not supported for now. Please contact us on https://carts.guru?platform=prestashop')); } elseif ($response->error == 'Account already exists') { return $this->displayWarn($this->l('This email is already associated with existing account')); } elseif ($response->error == 'This domain name is already registered') { return $this->displayWarn($this->l('This domain name is already associated with existing account')); } else { $this->followProgress('subscribe-error', $fields); return $this->displayWarn($this->l('An error occurs during the registration. Please contact us on https://carts.guru?platform=prestashop')); } } //Success Configuration::updateValue('CARTSG_API_AUTH_KEY', $response->apiToken); Configuration::updateValue('CARTSG_SITE_ID', $response->siteId); Configuration::updateValue('CARTSG_API_SUCCESS', 1); //Follow $this->followProgress('subscribed', $fields); //Run import $this->importCarts($response->siteId); $this->importOrders($response->siteId); if (!(int)Configuration::get('CARTSG_IMAGE_GENERATE')) { $html .= $this->generateProductImages(); } // If we have redirect folllow if ($response->redirectUrl) { Tools::redirect($response->redirectUrl); return; } return $html; } protected function registerSite() { $html = ''; $configs = $this->getConfigFieldsValues(); if (! empty($configs['CARTSG_API_AUTH_KEY']) && ! empty($configs['CARTSG_SITE_ID'])) { if (!$this->_isCurlAvailable()) { return $this->displayWarn($this->l('Curl is not usable or is missing so it is not possible to call Carts Guru. Please install it and try again')); } $api = new CartsGuruRAPI($configs['CARTSG_SITE_ID'], $configs['CARTSG_API_AUTH_KEY']); $adminUrl = $this->getAdminUrl(); $result = $api->checkAccess($adminUrl); $access_cg = ($result ? ($result->info->http_code == 200) : false); if ($access_cg) { Configuration::updateValue('CARTSG_API_SUCCESS', 1); $this->followProgress('registered'); $response = $result->decodeResponse(); if ($response->isNew) { $this->importCarts($configs['CARTSG_SITE_ID']); $this->importOrders($configs['CARTSG_SITE_ID']); } if (!(int)Configuration::get('CARTSG_IMAGE_GENERATE')) { $html .= $this->generateProductImages(); } } else { Configuration::updateValue('CARTSG_API_SUCCESS', 0); $html .= $this->displayWarn($this->l('Impossible to connect with this credentials.')); } } else { Configuration::updateValue('CARTSG_API_SUCCESS', 0); } return $html; } // Check if multistore option is enabled, and if yes if a store is selected protected function canConfigure() { return (version_compare(_PS_VERSION_, '1.5.0', '<') || ! Shop::isFeatureActive() || Shop::getContext() == Shop::CONTEXT_SHOP); } protected function getStoreInformation() { $employee = $this->context->employee; $shop = $this->context->shop; $phoneNumber = Configuration::get('PS_SHOP_PHONE', null, null, $shop->id); return array( 'country' => Configuration::get('PS_COUNTRY_DEFAULT', null, null, $shop->id), 'phoneNumber' => $phoneNumber ? $phoneNumber : '', 'website' => _PS_BASE_URL_, 'email' => $employee->email, 'lastname' => $employee->lastname, 'firstname' => $employee->firstname, 'language' => Language::getIsoById((int)$employee->id_lang) ); } /** * Generate welcome view after install */ public function renderWelcomeView() { $html = ''; $employee = $this->context->employee; $countries = CountryCore::getCountries($employee->id_lang, false, false, false); $countries_array = array(); foreach ($countries as $country) { $countries_array[$country['id_country']] = $country['name']; } $configs = $this->getConfigFieldsValues(); $options = array( 'isSubmitSuccess' => (int)$configs['CARTSG_API_SUCCESS'] == 1, 'canConfigure' => $this->canConfigure() ); $variables = array( 'siteid' => $configs['CARTSG_SITE_ID'] ? $configs['CARTSG_SITE_ID'] : '', 'authkey' => $configs['CARTSG_API_AUTH_KEY'] ? $configs['CARTSG_API_AUTH_KEY'] : '', 'formUrl' => $this->getConfigModuleUrl(), 'imagesUrl' => $this->images_url, 'activeView' => '', 'countries' => $countries_array ); if ($options['canConfigure'] == false) { $variables['activeView'] = 'view-no-store-selected'; } elseif ($options['isSubmitSuccess'] == true) { $variables['activeView'] = 'view-success'; } elseif (Tools::isSubmit('submitHasNoAccount') || Tools::isSubmit('submitSubscribe')) { $variables['activeView'] = 'view-try-it'; } elseif (!empty($configs['CARTSG_SITE_ID']) && !empty($configs['CARTSG_SITE_ID'])) { $variables['activeView'] = 'view-have-account'; } $storeInformation = $this->getStoreInformation(); $variables = array_merge($variables, $storeInformation); $this->context->smarty->assign($variables); $html .= $this->context->smarty->fetch($this->views_url . '/templates/admin/welcome.tpl'); return $html; } /** * Get all configuration * * @return array */ public function getConfigFieldsValues() { return array( 'CARTSG_SITE_ID' => Tools::getValue('siteid', Configuration::get('CARTSG_SITE_ID')), 'CARTSG_API_AUTH_KEY' => Tools::getValue('authkey', Configuration::get('CARTSG_API_AUTH_KEY')), 'CARTSG_API_SUCCESS' => Configuration::get('CARTSG_API_SUCCESS') ); } /** * generate a uniq code for token * * @param string $prefix * @param int $length * @return string */ public static function generateCode($prefix = '', $length = 8) { $code = ''; $possible = '123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; $maxlength = Tools::strlen($possible); if ($length > $maxlength) { $length = $maxlength; } $i = 0; while ($i < $length) { $char = Tools::substr($possible, mt_rand(0, $maxlength - 1), 1); if (! strstr($code, $char)) { $code .= $char; $i ++; } } return $prefix . $code; } /** * Only used for 1.4 * @param $params */ public function hookNewOrder($params) { return $this->hookActionValidateOrder($params); } /** * Only used for 1.4 * @param $params */ public function hookPostUpdateOrderStatus($params) { if ((int)$params['id_order']) { $order = new Order((int)$params['id_order']); $params['object'] = $order; return $this->hookActionObjectOrderUpdateAfter($params); } } /** * Display on each page * * @param array $params * @return boolean */ public function hookDisplayHeader($params) { //Result $html = ''; //CartRules was not apply, car not found if ($this->context->controller instanceof OrderController && Tools::getValue('discount_name') && Tools::getValue('recover_cart')) { $this->context->controller->errors[] = $this->l('We can not applied on your cart the voucher') . ' ' . Tools::getValue('discount_name'); } // jQuery handler $html .= $this->context->smarty->fetch($this->views_url . '/templates/hook/jQuery.tpl'); // Live tracking url $trackingUrl = (version_compare(_PS_VERSION_, '1.5.0', '<') ? _PS_BASE_URL_.__PS_BASE_URI__ . 'modules/cartsguru/controllers14/tracking.php' : $this->context->link->getModuleLink('cartsguru', 'tracking')); // Avoid mixed content $trackingUrl = str_replace(array('https:', 'http:'), '', $trackingUrl); $this->context->smarty->assign(array( 'trackingUrl' => $trackingUrl )); $html .= $this->context->smarty->fetch($this->views_url . '/templates/hook/tracking.tpl'); $facebook = Configuration::get('CARTSG_FEATURE_FB'); // If facebook ads enabled if ($facebook) { // Set source cookie $utm_source = Tools::getValue('utm_source'); $utm_campaign = Tools::getValue('utm_campaign'); if (!empty($utm_source) && $utm_source === 'cartsguru-fb' && !empty($utm_campaign)) { Context::getContext()->cookie->__set('cartsguru-source', serialize(array( 'type' => $utm_source, 'campaign' => $utm_campaign, 'timestamp' => time() ))); } $pixel = Configuration::get('CARTSG_FB_PIXEL'); $catalogId = Configuration::get('CARTSG_FB_CATALOGID'); if ($pixel && $catalogId) { // Create smarty context if (version_compare(_PS_VERSION_, '1.7.3', '>')) { $data = $this->context->smarty->createData($this->context->smarty); } else { $data = $this->context->smarty->smarty->createData(); } $variables = array( 'pixel' => $pixel, 'currency_iso' => $this->context->currency->iso_code, 'catalogId' => $catalogId, ); if (version_compare(_PS_VERSION_, '1.7', '>=')) { $variables['isPsVersionOnePointSeven'] = 1; } else { $variables['isPsVersionOnePointSeven'] = 0; } // Product view if ($this->context->controller instanceof ProductController || Tools::getValue('id_product')) { $product_instance = method_exists($this->context->controller, 'getProduct') ? $this->context->controller->getProduct() : new Product(Tools::getValue('id_product')); if ($product_instance) { $variables['track_product_view'] = array( 'id' => $product_instance->id, 'value' => Tools::ps_round($product_instance->getPrice(), 2), 'name' => $product_instance->name ); } } $data->assign($variables); $html .= $this->context->smarty->fetch($this->views_url . '/templates/hook/pixel.tpl', $data); } } $isFBMactive = Configuration::get('CARTSG_FEATURE_FBM'); $isCIactive = Configuration::get('CARTSG_FEATURE_CI'); // If facebook messenger, ci or facebook ads enabled if ($isFBMactive || $isCIactive || $facebook) { // Cart info url $cartInfoUrl = (version_compare(_PS_VERSION_, '1.5.0', '<') ? _PS_BASE_URL_.__PS_BASE_URI__ . 'modules/cartsguru/controllers14/cartinfo.php' : $this->context->link->getModuleLink('cartsguru', 'cartinfo')); // Avoid mixed content $cartInfoUrl = str_replace(array('https:', 'http:'), '', $cartInfoUrl); $currency = new Currency((int)Configuration::get('PS_CURRENCY_DEFAULT')); // Create smarty context if (version_compare(_PS_VERSION_, '1.7.3', '>')) { $data = $this->context->smarty->createData($this->context->smarty); } else { $data = $this->context->smarty->smarty->createData(); } $variables = array( 'ci' => $isCIactive, 'fbm' => $isFBMactive, 'fbAds' => $facebook, 'siteId' => Configuration::get('CARTSG_SITE_ID'), 'trackerUrl' => Configuration::get('CARTSG_TRACKERURL'), 'cartInfoUrl' => $cartInfoUrl, 'appId' => Configuration::get('CARTSG_FB_APPID'), 'pageId' => Configuration::get('CARTSG_FB_PAGEID'), 'currency' => isset($currency) ? (string) $currency->iso_code : '', 'data' => '{}' ); // Add cart content if available if ($this->context->cart && $this->context->cart->id) { $id_lang_default = (int) Configuration::get('PS_LANG_DEFAULT'); $id_shop_group = version_compare(_PS_VERSION_, '1.5.0', '<') ? 0 : $this->context->cart->id_shop_group; $id_shop = version_compare(_PS_VERSION_, '1.5.0', '<') ? 0 : $this->context->cart->id_shop; $cartMapper = $this->getMapper('cart', $id_lang_default, $id_shop_group, $id_shop); $cart = $cartMapper->mappObject($this->context->cart, array(), false, false); $cart['cartId'] = $cart['id']; // Use mapper for cart data $variables['data'] = Tools::jsonEncode(array( 'cart' => $cart )); } $widgets = Configuration::get('CARTSG_WIDGETS'); $variables['widgets'] = !empty($widgets) ? $widgets : '[]'; $data->assign($variables); $html .= $this->context->smarty->fetch($this->views_url . '/templates/hook/tracker.tpl', $data); } return $html; } /** * Display when order is confirmed * warning params changed in 1.7! * * @param array $params * @return boolean */ public function hookDisplayOrderConfirmation($params) { $facebook = Configuration::get('CARTSG_FEATURE_FB'); // If FB not enabled return early if (!$facebook) { return; } if (version_compare(_PS_VERSION_, '1.7.0', '<')) { $order = $params['objOrder']; } else { $order = $params['order']; } // Track order if (isset($order) && (int) $order->id && (int) $order->id_customer) { // Set source if present if (Context::getContext()->cookie->__isset('cartsguru-source')) { $order->source = unserialize(Context::getContext()->cookie->__get('cartsguru-source')); } if (version_compare(_PS_VERSION_, '1.5.0', '<')) { $this->callCG( CartsGuruRAPI::API_PATH_ORDERS, 'order', $order, 0, 0, false, $params ); } else { $this->callCG( CartsGuruRAPI::API_PATH_ORDERS, 'order', $order, (int) $order->id_shop_group, (int) $order->id_shop ); } } // Unset the cookie after order is made if (Context::getContext()->cookie->__isset('cartsguru-source')) { Context::getContext()->cookie->__unset('cartsguru-source'); } $pixel = Configuration::get('CARTSG_FB_PIXEL'); $catalogId = Configuration::get('CARTSG_FB_CATALOGID'); if ($pixel && $catalogId) { $order_items = $order->getProducts(); if (count($order_items) > 0) { $productsIds = array(); foreach ($order_items as $order_item) { $productsIds[] = (string)$order_item['product_attribute_id']; } $variables = array( 'order' => array( 'products' => json_encode($productsIds) ), 'catalogId' => $catalogId ); if (version_compare(_PS_VERSION_, '1.7.0', '<')) { $variables['order']['total'] = Tools::ps_round($params['total_to_pay'], 2); $variables['currency_iso'] = $params['currencyObj']->iso_code; } else { $variables['order']['total'] = Tools::ps_round($order->total_paid, 2); $variables['currency_iso'] = $this->context->currency->iso_code; } $this->context->smarty->assign($variables); return $this->context->smarty->fetch($this->views_url . '/templates/hook/order_confirm.tpl'); } } } /** * When order is validate, indicate it is the reminder permit * journal is close * * @param * $params */ public function hookActionValidateOrder($params) { $order = $params['order']; $params['object'] = $order; return $this->hookActionObjectOrderUpdateAfter($params); } /** * Order update * * @param array $params * @return boolean */ public function hookActionObjectOrderUpdateAfter($params) { $order = $params['object']; if (! Validate::isLoadedObject($order)) { return false; } if (isset($order) && (int) $order->id && (int) $order->id_customer) { // Set source if present if (Context::getContext()->cookie->__isset('cartsguru-source')) { $order->source = unserialize(Context::getContext()->cookie->__get('cartsguru-source')); } if (version_compare(_PS_VERSION_, '1.5.0', '<')) { $this->callCG( CartsGuruRAPI::API_PATH_ORDERS, 'order', $order, 0, 0, false, $params ); } else { $this->callCG( CartsGuruRAPI::API_PATH_ORDERS, 'order', $order, (int) $order->id_shop_group, (int) $order->id_shop ); } } return true; } /** * Customer add address * * @param array $params * @return boolean */ public function hookActionObjectAddressAddAfter($params) { return $this->hookActionObjectAddressUpdateAfter($params); } /** * Customer update address * * @param array $params * @return boolean */ public function hookActionObjectAddressUpdateAfter($params) { $address = $params['object']; if (! Validate::isLoadedObject($address)) { return false; } if (isset($address) && (int) $address->id) { if ((int) $address->id_customer) { $customer = new Customer((int) $address->id_customer); if (version_compare(_PS_VERSION_, '1.5.0', '<')) { $this->callCG( CartsGuruRAPI::API_PATH_ACCOUNTS, 'customer', $customer ); } else { $this->callCG( CartsGuruRAPI::API_PATH_ACCOUNTS, 'customer', $customer, (int) $customer->id_shop_group, (int) $customer->id_shop ); } } } return true; } /** * Customer update information * * @param array $params * @return boolean */ public function hookActionObjectCustomerUpdateAfter($params) { $customer = $params['object']; if (! Validate::isLoadedObject($customer)) { return false; } if (isset($customer) && (int) $customer->id) { if (version_compare(_PS_VERSION_, '1.5.0', '<')) { $this->callCG( CartsGuruRAPI::API_PATH_ACCOUNTS, 'customer', $customer ); } else { $this->callCG( CartsGuruRAPI::API_PATH_ACCOUNTS, 'customer', $customer, (int) $customer->id_shop_group, (int) $customer->id_shop ); } } return true; } /** * hookHeader only used for 1.4 * @param $params * @return boolean */ public function hookHeader($params) { return ($this->hookDisplayHeader($params)); } /** * orderConfirmation only used for 1.4 * @param $params * @return boolean */ public function hookOrderConfirmation($params) { return $this->hookDisplayOrderConfirmation($params); } /** * Only used for 1.4 * @param $params */ public function hookCreateAccount($params) { return ($this->hookActionCartSave($params)); } /** * Successful create account * * @param array $params * @return boolean */ public function hookActionCustomerAccountAdd($params) { $new_customer = $params['newCustomer']; $params['object'] = $new_customer; return ($this->hookActionObjectCustomerUpdateAfter($params)); } /** * Only used for Prestashop 1.4 * @param $params * @return void|boolean */ public function hookCart($params) { if (!$params['cart']->id) { return; } return ($this->hookActionCartSave($params)); } /** * this hook is call many times update the cart * The module catch only cart have customer logged */ public function hookActionCartSave($params) { $cart = $params['cart']; if (! Validate::isLoadedObject($cart)) { return false; } if (isset($cart) && (int) $cart->id && (int) $cart->id_customer) { if (version_compare(_PS_VERSION_, '1.5.0', '<')) { $this->callCG( CartsGuruRAPI::API_PATH_CARTS, 'cart', $cart ); } else { $this->callCG( CartsGuruRAPI::API_PATH_CARTS, 'cart', $cart, (int) $cart->id_shop_group, (int) $cart->id_shop ); } } return true; } /** * Dashboard: Register widget on left area (> 1.6) */ public function hookDashboardZoneOne($params) { $this->context->smarty->assign( array( 'date_from' => Tools::displayDate($params['date_from']), 'date_to' => Tools::displayDate($params['date_to']) ) ); return $this->display(__FILE__, 'dashboard_zone_one.tpl'); } /** * Dashboard: Retrieve the data from API */ public function hookDashboardData($params) { $result = array( 'data_value' => array( 'cg_processed_carts' => 0, 'cg_turnover' => 0, 'cg_sales' => 0 ) ); $configs = $this->getConfigFieldsValues(); //Check plugin is configured if (!$configs['CARTSG_API_SUCCESS'] || empty($configs['CARTSG_API_AUTH_KEY']) || empty($configs['CARTSG_SITE_ID'])) { return $result; } if (!$this->_isCurlAvailable()) { $this->displayWarn($this->l('Curl is not usable or is missing so it is not possible to call Carts Guru. Please install it and try again')); return $result; } $apiParams = array( 'dateFrom' => $params['date_from'], 'dateTo' => $params['date_to'] ); $api = new CartsGuruRAPI($configs['CARTSG_SITE_ID'], $configs['CARTSG_API_AUTH_KEY']); $request = $api->getDashboardStatistics($apiParams); //Check API success request if (!$request || $request->info->http_code != 200) { return $result; } $response = $request->decodeResponse(); //Result look like {"average":0,"turnover":0,"sales":0,"conversionRate":0,"remainingCarts":0,"processedCarts":0,"abandonedPercentage":0,"totalCarts":0}; $result['data_value']['cg_processed_carts'] = $response->processedCarts; $result['data_value']['cg_turnover'] = $response->turnover; $result['data_value']['cg_sales'] = $response->sales; return $result; } /** * Return good initialize mapper depending name * @param string $mapper_name * @param int $id_lang_default * @param int $id_shop_group * @param int $id_shop * @throws InvalidArgumentException * @return AbstractCartsGuruMapper */ public function getMapper($mapper_name, $id_lang_default, $id_shop_group, $id_shop) { switch ($mapper_name) { case 'cart': return new CartsGuruCartMapper($id_lang_default, (int) $id_shop_group, (int) $id_shop); case 'order': return new CartsGuruOrderMapper($id_lang_default, (int) $id_shop_group, (int) $id_shop); case 'product': return new CartsGuruProductMapper($id_lang_default, (int) $id_shop_group, (int) $id_shop); case 'customer': return new CartsGuruAccountMapper($id_lang_default, (int) $id_shop_group, (int) $id_shop); } throw new InvalidArgumentException(); } /** * Map and send data to api * * @param string $path * @param string $mapper_name * @param Object $object * @param int $id_shop_group * @param int $id_shop * @param string $sync * @return boolean */ public function callCG($path, $mapper_name, $object, $id_shop_group = 0, $id_shop = 0, $sync = false, $params = array()) { $success = 0; $site_id = ''; $auth_key = ''; if (version_compare(_PS_VERSION_, '1.5.0', '<')) { $success = Configuration::get('CARTSG_API_SUCCESS'); $site_id = Configuration::get('CARTSG_SITE_ID'); $auth_key = Configuration::get('CARTSG_API_AUTH_KEY'); } else { $success = Configuration::get('CARTSG_API_SUCCESS', null, $id_shop_group, $id_shop); $site_id = Configuration::get('CARTSG_SITE_ID', null, $id_shop_group, $id_shop); $auth_key = Configuration::get('CARTSG_API_AUTH_KEY', null, $id_shop_group, $id_shop); } if ($success && ! empty($site_id) && ! empty($auth_key)) { if ($mapper_name) { $id_lang_default = (int) Configuration::get('PS_LANG_DEFAULT'); $mapper = $this->getMapper( $mapper_name, $id_lang_default, (int) $id_shop_group, (int) $id_shop ); $object = $mapper->create($object, $params); if ($object == null) { return false; } $object['siteId'] = $site_id; } $call_uid = $path.'_'.self::getUniqueVar($object); //Is already call in same request $this->logDebug('UID :'.$call_uid); if (!isset(self::$c_calls[$call_uid])) { try { if (!$this->_isCurlAvailable()) { $this->displayWarn($this->l('Curl is not usable or is missing so it is not possible to call Carts Guru. Please install it and try again')); return false; } $api = new CartsGuruRAPI($site_id, $auth_key); $this->logDebug('UID:'.$call_uid.' / START CALL API'); $api->post($path, $object, $sync); $this->logDebug('UID:'.$call_uid.' / END CALL API'); self::$c_calls[$call_uid] = 1; return true; } catch (Exception $e) { } } else { $this->logDebug('UID:'.$call_uid.' / NO CALL NEED'); } return true; } return false; } static function _isCurlAvailable(){ return function_exists('curl_version'); } public static function getUniqueVar($data) { if (!isset($data)) { return ''; } return md5(serialize($data)); } /** * Compatibility with all PS Version * * @param array/string $warning * @return string */ public function displayWarn($warning) { $this->context->smarty->assign( array( 'warning' => $warning, 'ps_version' => _PS_VERSION_ ) ); $output = $this->context->smarty->fetch( $this->views_url . '/templates/admin/helper_warning.tpl' ); return $output; } private function import($siteId, $type, $api_path) { $isMultiStoreSupported = CartsGuruHelper::isMultiStoreSupported(); $sql = 'SELECT `id_' . bqSQL($type) . '` AS id FROM `' . _DB_PREFIX_ . bqSQL($type); if ($type === 'order') { $sql .= 's'; } $sql .= '`'; //Need filter on the good shop if ($isMultiStoreSupported) { $id_shop = (int)Context::getContext()->shop->id; $sql .= ' WHERE id_shop = ' . (int)$id_shop; } $sql .= ' ORDER BY date_add DESC LIMIT 250'; if ($results = Db::getInstance()->ExecuteS($sql)) { $id_lang_default = (int) Configuration::get('PS_LANG_DEFAULT'); $items = array(); foreach ($results as $row) { $item = $type === 'order' ? new Order($row['id']) : new Cart($row['id']); $mapper = $this->getMapper( $type, $id_lang_default, $isMultiStoreSupported ? $item->id_shop_group : 0, $isMultiStoreSupported ? $item->id_shop : 0 ); $cart_guru_data = $mapper->create($item); if ($cart_guru_data) { $cart_guru_data['siteId'] = $siteId; $items[] = $cart_guru_data; } } $this->callCG( $api_path, null, $items ); } } private function importCarts($siteId) { $this->import($siteId, 'cart', CartsGuruRAPI::API_PATH_IMPORT_CARTS); } private function importOrders($siteId) { $this->import($siteId, 'order', CartsGuruRAPI::API_PATH_IMPORT_ORDERS); } private function getOrderStatistics($sinceDays = 31) { $sinceDays = $sinceDays * -1; $currency = new Currency((int)Configuration::get('PS_CURRENCY_DEFAULT')); $result = array( 'orderCount' => 0, 'orderTotal' => 0, 'discountCount' => 0, 'discountAverage' => 0, 'currency' => (string) $currency->iso_code, ); $orderSql = 'SELECT count(id_order) as `order_count` , sum(total_paid / conversion_rate) AS `order_total` FROM `' . _DB_PREFIX_ . 'orders` WHERE `invoice_date` >= DATE_ADD(SYSDATE(), INTERVAL ' . (int)$sinceDays . ' DAY) AND valid = 1'; $discountSql = 'SELECT count(total_discounts) as `discount_count` , sum(total_discounts / conversion_rate) / count(total_discounts) AS `discount_avg` FROM `' . _DB_PREFIX_ . 'orders` WHERE `invoice_date` >= DATE_ADD(SYSDATE(), INTERVAL ' . (int)$sinceDays . ' DAY) AND valid = 1'; //Need filter on the good shop if (CartsGuruHelper::isMultiStoreSupported()) { $id_shop = (int)Context::getContext()->shop->id; $orderSql .= ' AND id_shop = ' . (int)$id_shop; $discountSql .= ' AND id_shop = ' . (int)$id_shop; } if ($results = Db::getInstance()->ExecuteS($orderSql)) { $row = $results[0]; $result['orderCount'] = round($row['order_count'], 0); $result['orderTotal'] = round($row['order_total'], 2); } if ($results = Db::getInstance()->ExecuteS($discountSql)) { $row = $results[0]; $result['discountCount'] = round($row['discount_count'], 0); if ($result['discountCount'] > 0) { $result['discountAverage'] = round($row['discount_avg'], 2); } } return $result; } }