418 lines
16 KiB
PHP
Executable File
418 lines
16 KiB
PHP
Executable File
<?php
|
|
if (!defined('_PS_VERSION_'))
|
|
exit;
|
|
|
|
class GoogleSitemap extends Module {
|
|
private $_html = '';
|
|
private $_postErrors = array();
|
|
|
|
public function __construct() {
|
|
$this->name = 'googlesitemap';
|
|
$this->tab = 'seo';
|
|
$this->version = '1.2';
|
|
$this->author = 'Antadis';
|
|
$this->need_instance = 0;
|
|
|
|
parent::__construct();
|
|
|
|
$this->displayName = $this->l('Google sitemap with private sales support');
|
|
$this->description = $this->l('Generate your Google sitemap file');
|
|
|
|
if(!defined('GSITEMAP_FILE')) {
|
|
define('GSITEMAP_FILE', dirname(__FILE__).'/../../sitemap.xml');
|
|
}
|
|
}
|
|
|
|
public function install() {
|
|
if(!parent::install()) {
|
|
return FALSE;
|
|
}
|
|
|
|
if(Module::isInstalled('privatesales')) {
|
|
Db::getInstance()->Execute('
|
|
INSERT INTO `'._DB_PREFIX_.'privatesale_module`
|
|
VALUES (
|
|
(SELECT `id_module` FROM `'._DB_PREFIX_.'module` WHERE `name` = "googlesitemap"),
|
|
"googlesitemap"
|
|
)
|
|
');
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
public function uninstall() {
|
|
file_put_contents(GSITEMAP_FILE, '');
|
|
|
|
if(Module::isInstalled('privatesales')) {
|
|
Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.'privatesale_module` WHERE `modulename` = "googlesitemap"');
|
|
}
|
|
|
|
return parent::uninstall();
|
|
}
|
|
|
|
private function _postValidation() {
|
|
file_put_contents(GSITEMAP_FILE, '');
|
|
if(!($fp = fopen(GSITEMAP_FILE, 'w'))) {
|
|
$this->_postErrors[] = $this->l('Cannot create').' '.realpath(dirname(__FILE__.'/../..')).'/'.$this->l('sitemap.xml file.');
|
|
} else {
|
|
fclose($fp);
|
|
}
|
|
}
|
|
|
|
public function generateSitemap() {
|
|
global $cookie;
|
|
$link = new Link();
|
|
$langs = Language::getLanguages();
|
|
$iso_code = Language::getIsoById((int) $cookie->id_lang);
|
|
|
|
$xmlString = <<<XML
|
|
<?xml version="1.0" encoding="UTF-8" ?>
|
|
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"
|
|
xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
|
|
</urlset>
|
|
XML;
|
|
|
|
$xml = new SimpleXMLElement($xmlString);
|
|
|
|
if(Configuration::get('PS_REWRITING_SETTINGS') && sizeof($langs) > 1) {
|
|
foreach($langs as $lang) {
|
|
$this->_addSitemapNode($xml, Tools::getShopDomain(true, true).__PS_BASE_URI__.$lang['iso_code'].'/', '1.00', 'daily', date('Y-m-d'));
|
|
}
|
|
} else {
|
|
$this->_addSitemapNode($xml, Tools::getShopDomain(true, true).__PS_BASE_URI__, '1.00', 'daily', date('Y-m-d'));
|
|
}
|
|
|
|
/* CMS Generator */
|
|
if(Configuration::get('GSITEMAP_ALL_CMS') || !Module::isInstalled('blockcms')) {
|
|
$sql_cms = '
|
|
SELECT DISTINCT '.(Configuration::get('PS_REWRITING_SETTINGS')? 'cl.id_cms, cl.link_rewrite, cl.id_lang': 'cl.id_cms').'
|
|
FROM `'._DB_PREFIX_.'cms_lang` cl
|
|
LEFT JOIN `'._DB_PREFIX_.'lang` l
|
|
ON (cl.id_lang = l.id_lang)
|
|
WHERE l.`active` = 1
|
|
ORDER BY cl.id_cms, cl.id_lang ASC
|
|
';
|
|
} elseif (Module::isInstalled('blockcms')) {
|
|
$sql_cms = '
|
|
SELECT DISTINCT '.(Configuration::get('PS_REWRITING_SETTINGS')? 'cl.id_cms, cl.link_rewrite, cl.id_lang': 'cl.id_cms').'
|
|
FROM `'._DB_PREFIX_.'cms_block_page` b
|
|
LEFT JOIN `'._DB_PREFIX_.'cms_lang` cl
|
|
ON (b.id_cms = cl.id_cms)
|
|
LEFT JOIN '._DB_PREFIX_.'lang l
|
|
ON (cl.id_lang = l.id_lang)
|
|
WHERE l.`active` = 1
|
|
ORDER BY cl.id_cms, cl.id_lang ASC
|
|
';
|
|
}
|
|
|
|
$cmss = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS($sql_cms);
|
|
foreach($cmss as $cms) {
|
|
$tmpLink = Configuration::get('PS_REWRITING_SETTINGS')? $link->getCMSLink((int)$cms['id_cms'], $cms['link_rewrite'], FALSE, (int) $cms['id_lang']): $link->getCMSLink((int)$cms['id_cms']);
|
|
$this->_addSitemapNode($xml, $tmpLink, '0.8', 'daily');
|
|
}
|
|
|
|
/* Categories Generator */
|
|
$exclude_categories = array();
|
|
if(Module::isInstalled('privatesales')) {
|
|
include(dirname(__FILE__).'/../privatesales/Sale.php');
|
|
$has_trailers = file_exists(dirname(__FILE__).'/../privatesales/trailer.php');
|
|
$sales = Sale::getSales(TRUE, NULL, NULL, 'not_ended');
|
|
|
|
foreach($sales as $sale) {
|
|
$exclude_categories = array_merge($exclude_categories, Sale::getCategoriesFromCache($sale->id));
|
|
if($has_trailers) {
|
|
$trailers_i18n = array(
|
|
'fr' => 'bande-annonce',
|
|
'en' => 'trailer',
|
|
);
|
|
|
|
if(Configuration::get('PS_REWRITING_SETTINGS')) {
|
|
if(count($langs) > 1) {
|
|
$this->_addSitemapNode($xml, Tools::getShopDomain(TRUE, TRUE).__PS_BASE_URI__.$iso_code.'/'.(isset($trailers_i18n[$iso_code])? $trailers_i18n[$iso_code]: $trailers_i18n['en']).'/'.$sale->id.'-'.Tools::str2url($sale->title[$cookie->id_lang]), '0.8', 'weekly');
|
|
} else {
|
|
$this->_addSitemapNode($xml, Tools::getShopDomain(TRUE, TRUE).__PS_BASE_URI__.(isset($trailers_i18n[$iso_code])? $trailers_i18n[$iso_code]: $trailers_i18n['en']).'/'.$sale->id.'-'.Tools::str2url($sale->title[$cookie->id_lang]), '0.8', 'weekly');
|
|
}
|
|
} else {
|
|
$this->_addSitemapNode($xml, Tools::getShopDomain(TRUE, TRUE).__PS_BASE_URI__.'modules/privatesales/trailer.php?id_sale='.$sale->id, '0.8', 'weekly');
|
|
}
|
|
}
|
|
}
|
|
|
|
$ordering = (int) Configuration::get('PRIVATESALES_FEATURED_ORDER');
|
|
if($ordering == 0) {
|
|
if(Module::isInstalled('privatesales_brands')) {
|
|
$sales = Sale::getSales(TRUE, (int) Configuration::get('PRIVATESALES_FEATURED_IGNORE') == 1? NULL: !((bool) Configuration::get('PRIVATESALES_GUESTLIST')), TRUE, (bool) Configuration::get('PRIVATESALES_FEATURED_CURRENT'), TRUE);
|
|
|
|
$brands = array();
|
|
foreach(Db::getInstance()->ExecuteS('
|
|
SELECT `id_brand`
|
|
FROM `'._DB_PREFIX_.'privatesale_brands`
|
|
WHERE `id_sale` IN ('.implode(', ', $sales).')
|
|
GROUP BY `id_brand`
|
|
') as $b) {
|
|
$brands[] = $b['id_brand'];
|
|
}
|
|
|
|
$manufacturers = Db::getInstance()->ExecuteS('
|
|
SELECT m.*, ml.`short_description`
|
|
FROM `'._DB_PREFIX_.'manufacturer` m
|
|
LEFT JOIN `'._DB_PREFIX_.'manufacturer_lang` ml
|
|
ON (
|
|
m.`id_manufacturer` = ml.`id_manufacturer`
|
|
AND ml.`id_lang` = '.(int) $cookie->id_lang.'
|
|
)
|
|
WHERE m.`active` = 1
|
|
AND m.`id_manufacturer` IN ('.implode(', ', $brands).')
|
|
ORDER BY m.`name` ASC
|
|
');
|
|
} else {
|
|
$manufacturers = Manufacturer::getManufacturers(TRUE, (int) $cookie->id_lang, TRUE, FALSE, FALSE, TRUE);
|
|
}
|
|
|
|
$brands_i18n = array(
|
|
'fr' => 'marques',
|
|
'en' => 'brands',
|
|
);
|
|
foreach($manufacturers as $manufacturer) {
|
|
if(Configuration::get('PS_REWRITING_SETTINGS')) {
|
|
if(count($langs) > 1) {
|
|
$this->_addSitemapNode($xml, Tools::getShopDomain(true, true).__PS_BASE_URI__.$iso_code.'/'.(isset($brands_i18n[$iso_code])? $brands_i18n[$iso_code]: $brands_i18n['en']).'/'.$manufacturer['id_manufacturer'].'-'.Tools::str2url($manufacturer['name']), '0.8', 'weekly');
|
|
} else {
|
|
$this->_addSitemapNode($xml, Tools::getShopDomain(true, true).__PS_BASE_URI__.(isset($brands_i18n[$iso_code])? $brands_i18n[$iso_code]: $brands_i18n['en']).'/'.$manufacturer['id_manufacturer'].'-'.Tools::str2url($manufacturer['name']), '0.8', 'weekly');
|
|
}
|
|
} else {
|
|
$this->_addSitemapNode($xml, Tools::getShopDomain(true, true).__PS_BASE_URI__.'modules/privatesales/featured.php?id_brand='.$manufacturer['id_manufacturer'], '0.8', 'weekly');
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if(Configuration::get('PS_REWRITING_SETTINGS')) {
|
|
$categories = Db::getInstance()->ExecuteS('
|
|
SELECT c.id_category, c.level_depth, link_rewrite, DATE_FORMAT(IF(date_upd,date_upd,date_add), \'%Y-%m-%d\') AS date_upd, cl.id_lang
|
|
FROM '._DB_PREFIX_.'category c
|
|
LEFT JOIN '._DB_PREFIX_.'category_lang cl
|
|
ON c.id_category = cl.id_category
|
|
LEFT JOIN '._DB_PREFIX_.'lang l
|
|
ON cl.id_lang = l.id_lang
|
|
WHERE l.`active` = 1
|
|
AND c.`active` = 1
|
|
AND c.id_category != 1
|
|
'.(count($exclude_categories) > 0? ' AND c.id_category NOT IN ('.implode(', ', $exclude_categories).')': '').'
|
|
ORDER BY cl.id_category, cl.id_lang ASC
|
|
');
|
|
} else {
|
|
$categories = Db::getInstance()->ExecuteS('
|
|
SELECT c.id_category, c.level_depth, DATE_FORMAT(IF(date_upd,date_upd,date_add), \'%Y-%m-%d\') AS date_upd
|
|
FROM '._DB_PREFIX_.'category c
|
|
'.(count($exclude_categories) > 0? ' AND c.id_category NOT IN ('.implode(', ', $exclude_categories).')': '').'
|
|
ORDER BY c.id_category ASC
|
|
');
|
|
}
|
|
|
|
foreach($categories as $category) {
|
|
if(($priority = 0.9 - ($category['level_depth'] / 10)) < 0.1) {
|
|
$priority = 0.1;
|
|
}
|
|
|
|
$tmpLink = Configuration::get('PS_REWRITING_SETTINGS')? $link->getCategoryLink((int)$category['id_category'], $category['link_rewrite'], (int)$category['id_lang']): $link->getCategoryLink((int)$category['id_category']);
|
|
$this->_addSitemapNode($xml, htmlspecialchars($tmpLink), $priority, 'weekly', substr($category['date_upd'], 0, 10));
|
|
}
|
|
|
|
$products = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS('
|
|
SELECT p.id_product, pl.link_rewrite, DATE_FORMAT(IF(date_upd,date_upd,date_add), \'%Y-%m-%d\') date_upd, pl.id_lang, cl.`link_rewrite` category, ean13, i.id_image, il.legend legend_image, (
|
|
SELECT MIN(level_depth)
|
|
FROM '._DB_PREFIX_.'product p2
|
|
LEFT JOIN '._DB_PREFIX_.'category_product cp2
|
|
ON p2.id_product = cp2.id_product
|
|
LEFT JOIN '._DB_PREFIX_.'category c2
|
|
ON cp2.id_category = c2.id_category
|
|
WHERE p2.id_product = p.id_product AND p2.`active` = 1
|
|
AND c2.`active` = 1
|
|
) AS level_depth
|
|
FROM '._DB_PREFIX_.'product p
|
|
LEFT JOIN '._DB_PREFIX_.'product_lang pl
|
|
ON (p.id_product = pl.id_product)
|
|
LEFT JOIN `'._DB_PREFIX_.'category_lang` cl
|
|
ON (p.`id_category_default` = cl.`id_category` AND pl.`id_lang` = cl.`id_lang`)
|
|
LEFT JOIN '._DB_PREFIX_.'image i
|
|
ON p.id_product = i.id_product
|
|
LEFT JOIN `'._DB_PREFIX_.'image_lang` il
|
|
ON (i.`id_image` = il.`id_image`
|
|
AND pl.`id_lang` = il.`id_lang`)
|
|
LEFT JOIN '._DB_PREFIX_.'lang l
|
|
ON (pl.id_lang = l.id_lang)
|
|
WHERE l.`active` = 1
|
|
AND p.`active` = 1
|
|
'.(count($exclude_categories) > 0? ' AND p.id_category_default NOT IN ('.implode(', ', $exclude_categories).')': '').'
|
|
'.(Configuration::get('GSITEMAP_ALL_PRODUCTS') ? '' : 'HAVING level_depth IS NOT NULL').'
|
|
ORDER BY pl.id_product, pl.id_lang ASC
|
|
');
|
|
|
|
$tmp = NULL;
|
|
$res = NULL;
|
|
foreach($products as $product) {
|
|
if($tmp == $product['id_product']) {
|
|
$res[$tmp]['images'][] = array('id_image' => $product['id_image'], 'legend_image' => $product['legend_image']);
|
|
} else {
|
|
$tmp = $product['id_product'];
|
|
$res[$tmp] = $product;
|
|
unset($res[$tmp]['id_image'], $res[$tmp]['legend_image']);
|
|
$res[$tmp]['images'][] = array('id_image' => $product['id_image'], 'legend_image' => $product['legend_image']);
|
|
}
|
|
}
|
|
|
|
foreach($res as $product) {
|
|
if(($priority = 0.7 - ($product['level_depth'] / 10)) < 0.1) {
|
|
$priority = 0.1;
|
|
}
|
|
|
|
$tmpLink = $link->getProductLink((int) $product['id_product'], $product['link_rewrite'], $product['category'], $product['ean13'], (int) $product['id_lang']);
|
|
$sitemap = $this->_addSitemapNode($xml, htmlspecialchars($tmpLink), $priority, 'weekly', substr($product['date_upd'], 0, 10));
|
|
$sitemap = $this->_addSitemapNodeImage($sitemap, $product);
|
|
}
|
|
|
|
/* Add classic pages (contact, best sales, new products...) */
|
|
$pages = array(
|
|
'authentication' => TRUE,
|
|
'best-sales' => FALSE,
|
|
'contact-form' => TRUE,
|
|
'discount' => FALSE,
|
|
'index' => FALSE,
|
|
'manufacturer' => FALSE,
|
|
'new-products' => FALSE,
|
|
'prices-drop' => FALSE,
|
|
'supplier' => FALSE,
|
|
'store' => FALSE,
|
|
);
|
|
|
|
// Don't show suppliers and manufacturers if they are disallowed
|
|
if(!Module::getInstanceByName('blockmanufacturer')->id && !Configuration::get('PS_DISPLAY_SUPPLIERS')) {
|
|
unset($pages['manufacturer']);
|
|
}
|
|
|
|
if(!Module::getInstanceByName('blocksupplier')->id && !Configuration::get('PS_DISPLAY_SUPPLIERS')) {
|
|
unset($pages['supplier']);
|
|
}
|
|
|
|
// Generate nodes for pages
|
|
if(Configuration::get('PS_REWRITING_SETTINGS')) {
|
|
foreach($pages as $page => $ssl) {
|
|
foreach($langs as $lang) {
|
|
$this->_addSitemapNode($xml, $link->getPageLink($page.'.php', $ssl, $lang['id_lang']), '0.5', 'monthly');
|
|
}
|
|
}
|
|
} else {
|
|
foreach($pages as $page => $ssl) {
|
|
$this->_addSitemapNode($xml, $link->getPageLink($page.'.php', $ssl), '0.5', 'monthly');
|
|
}
|
|
}
|
|
|
|
$xmlString = $xml->asXML();
|
|
|
|
$fp = fopen(GSITEMAP_FILE, 'w');
|
|
fwrite($fp, $xmlString);
|
|
fclose($fp);
|
|
}
|
|
|
|
|
|
private function _postProcess() {
|
|
Configuration::updateValue('GSITEMAP_ALL_CMS', (int) Tools::getValue('GSITEMAP_ALL_CMS'));
|
|
Configuration::updateValue('GSITEMAP_ALL_PRODUCTS', (int) Tools::getValue('GSITEMAP_ALL_PRODUCTS'));
|
|
|
|
$this->generateSitemap();
|
|
|
|
$res = file_exists(GSITEMAP_FILE);
|
|
$this->_html .= '<h3 class="'. ($res? 'conf confirm': 'alert error').'" style="margin-bottom: 20px">';
|
|
$this->_html .= $res? $this->l('Sitemap file generated'): $this->l('Error while creating sitemap file');
|
|
$this->_html .= '</h3>';
|
|
}
|
|
|
|
private function getUrlWith($url, $key, $value) {
|
|
if(empty($value)) {
|
|
return $url;
|
|
}
|
|
if(strpos($url, '?') !== FALSE) {
|
|
return $url.'&'.$key.'='.$value;
|
|
}
|
|
return $url.'?'.$key.'='.$value;
|
|
}
|
|
|
|
private function _addSitemapNode($xml, $loc, $priority, $change_freq, $last_mod=NULL) {
|
|
$sitemap = $xml->addChild('url');
|
|
$sitemap->addChild('loc', $loc);
|
|
$sitemap->addChild('priority', $priority);
|
|
if($last_mod) {
|
|
$sitemap->addChild('lastmod', $last_mod);
|
|
}
|
|
$sitemap->addChild('changefreq', $change_freq);
|
|
return $sitemap;
|
|
}
|
|
|
|
private function _addSitemapNodeImage($xml, $product) {
|
|
foreach($product['images'] as $img) {
|
|
$link = new Link();
|
|
$image = $xml->addChild('image', NULL, 'http://www.google.com/schemas/sitemap-image/1.1');
|
|
$image->addChild('loc', $link->getImageLink($product['link_rewrite'], (int) $product['id_product'].'-'.(int) $img['id_image']), 'http://www.google.com/schemas/sitemap-image/1.1');
|
|
|
|
$legend_image = preg_replace('/(&+)/i', '&', $img['legend_image']);
|
|
$image->addChild('caption', $legend_image, 'http://www.google.com/schemas/sitemap-image/1.1');
|
|
$image->addChild('title', $legend_image, 'http://www.google.com/schemas/sitemap-image/1.1');
|
|
}
|
|
}
|
|
|
|
private function _displaySitemap() {
|
|
if(file_exists(GSITEMAP_FILE) && filesize(GSITEMAP_FILE)) {
|
|
$fp = fopen(GSITEMAP_FILE, 'r');
|
|
$fstat = fstat($fp);
|
|
fclose($fp);
|
|
$xml = simplexml_load_file(GSITEMAP_FILE);
|
|
|
|
$nbPages = sizeof($xml->url);
|
|
|
|
$this->_html .= '<p>'.$this->l('Your Google sitemap file is online at the following address:').'<br />
|
|
<a href="'.Tools::getShopDomain(true, true).__PS_BASE_URI__.'sitemap.xml" target="_blank"><b>'.Tools::getShopDomain(true, true).__PS_BASE_URI__.'sitemap.xml</b></a></p><br />';
|
|
|
|
$this->_html .= $this->l('Update:').' <b>'.utf8_encode(strftime('%A %d %B %Y %H:%M:%S', $fstat['mtime'])).'</b><br />';
|
|
$this->_html .= $this->l('Filesize:').' <b>'.number_format(($fstat['size']*.000001), 3).'MB</b><br />';
|
|
$this->_html .= $this->l('Indexed pages:').' <b>'.$nbPages.'</b><br /><br />';
|
|
}
|
|
}
|
|
|
|
private function _displayForm() {
|
|
$this->_html .=
|
|
'<form action="'.Tools::htmlentitiesUTF8($_SERVER['REQUEST_URI']).'" method="post">
|
|
<div style="margin:0 0 20px 0;">
|
|
<input type="checkbox" name="GSITEMAP_ALL_PRODUCTS" id="GSITEMAP_ALL_PRODUCTS" style="vertical-align: middle;" value="1" '.(Configuration::get('GSITEMAP_ALL_PRODUCTS') ? 'checked="checked"' : '').' /> <label class="t" for="GSITEMAP_ALL_PRODUCTS">'.$this->l('Sitemap also includes products from inactive categories').'</label>
|
|
</div>
|
|
<div style="margin:0 0 20px 0;">
|
|
<input type="checkbox" name="GSITEMAP_ALL_CMS" id="GSITEMAP_ALL_CMS" style="vertical-align: middle;" value="1" '.(Configuration::get('GSITEMAP_ALL_CMS') ? 'checked="checked"' : '').' /> <label class="t" for="GSITEMAP_ALL_CMS">'.$this->l('Sitemap also includes CMS pages which are not in a CMS block').'</label>
|
|
</div>
|
|
<input name="btnSubmit" class="button" type="submit"
|
|
value="'.((!file_exists(GSITEMAP_FILE))? $this->l('Generate sitemap file'): $this->l('Update sitemap file')).'" />
|
|
</form>';
|
|
}
|
|
|
|
public function getContent() {
|
|
$this->_html .= '<h2>'.$this->l('Search Engine Optimization').'</h2>
|
|
'.$this->l('See').' <a href="https://www.google.com/webmasters/tools/docs/en/about.html" style="font-weight:bold;text-decoration:underline;" target="_blank">
|
|
'.$this->l('this page').'</a> '.$this->l('for more information').'<br /><br />';
|
|
if(Tools::isSubmit('btnSubmit')) {
|
|
$this->_postValidation();
|
|
if (!sizeof($this->_postErrors)) {
|
|
$this->_postProcess();
|
|
} else {
|
|
foreach ($this->_postErrors as $err) {
|
|
$this->_html .= '<div class="alert error">'.$err.'</div>';
|
|
}
|
|
}
|
|
}
|
|
|
|
$this->_displaySitemap();
|
|
$this->_displayForm();
|
|
|
|
return $this->_html;
|
|
}
|
|
}
|