name = 'criteo'; $this->tab = 'advertising_marketing'; $this->version = '2.7.7'; $this->need_instance = 0; $this->module_key = '231ae9b8e1dd846cbffc2f59c326acef'; $this->author = 'Web In Color'; parent::__construct(); $this->displayName = $this->l('Criteo'); $this->description = $this->l('Criteo product export and tag display.'); /* Backward compatibility */ if (version_compare(_PS_VERSION_, '1.5', '<')) { require _PS_MODULE_DIR_.$this->name.'/backward_compatibility/backward.php'; } } public function install() { return parent::install() && $this->registerHook('header') && $this->registerHook('productfooter') && $this->registerHook('home') && $this->registerHook('shoppingCartExtra') && $this->registerHook('footer') && $this->registerHook('orderConfirmation'); } private function postProcess() { if (Tools::isSubmit('submitCriteo')) { if (!Tools::getValue('id_criteo_account')) { return $this->displayError($this->l('All fields required')); } Configuration::updateValue('WIC_CRITEO_ID_ACCOUNT', pSQL(Tools::getValue('id_criteo_account'))); Configuration::updateValue('WIC_CRITEO_SITE_TYPE', pSQL(Tools::getValue('site_type_criteo'))); $categories = (Tools::getValue('category') ? implode(',', Tools::getValue('category')) : ''); Configuration::updateValue('WIC_CRITEO_CATEGORY', $categories); Configuration::updateValue('WIC_CRITEO_DISPLAY_CAT', Tools::getValue('display_category_criteo')); return $this->displayConfirmation($this->l('Settings updated successfully')); } return false; } public function getContent() { if (version_compare(_PS_VERSION_, '1.4', '>=')) { $this->_html = ''; } else { $this->_html = ''; } $this->_html .= '

'.$this->l('Expertise e-commerce Prestashop').'

'.$this->l('Download the documentation').'
'; if (version_compare(_PS_VERSION_, '1.5', '<=')) { $this->_html .= ''; } $this->_html .= $this->postProcess(); $this->_html .= '
'.$this->l('Criteo Export').'
X ' .$this->l('URL to communicate to Criteo:').'
    '; $use_ssl = (bool) Configuration::get('PS_SSL_ENABLED'); $url_query = array( 'ajax' => true, 'action' => 'XML', ); if (version_compare(_PS_VERSION_, '1.5', '>=')) { $shops = Shop::getShops(); foreach ($shops as $shop) { $url_query['id_shop'] = $shop['id_shop']; $url_query['token'] = $this->getFrontToken($url_query); $url = $this->context->link->getModuleLink($this->name, 'export', $url_query, $use_ssl); $this->_html .= '
  • '.$url.'
  • '; } } else { $token = sha1(_COOKIE_KEY_.'exportCriteo'); $this->_html .= ' '.Tools::getProtocol().$_SERVER['HTTP_HOST'].__PS_BASE_URI__.'modules/'.$this->name.'/tools/export_xml.php?token='.$token.''; } $this->_html .= '




  No       Yes

  • '.$this->l('You can exclude categories, so that the products are not present.').'
  • '.$this->l('Warning !').' '.$this->l('Products with the default category is selected below will not be exported.').'

'.$this->l('Category filter').'

'; $done = array(); $index = array(); $indexed_categories = explode(',', Configuration::get('WIC_CRITEO_CATEGORY')); $categories = Category::getCategories((int) $this->context->language->id, false); foreach ($indexed_categories as $k => $row) { $index[] = $row; } $this->recurseCategoryForInclude($index, $categories, $categories[0][1], 1, null, $done); $this->_html .= '
'.$this->l('ID').' '.$this->l('Name').'

'.$this->l('Mark all checkbox(es) of categories to which the product are not in data XML flow').' *


'; $this->_html .= ''; return $this->_html; } /* Build a categories tree * * @param array $indexed_categories Array with categories where product is indexed (in order to check checkbox) * @param array $categories Categories to list * @param array $current Current category * @param integer $id_category Current category id */ private function recurseCategoryForInclude($indexed_categories, $categories, $current, $id_category = 1, $id_category_default = null, $has_suite = array(), $done = array()) { static $irow; if (!isset($done[$current['infos']['id_parent']])) { $done[$current['infos']['id_parent']] = 0; } $done[$current['infos']['id_parent']] += 1; $todo = count($categories[$current['infos']['id_parent']]); $done_c = $done[$current['infos']['id_parent']]; $level = $current['infos']['level_depth'] + 1; $this->_html .= ' '.$id_category.' '; if (version_compare(_PS_VERSION_, '1.4', '>=')) { for ($i = 2; $i < $level; ++$i) { $this->_html .= ''; } $this->_html .= '   '; } else { $img = $level == 1 ? 'lv1.gif' : 'lv'.$level.'_'.($todo == $done_c ? 'f' : 'b').'.gif'; $this->_html .= '  '; } $this->_html .= ' '; if ($level > 1) { $has_suite[] = ($todo == $done_c ? 0 : 1); } if (isset($categories[$id_category])) { foreach ($categories[$id_category] as $key => $row) { if ($key != 'infos') { $this->recurseCategoryForInclude($indexed_categories, $categories, $categories[$id_category][$key], $key, $has_suite, $done); } } } } public function buildXML($id_shop) { $cache_key = sprintf('criteo_feed_%d', $id_shop); $cache = Cache::getInstance(); $legacy_images = defined('PS_LEGACY_IMAGES') && PS_LEGACY_IMAGES; if ($cache->exists($cache_key)) { if ($xml = gzdecode($cache->get($cache_key))) { return $xml; } } $sxe = new SimpleXMLElement(''."\n".''); /* First line, columns */ $columns = array('id', 'name', 'smallimage', 'bigimage', 'producturl', 'description', 'price', 'retailprice', 'discount', 'recommendable', 'instock'); /* Setting parameters */ $conf = Configuration::getMultiple(array( 'PS_LANG_DEFAULT', )); /* Searching for products */ $sql = 'SELECT DISTINCT p.`id_product`, i.`id_image` FROM `'._DB_PREFIX_.'product` p JOIN `'._DB_PREFIX_.'category_product` cp ON (cp.id_product = p.id_product) LEFT JOIN `'._DB_PREFIX_.'image` i ON (i.id_product = p.id_product) WHERE p.`active` = 1 AND i.id_image IS NOT NULL'; if (version_compare(_PS_VERSION_, '1.5', '>=') && $id_shop) { $sql .= ' AND p.`id_product` IN (SELECT ps.`id_product` FROM `'._DB_PREFIX_.'product_shop` ps WHERE ps.`id_shop` = '.(int) $id_shop.')'; } if (Configuration::get('WIC_CRITEO_CATEGORY')) { $array_category = explode(',', Configuration::get('WIC_CRITEO_CATEGORY')); $array_category = array_map('intval', $array_category); $sql .= ' AND p.`id_category_default` NOT IN ('.implode(',', $array_category).')'; } $display_cat = Configuration::get('WIC_CRITEO_DISPLAY_CAT'); $sql .= ' GROUP BY p.id_product'; $result = Db::getInstance()->executeS($sql); foreach (array_values($result) as $row) { if (Pack::isPack((int) $row['id_product'])) { continue; } $product = new Product((int) $row['id_product'], true); if (Validate::isLoadedObject($product)) { $imageObj = Product::getCover((int) $product->id); $line = array(); $line[] = (($product->manufacturer_name) ? $product->manufacturer_name.' - ' : '').$product->name[(int) $conf['PS_LANG_DEFAULT']]; $line[] = $this->context->link->getImageLink($product->link_rewrite[(int) $conf['PS_LANG_DEFAULT']], (!$legacy_images ? $imageObj['id_image'] : $product->id.'-'.$imageObj['id_image']), (version_compare(_PS_VERSION_, '1.5', '>=') ? ImageType::getFormatedName('small') : 'small')); $line[] = $this->context->link->getImageLink($product->link_rewrite[(int) $conf['PS_LANG_DEFAULT']], (!$legacy_images ? $imageObj['id_image'] : $product->id.'-'.$imageObj['id_image']), (version_compare(_PS_VERSION_, '1.5', '>=') ? ImageType::getFormatedName('thickbox') : 'thickbox')); $line[] = $this->context->link->getProductLink((int) $product->id, $product->link_rewrite[(int) $conf['PS_LANG_DEFAULT']], $product->ean13).'?utm_source=criteo&aff=criteo'; $line[] = str_replace(array("\n", "\r", "\t", '|'), '', strip_tags(html_entity_decode($product->description_short[(int) $conf['PS_LANG_DEFAULT']], ENT_COMPAT, 'UTF-8'))); unset($imageObj); $price = $product->getPrice(true, (int) Product::getDefaultAttribute($product->id)); if ($product->getPrice(true, (int) Product::getDefaultAttribute((int) $product->id), 6, null, false, false)) { $val = $product->getPrice(true, (int) Product::getDefaultAttribute((int) $product->id), 6, null, false, false); } else { $val = 1; } $line[] = number_format($price, 2, '.', ''); $line[] = number_format($product->getPrice(true, (int) Product::getDefaultAttribute((int) $product->id), 6, null, false, false), 2, '.', ''); $line[] = number_format($product->getPrice(true, null, 2, null, true) * 100 / $val, 2, '.', ''); $line[] = '1'; $line[] = $product->quantity > 0 ? '1' : '0'; $cpt_xml = 1; $product_xml = $sxe->addChild('product'); $product_xml->addAttribute('id', $product->id); foreach ($line as $column) { $product_xml->addChild($columns[$cpt_xml], htmlspecialchars($column)); ++$cpt_xml; } if ($display_cat) { $categories = Product::getProductCategoriesFull((int) $product->id, $conf['PS_LANG_DEFAULT']); if ($categories) { $i = 1; foreach ($categories as $category) { $product_xml->addChild('category_'.$i, htmlspecialchars($category['name'])); ++$i; } } } unset($product, $product_xml, $cpt_xml, $i); } } // One day in seconds $ttl = 86400; $cache->set($cache_key, gzencode($sxe->asXML()), $ttl); return $sxe->asXML(); } public function fetchTemplate($path, $name, $extension = false) { return $this->display(__FILE__, $path.$name.'.'.($extension ? $extension : 'tpl')); } public function hookShoppingCartExtra($params) { if (!Configuration::get('WIC_CRITEO_ID_ACCOUNT') || !Configuration::get('WIC_CRITEO_SITE_TYPE')) { return false; } $product_list = array(); foreach ($params['products'] as $product) { $product_obj = new Product((int) $product['id_product']); $price = $product_obj->getPrice(true, ($product['id_product_attribute'] ? $product['id_product_attribute'] : (int) Product::getDefaultAttribute($product_obj->id)), 2); $product_list[] = array( 'id' => (int) $product['id_product'], 'price' => (float) $price, 'quantity' => (int) $product['quantity'], ); unset($product_obj); } if ($this->context->customer->id) { $customer = new Customer($this->context->customer->id); if (Validate::isLoadedObject($customer)) { $email = $customer->email; } else { $email = ''; } } else { $email = ''; } $this->context->smarty->assign(array( 'wic_criteo_account' => Configuration::get('WIC_CRITEO_ID_ACCOUNT'), 'wic_criteo_site_type' => Configuration::get('WIC_CRITEO_SITE_TYPE'), 'wic_product_list' => $product_list, 'wic_action' => 'shoppingCart', 'id_customer' => $this->context->customer->id, 'customer_email' => ($email) ? md5($email) : '', 'currency' => $this->context->currency->iso_code, )); return $this->fetchTemplate('/views/templates/hooks/', 'criteo'); } public function hookOrderConfirmation($params) { if (!Configuration::get('WIC_CRITEO_ID_ACCOUNT') || !Configuration::get('WIC_CRITEO_SITE_TYPE')) { return false; } $cart = new Cart((int) $params['objOrder']->id_cart); // Use refresh option to avoid differences with shopping cart tag. $products = $cart->getProducts(true); $product_list = array(); foreach ($products as $product) { $product_obj = new Product((int) $product['id_product']); $price = $product_obj->getPrice(true, ($product['id_product_attribute'] ? $product['id_product_attribute'] : (int) Product::getDefaultAttribute($product_obj->id)), 2); $product_list[] = array( 'id' => (int) $product['id_product'], 'price' => (float) $price, 'quantity' => (int) $product['quantity'], ); unset($product_obj); } $customer = new Customer($this->context->customer->id); $new = Db::getInstance(_PS_USE_SQL_SLAVE_)->getValue(' SELECT COUNT(`id_order`) FROM `'._DB_PREFIX_.'orders` o WHERE o.valid = 1 AND o.`id_customer` = '.(int) $customer->id); $this->context->smarty->assign(array( 'wic_criteo_account' => Configuration::get('WIC_CRITEO_ID_ACCOUNT'), 'wic_criteo_site_type' => Configuration::get('WIC_CRITEO_SITE_TYPE'), 'wic_product_list' => $product_list, 'wic_action' => 'orderConfirmation', 'wic_id_order' => (int) $params['objOrder']->id, 'id_customer' => $this->context->customer->id, 'old_customer' => (($new > 1) ? '1' : '0'), 'customer_email' => ($customer->email) ? md5($customer->email) : '', 'currency' => $this->context->currency->iso_code, )); return $this->fetchTemplate('/views/templates/hooks/', 'criteo'); } public function hookHeader($params) { if (!Configuration::get('WIC_CRITEO_ID_ACCOUNT') || !Configuration::get('WIC_CRITEO_SITE_TYPE')) { return false; } return ''; } public function hookHome($params) { if (!Configuration::get('WIC_CRITEO_ID_ACCOUNT') || !Configuration::get('WIC_CRITEO_SITE_TYPE')) { return false; } if ($this->context->customer->id) { $customer = new Customer($this->context->customer->id); if (Validate::isLoadedObject($customer)) { $email = $customer->email; } else { $email = ''; } } else { $email = ''; } $this->context->smarty->assign(array( 'wic_criteo_account' => Configuration::get('WIC_CRITEO_ID_ACCOUNT'), 'wic_criteo_site_type' => Configuration::get('WIC_CRITEO_SITE_TYPE'), 'wic_action' => 'home', 'id_customer' => $this->context->customer->id, 'customer_email' => ($email) ? md5($email) : '', )); return $this->fetchTemplate('/views/templates/hooks/', 'criteo'); } public function hookFooter($params) { if (!Configuration::get('WIC_CRITEO_ID_ACCOUNT') || !Configuration::get('WIC_CRITEO_SITE_TYPE')) { return false; } $wic_criteo_site_type = 'd'; if (class_exists('Mobile_Detect')) { $detect = new Mobile_Detect; if ($detect->isMobile()) { $wic_criteo_site_type = 'm'; } elseif ($detect->isTablet()){ $wic_criteo_site_type = 't'; } else { $wic_criteo_site_type = 'd'; } } $step = Tools::getValue('step', 0); if (Context::getContext()->controller->php_self == 'order' && $step == 0) { $cart = Context::getContext()->cart; $products = $cart->getProducts(); $product_list = array(); foreach ($products as $product) { $product_obj = new Product((int) $product['id_product']); $price = $product_obj->getPrice(true, ($product['id_product_attribute'] ? $product['id_product_attribute'] : (int) Product::getDefaultAttribute($product_obj->id)), 2); $product_list[] = array( 'id' => (int) $product['id_product'], 'price' => (float) $price, 'quantity' => (int) $product['quantity'], ); unset($product_obj); } if ($this->context->customer->id) { $customer = new Customer($this->context->customer->id); if (Validate::isLoadedObject($customer)) { $email = $customer->email; } else { $email = ''; } } else { $email = ''; } $this->context->smarty->assign(array( 'wic_criteo_account' => Configuration::get('WIC_CRITEO_ID_ACCOUNT'), 'wic_criteo_site_type' => $wic_criteo_site_type, 'wic_product_list' => $product_list, 'wic_action' => 'shoppingCart', 'id_customer' => $this->context->customer->id, 'customer_email' => ($email) ? md5($email) : '', 'currency' => $this->context->currency->iso_code, )); return $this->fetchTemplate('/views/templates/hooks/', 'criteo'); } elseif (Context::getContext()->controller->php_self == 'product') { if ($this->context->customer->id) { $customer = new Customer($this->context->customer->id); if (Validate::isLoadedObject($customer)) { $email = $customer->email; } else { $email = ''; } } else { $email = ''; } $this->context->smarty->assign(array( 'wic_criteo_account' => Configuration::get('WIC_CRITEO_ID_ACCOUNT'), 'wic_criteo_site_type' => $wic_criteo_site_type, 'wic_product_id' => Tools::getValue('id_product'), 'wic_action' => 'productFooter', 'id_customer' => $this->context->customer->id, 'customer_email' => ($email) ? md5($email) : '', )); return $this->fetchTemplate('/views/templates/hooks/', 'criteo'); } elseif (Context::getContext()->controller->php_self == 'homestore') { if ($this->context->customer->id) { $customer = new Customer($this->context->customer->id); if (Validate::isLoadedObject($customer)) { $email = $customer->email; } else { $email = ''; } } else { $email = ''; } $this->context->smarty->assign(array( 'wic_criteo_account' => Configuration::get('WIC_CRITEO_ID_ACCOUNT'), 'wic_criteo_site_type' => $wic_criteo_site_type, 'wic_action' => 'home', 'id_customer' => $this->context->customer->id, 'customer_email' => ($email) ? md5($email) : '', )); return $this->fetchTemplate('/views/templates/hooks/', 'criteo'); } elseif (Tools::getValue('id_category')) { $products = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS(' SELECT cp.`id_product` FROM `'._DB_PREFIX_.'product` p LEFT JOIN `'._DB_PREFIX_.'category_product` cp ON p.`id_product` = cp.`id_product` WHERE cp.`id_category` = '.(int) Tools::getValue('id_category').' AND p.`active` = 1 ORDER BY cp.`position` LIMIT 3'); if ($this->context->customer->id) { $customer = new Customer($this->context->customer->id); if (Validate::isLoadedObject($customer)) { $email = $customer->email; } else { $email = ''; } } else { $email = ''; } $this->context->smarty->assign(array( 'wic_criteo_account' => Configuration::get('WIC_CRITEO_ID_ACCOUNT'), 'wic_criteo_site_type' => $wic_criteo_site_type, 'wic_action' => 'productList', 'id_customer' => $this->context->customer->id, 'customer_email' => ($email) ? md5($email) : '', )); if (isset($products)) { $products_data = array(); foreach ($products as $product) { $products_data[] = (int) $product['id_product']; } $this->context->smarty->assign(array('products_data' => implode(',', $products_data))); } return $this->fetchTemplate('/views/templates/hooks/', 'criteo'); } elseif (Tools::getValue('search_query')) { if ($this->context->customer->id) { $customer = new Customer($this->context->customer->id); if (Validate::isLoadedObject($customer)) { $email = $customer->email; } else { $email = ''; } } else { $email = ''; } $this->context->smarty->assign(array( 'wic_criteo_account' => Configuration::get('WIC_CRITEO_ID_ACCOUNT'), 'wic_criteo_site_type' => $wic_criteo_site_type, 'wic_action' => 'search', 'id_customer' => $this->context->customer->id, 'customer_email' => ($email) ? md5($email) : '', 'searchQuery' => Tools::getValue('search_query'), )); return $this->fetchTemplate('/views/templates/hooks/', 'criteo'); } else { return false; } } public function getFrontToken($query) { if (!empty($query['token'])) { unset($query['token']); } ksort($query); $query_string = http_build_query($query); return Tools::encrypt($query_string); } }