PageRenderTime 51ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/gsitemap/gsitemap.php

https://github.com/DaveBenNoah/PrestaShop-modules
PHP | 867 lines | 602 code | 83 blank | 182 comment | 89 complexity | dc6f8693f673aaa024dbdf6a07010ef6 MD5 | raw file
Possible License(s): Apache-2.0, CC-BY-SA-3.0
  1. <?php
  2. /*
  3. * 2007-2014 PrestaShop
  4. *
  5. * NOTICE OF LICENSE
  6. * This source file is subject to the Academic Free License (AFL 3.0)
  7. * that is bundled with this package in the file LICENSE.txt.
  8. * It is also available through the world-wide-web at this URL:
  9. * http://opensource.org/licenses/afl-3.0.php* If you did not receive a copy of the license and are unable to
  10. * obtain it through the world-wide-web, please send an email
  11. * to license@prestashop.com so we can send you a copy immediately.
  12. *
  13. * DISCLAIMER
  14. *
  15. * Do not edit or add to this file if you wish to upgrade PrestaShop to newer
  16. * versions in the future. If you wish to customize PrestaShop for your
  17. * needs please refer to http://www.prestashop.com for more information.
  18. *
  19. * @author PrestaShop SA <contact@prestashop.com>
  20. * @copyright 2007-2014 PrestaShop SA
  21. * @version Release: $Revision: 7515 $
  22. * @license http://opensource.org/licenses/afl-3.0.php Academic Free License (AFL 3.0)
  23. * International Registered Trademark & Property of PrestaShop SA
  24. */
  25. if (!defined('_PS_VERSION_'))
  26. exit;
  27. class Gsitemap extends Module
  28. {
  29. public $cron = false;
  30. private $sql_checks = array();
  31. public function __construct()
  32. {
  33. $this->name = 'gsitemap';
  34. $this->tab = 'seo';
  35. $this->version = '2.3.9';
  36. $this->author = 'PrestaShop';
  37. $this->need_instance = 0;
  38. parent::__construct();
  39. $this->displayName = $this->l('Google sitemap');
  40. $this->description = $this->l('Generate your Google sitemap file');
  41. }
  42. /**
  43. * Google Sitemap installation process:
  44. *
  45. * Step 1 - Pre-set Configuration option values
  46. * Step 2 - Install the Addon and create a database table to store Sitemap files name by shop
  47. *
  48. * @return boolean Installation result
  49. */
  50. public function install()
  51. {
  52. foreach (array(
  53. 'GSITEMAP_PRIORITY_HOME' => 1.0,
  54. 'GSITEMAP_PRIORITY_PRODUCT' => 0.9,
  55. 'GSITEMAP_PRIORITY_CATEGORY' => 0.8,
  56. 'GSITEMAP_PRIORITY_MANUFACTURER' => 0.7,
  57. 'GSITEMAP_PRIORITY_SUPPLIER' => 0.6,
  58. 'GSITEMAP_PRIORITY_CMS' => 0.5,
  59. 'GSITEMAP_FREQUENCY' => 'weekly',
  60. 'GSITEMAP_CHECK_IMAGE_FILE' => false,
  61. 'GSITEMAP_LAST_EXPORT' => false
  62. ) as $key => $val)
  63. if (!Configuration::updateValue($key, $val))
  64. return false;
  65. return parent::install() &&
  66. Db::getInstance()->Execute('CREATE TABLE IF NOT EXISTS `'._DB_PREFIX_.'gsitemap_sitemap` (`link` varchar(255) DEFAULT NULL, `id_shop` int(11) DEFAULT 0) ENGINE='._MYSQL_ENGINE_.' DEFAULT CHARSET=utf8;') &&
  67. $this->_installOverride();
  68. }
  69. private function _installOverride()
  70. {
  71. if (_PS_VERSION_ != '1.4.11.0')
  72. return true;
  73. if (!is_dir(dirname(__FILE__).'/../../override/classes/'))
  74. mkdir(dirname(__FILE__).'/../../override/classes/', 0777, true);
  75. if (file_exists(dirname(__FILE__).'/../../override/classes/Shop.php'))
  76. rename(dirname(__FILE__).'/../../override/classes/Shop.php', dirname(__FILE__).'/../../override/classes/Shop.origin.php');
  77. if (!copy(dirname(__FILE__).'/override14/classes/Shop.php', dirname(__FILE__).'/../../override/classes/Shop.php'))
  78. return false;
  79. return true;
  80. }
  81. /**
  82. * Google Sitemap uninstallation process:
  83. *
  84. * Step 1 - Remove Configuration option values from database
  85. * Step 2 - Remove the database containing the generated Sitemap files names
  86. * Step 3 - Uninstallation of the Addon itself
  87. *
  88. * @return boolean Uninstallation result
  89. */
  90. public function uninstall()
  91. {
  92. foreach (array(
  93. 'GSITEMAP_PRIORITY_HOME' => '',
  94. 'GSITEMAP_PRIORITY_PRODUCT' => '',
  95. 'GSITEMAP_PRIORITY_CATEGORY' => '',
  96. 'GSITEMAP_PRIORITY_MANUFACTURER' => '',
  97. 'GSITEMAP_PRIORITY_SUPPLIER' => '',
  98. 'GSITEMAP_PRIORITY_CMS' => '',
  99. 'GSITEMAP_FREQUENCY' => '',
  100. 'GSITEMAP_CHECK_IMAGE_FILE' => '',
  101. 'GSITEMAP_LAST_EXPORT' => ''
  102. ) as $key => $val)
  103. if (!Configuration::deleteByName($key))
  104. return false;
  105. return parent::uninstall() && $this->removeSitemap();
  106. }
  107. /**
  108. * Delete all the generated Sitemap files and drop the addon table.
  109. * @return boolean
  110. */
  111. public function removeSitemap()
  112. {
  113. $links = Db::getInstance()->ExecuteS('SELECT * FROM `'._DB_PREFIX_.'gsitemap_sitemap`');
  114. if ($links)
  115. foreach ($links as $link)
  116. if (!@unlink(dirname(__FILE__).'/../../'.$link['link']))
  117. return false;
  118. if (!Db::getInstance()->Execute('DROP TABLE `'._DB_PREFIX_.'gsitemap_sitemap`'))
  119. return false;
  120. return true;
  121. }
  122. public function getContent()
  123. {
  124. /* Store the posted parameters and generate a new Google Sitemap files for the current Shop */
  125. if (Tools::isSubmit('SubmitGsitemap'))
  126. {
  127. Configuration::updateValue('GSITEMAP_FREQUENCY', pSQL(Tools::getValue('gsitemap_frequency')));
  128. Configuration::updateValue('GSITEMAP_INDEX_CHECK', '');
  129. Configuration::updateValue('GSITEMAP_CHECK_IMAGE_FILE', pSQL(Tools::getValue('gsitemap_check_image_file')));
  130. $meta = '';
  131. if (Tools::getValue('gsitemap_meta'))
  132. $meta .= implode(', ', Tools::getValue('gsitemap_meta'));
  133. Configuration::updateValue('GSITEMAP_DISABLE_LINKS', $meta);
  134. $this->emptySitemap();
  135. $this->createSitemap();
  136. }
  137. /* if no posted form and the variable [continue] is found in the HTTP request variable keep creating sitemap */
  138. elseif (Tools::getValue('continue'))
  139. $this->createSitemap();
  140. /* Backward compatibility */
  141. if (_PS_VERSION_ < 1.5)
  142. require(_PS_MODULE_DIR_.'gsitemap/backward_compatibility/backward.php');
  143. /* Empty the Shop domain cache */
  144. if (method_exists('ShopUrl', 'resetMainDomainCache'))
  145. ShopUrl::resetMainDomainCache();
  146. $this->context->smarty->assign(
  147. array(
  148. 'gsitemap_form' => './index.php?tab=AdminModules&configure=gsitemap&token='.Tools::getAdminTokenLite('AdminModules').'&tab_module='.$this->tab.'&module_name=gsitemap',
  149. 'gsitemap_cron' => _PS_BASE_URL_._MODULE_DIR_.'gsitemap/gsitemap-cron.php?token='.substr(Tools::encrypt('gsitemap/cron'), 0, 10).'&id_shop='.$this->context->shop->id,
  150. 'gsitemap_feed_exists' => file_exists(dirname(__FILE__).'/../../index_sitemap.xml'),
  151. 'gsitemap_last_export' => Configuration::get('GSITEMAP_LAST_EXPORT'),
  152. 'gsitemap_frequency' => Configuration::get('GSITEMAP_FREQUENCY'),
  153. 'gsitemap_store_url' => 'http://'.Tools::getShopDomain(false, true).__PS_BASE_URI__,
  154. 'gsitemap_links' => Db::getInstance()->ExecuteS('SELECT * FROM `'._DB_PREFIX_.'gsitemap_sitemap` WHERE id_shop = '.(int)$this->context->shop->id),
  155. 'store_metas' => Meta::getMetasByIdLang((int)$this->context->cookie->id_lang),
  156. 'gsitemap_disable_metas' => explode(',', Configuration::get('GSITEMAP_DISABLE_LINKS')),
  157. 'gsitemap_customer_limit' => array(
  158. 'max_exec_time' => (int)ini_get('max_execution_time'),
  159. 'memory_limit' => intval(ini_get('memory_limit'))
  160. ),
  161. 'prestashop_version' => _PS_VERSION_ >= 1.5 ? '1.5' : '1.4',
  162. 'prestashop_ssl' => Configuration::get('PS_SSL_ENABLED'),
  163. 'gsitemap_check_image_file' => Configuration::get('GSITEMAP_CHECK_IMAGE_FILE'),
  164. 'shop' => $this->context->shop
  165. )
  166. );
  167. return $this->display(__FILE__, 'tpl/configuration.tpl');
  168. }
  169. /**
  170. * Delete all the generated Sitemap files from the files system and the database.
  171. *
  172. * @param int $id_shop
  173. *
  174. * @return bool
  175. */
  176. public function emptySitemap($id_shop = 0)
  177. {
  178. if (!isset($this->context))
  179. $this->context = new Context();
  180. if ($id_shop != 0)
  181. $this->context->shop = new Shop((int)$id_shop);
  182. $links = Db::getInstance()->ExecuteS('SELECT * FROM `'._DB_PREFIX_.'gsitemap_sitemap` WHERE id_shop = '.(int)$this->context->shop->id);
  183. if ($links)
  184. {
  185. foreach ($links as $link)
  186. @unlink(dirname(__FILE__).'/../../'.$link['link']);
  187. return Db::getInstance()->Execute('DELETE FROM `'._DB_PREFIX_.'gsitemap_sitemap` WHERE id_shop = '.(int)$this->context->shop->id);
  188. }
  189. return true;
  190. }
  191. /**
  192. * @param array $link_sitemap contain all the links for the Google Sitemap file to be generated
  193. * @param array $new_link contain the link elements
  194. * @param string $lang language of link to add
  195. * @param int $index index of the current Google Sitemap file
  196. * @param int $i count of elements added to sitemap main array
  197. * @param int $id_obj identifier of the object of the link to be added to the Gogle Sitemap file
  198. *
  199. * @return bool
  200. */
  201. public function _addLinkToSitemap(&$link_sitemap, $new_link, $lang, &$index, &$i, $id_obj)
  202. {
  203. if ($i <= 25000 && memory_get_usage() < 100000000)
  204. {
  205. $link_sitemap[] = $new_link;
  206. $i++;
  207. return true;
  208. }
  209. else
  210. {
  211. $this->_recursiveSitemapCreator($link_sitemap, $lang, $index);
  212. if ($index % 20 == 0 && !$this->cron)
  213. {
  214. $this->context->smarty->assign(
  215. array(
  216. 'gsitemap_number' => (int)$index,
  217. 'gsitemap_refresh_page' => './index.php?tab=AdminModules&configure=gsitemap&token='.Tools::getAdminTokenLite('AdminModules').'&tab_module='.$this->tab.'&module_name=gsitemap&continue=1&type='.$new_link['type'].'&lang='.$lang.'&index='.$index.'&id='.($id_obj + 1).'&id_shop='.$this->context->shop->id
  218. )
  219. );
  220. return false;
  221. }
  222. else if ($index % 20 == 0 && $this->cron)
  223. {
  224. header('Refresh: 5; url=http'.(Configuration::get('PS_SSL_ENABLED') ? 's' : '').'://'.Tools::getShopDomain(false, true).__PS_BASE_URI__.'modules/gsitemap/gsitemap-cron.php?continue=1&token='.substr(Tools::encrypt('gsitemap/cron'), 0, 10).'&type='.$new_link['type'].'&lang='.$lang.'&index='.$index.'&id='.($id_obj + 1).'&id_shop='.$this->context->shop->id);
  225. die();
  226. }
  227. else
  228. {
  229. if ($this->cron)
  230. header('location: http'.(Configuration::get('PS_SSL_ENABLED') ? 's' : '').'://'.Tools::getShopDomain(false, true).__PS_BASE_URI__.'modules/gsitemap/gsitemap-cron.php?continue=1&token='.substr(Tools::encrypt('gsitemap/cron'), 0, 10).'&type='.$new_link['type'].'&lang='.$lang.'&index='.$index.'&id='.($id_obj + 1).'&id_shop='.$this->context->shop->id);
  231. else
  232. {
  233. $admin_folder = str_replace(_PS_ROOT_DIR_, '', _PS_ADMIN_DIR_);
  234. $admin_folder = substr($admin_folder, 1);
  235. header('location: http'.(Configuration::get('PS_SSL_ENABLED') ? 's' : '').'://'.Tools::getShopDomain(false, true).__PS_BASE_URI__.$admin_folder.'/index.php?tab=AdminModules&configure=gsitemap&token='.Tools::getAdminTokenLite('AdminModules').'&tab_module='.$this->tab.'&module_name=gsitemap&continue=1&type='.$new_link['type'].'&lang='.$lang.'&index='.$index.'&id='.($id_obj + 1).'&id_shop='.$this->context->shop->id);
  236. }
  237. die();
  238. }
  239. }
  240. }
  241. /**
  242. * Hydrate $link_sitemap with home link
  243. *
  244. * @param array $link_sitemap contain all the links for the Google Sitemap file to be generated
  245. * @param string $lang language of link to add
  246. * @param int $index index of the current Google Sitemap file
  247. * @param int $i count of elements added to sitemap main array
  248. *
  249. * @return bool
  250. */
  251. private function _getHomeLink(&$link_sitemap, $lang, &$index, &$i)
  252. {
  253. return $this->_addLinkToSitemap(
  254. $link_sitemap, array(
  255. 'type' => 'home',
  256. 'page' => 'home',
  257. 'link' => Tools::getShopDomainSsl(true).$this->context->shop->getBaseURI().(method_exists('Language', 'isMultiLanguageActivated') ? Language::isMultiLanguageActivated() ? $lang['iso_code'].'/' : '' : ''),
  258. 'image' => false
  259. ), $lang['iso_code'], $index, $i, -1
  260. );
  261. }
  262. /**
  263. * Hydrate $link_sitemap with meta link
  264. *
  265. * @param array $link_sitemap contain all the links for the Google Sitemap file to be generated
  266. * @param string $lang language of link to add
  267. * @param int $index index of the current Google Sitemap file
  268. * @param int $i count of elements added to sitemap main array
  269. * @param int $id_meta meta object identifier
  270. *
  271. * @return bool
  272. */
  273. private function _getMetaLink(&$link_sitemap, $lang, &$index, &$i, $id_meta = 0)
  274. {
  275. if (method_exists('ShopUrl', 'resetMainDomainCache'))
  276. ShopUrl::resetMainDomainCache();
  277. $link = new Link();
  278. $metas = Db::getInstance()->ExecuteS('SELECT * FROM `'._DB_PREFIX_.'meta` WHERE `id_meta` > '.(int)$id_meta.' ORDER BY `id_meta` ASC');
  279. foreach ($metas as $meta)
  280. {
  281. $url = '';
  282. if (!in_array($meta['id_meta'], explode(',', Configuration::get('GSITEMAP_DISABLE_LINKS'))))
  283. {
  284. if (_PS_VERSION_ >= 1.5)
  285. {
  286. $url_rewrite = Db::getInstance()->getValue('SELECT url_rewrite, id_shop FROM `'._DB_PREFIX_.'meta_lang` WHERE `id_meta` = '.(int)$meta['id_meta'].' AND `id_shop` ='.(int)$this->context->shop->id.' AND `id_lang` = '.(int)$lang['id_lang']);
  287. Dispatcher::getInstance()->addRoute($meta['page'], (isset($url_rewrite) ? $url_rewrite : $meta['page']), $meta['page'], $lang['id_lang']);
  288. $uri_path = Dispatcher::getInstance()->createUrl($meta['page'], $lang['id_lang'], array(), (bool)Configuration::get('PS_REWRITING_SETTINGS'));
  289. $url .= Tools::getShopDomainSsl(true).(($this->context->shop->virtual_uri) ? __PS_BASE_URI__.$this->context->shop->virtual_uri : __PS_BASE_URI__).(Language::isMultiLanguageActivated() ? $lang['iso_code'].'/' : '').ltrim($uri_path, '/');
  290. }
  291. else
  292. $url = $link->getPageLink($meta['page'].'.php', true, $lang['id_lang']);
  293. if (!$this->_addLinkToSitemap(
  294. $link_sitemap, array(
  295. 'type' => 'meta',
  296. 'page' => $meta['page'],
  297. 'link' => $url,
  298. 'image' => false
  299. ), $lang['iso_code'], $index, $i, $meta['id_meta']
  300. )
  301. )
  302. return false;
  303. }
  304. }
  305. return true;
  306. }
  307. /**
  308. * Hydrate $link_sitemap with products link
  309. *
  310. * @param array $link_sitemap contain all the links for the Google Sitemap file to be generated
  311. * @param string $lang language of link to add
  312. * @param int $index index of the current Google Sitemap file
  313. * @param int $i count of elements added to sitemap main array
  314. * @param int $id_product product object identifier
  315. *
  316. * @return bool
  317. */
  318. private function _getProductLink(&$link_sitemap, $lang, &$index, &$i, $id_product = 0)
  319. {
  320. $link = new Link();
  321. if (method_exists('ShopUrl', 'resetMainDomainCache'))
  322. ShopUrl::resetMainDomainCache();
  323. $products_id = Db::getInstance()->ExecuteS('SELECT `id_product` FROM `'._DB_PREFIX_.'product_shop` WHERE `active` = 1 AND `id_shop`='.$this->context->shop->id);
  324. foreach ($products_id as $product_id)
  325. {
  326. $product = new Product((int)$product_id['id_product'], false, (int)$lang['id_lang']);
  327. if (_PS_VERSION_ >= 1.5)
  328. {
  329. $url = $link->getProductLink($product, $product->link_rewrite, htmlspecialchars(strip_tags($product->category)), $product->ean13, (int)$lang['id_lang'], (int)$this->context->shop->id, 0, true);
  330. }
  331. else
  332. {
  333. $category = new Category((int)$product->id_category_default, (int)$lang['id_lang']);
  334. $url = $link->getProductLink($product, Configuration::get('PS_REWRITING_SETTINGS') ? $product->link_rewrite : false, htmlspecialchars(strip_tags($category->name)), $product->ean13, (int)$lang['id_lang']);
  335. }
  336. $id_image = Product::getCover((int)$product_id['id_product']);
  337. if (isset($id_image['id_image']))
  338. {
  339. $image_link = $this->context->link->getImageLink($product->link_rewrite, $product->id.'-'.(int)$id_image['id_image']);
  340. $image_link = (!in_array(rtrim(Context::getContext()->shop->virtual_uri, '/'), explode('/', $image_link))) ? str_replace(
  341. array(
  342. 'https',
  343. Context::getContext()->shop->domain.Context::getContext()->shop->physical_uri
  344. ), array(
  345. 'http',
  346. Context::getContext()->shop->domain.Context::getContext()->shop->physical_uri.Context::getContext()->shop->virtual_uri
  347. ), $image_link
  348. ) : $image_link;
  349. }
  350. $file_headers = (Configuration::get('GSITEMAP_CHECK_IMAGE_FILE')) ? @get_headers($image_link) : true;
  351. $image_product = array();
  352. if (isset($image_link) && ($file_headers[0] != 'HTTP/1.1 404 Not Found' || $file_headers === true))
  353. $image_product = array(
  354. 'title_img' => htmlspecialchars(strip_tags($product->name)),
  355. 'caption' => htmlspecialchars(strip_tags($product->description_short)),
  356. 'link' => $image_link
  357. );
  358. if (!$this->_addLinkToSitemap(
  359. $link_sitemap, array(
  360. 'type' => 'product',
  361. 'page' => 'product',
  362. 'lastmod' => $product->date_upd,
  363. 'link' => $url,
  364. 'image' => $image_product
  365. ), $lang['iso_code'], $index, $i, $product_id['id_product']
  366. )
  367. )
  368. return false;
  369. unset($image_link);
  370. }
  371. return true;
  372. }
  373. /**
  374. * Hydrate $link_sitemap with categories link
  375. *
  376. * @param array $link_sitemap contain all the links for the Google Sitemap file to be generated
  377. * @param string $lang language of link to add
  378. * @param int $index index of the current Google Sitemap file
  379. * @param int $i count of elements added to sitemap main array
  380. * @param int $id_category category object identifier
  381. *
  382. * @return bool
  383. */
  384. private function _getCategoryLink(&$link_sitemap, $lang, &$index, &$i, $id_category = 0)
  385. {
  386. $link = new Link();
  387. if (method_exists('ShopUrl', 'resetMainDomainCache'))
  388. ShopUrl::resetMainDomainCache();
  389. $categories_id = Db::getInstance()->ExecuteS(
  390. 'SELECT c.id_category FROM `'._DB_PREFIX_.'category` c
  391. INNER JOIN `'._DB_PREFIX_.'category_shop` cs ON c.`id_category` = cs.`id_category`
  392. WHERE c.`active` = 1 AND c.`id_category` != 1 AND c.id_parent > 0 AND c.`id_category` > 0 AND cs.`id_shop` = '.(int)$this->context->shop->id.' ORDER BY c.`id_category` ASC'
  393. );
  394. foreach ($categories_id as $category_id)
  395. {
  396. $category = new Category((int)$category_id['id_category'], (int)$lang['id_lang']);
  397. $url = $link->getCategoryLink($category, urlencode($category->link_rewrite), (int)$lang['id_lang']);
  398. if ($category->id_image)
  399. {
  400. $image_link = $this->context->link->getCatImageLink($category->link_rewrite, (int)$category->id_image, 'category_default');
  401. $image_link = (!in_array(rtrim(Context::getContext()->shop->virtual_uri, '/'), explode('/', $image_link))) ? str_replace(
  402. array(
  403. 'https',
  404. Context::getContext()->shop->domain.Context::getContext()->shop->physical_uri
  405. ), array(
  406. 'http',
  407. Context::getContext()->shop->domain.Context::getContext()->shop->physical_uri.Context::getContext()->shop->virtual_uri
  408. ), $image_link
  409. ) : $image_link;
  410. }
  411. $file_headers = (Configuration::get('GSITEMAP_CHECK_IMAGE_FILE')) ? @get_headers($image_link) : true;
  412. $image_category = array();
  413. if (isset($image_link) && ($file_headers[0] != 'HTTP/1.1 404 Not Found' || $file_headers === true))
  414. $image_category = array(
  415. 'title_img' => htmlspecialchars(strip_tags($category->name)),
  416. 'link' => $image_link
  417. );
  418. if (!$this->_addLinkToSitemap(
  419. $link_sitemap, array(
  420. 'type' => 'category',
  421. 'page' => 'category',
  422. 'lastmod' => $category->date_upd,
  423. 'link' => $url,
  424. 'image' => $image_category
  425. ), $lang['iso_code'], $index, $i, (int)$category_id['id_category']
  426. )
  427. )
  428. return false;
  429. unset($image_link);
  430. }
  431. return true;
  432. }
  433. /**
  434. * return the link elements for the manufacturer object
  435. *
  436. * @param array $link_sitemap contain all the links for the Google Sitemap file to be generated
  437. * @param string $lang language of link to add
  438. * @param int $index index of the current Google Sitemap file
  439. * @param int $i count of elements added to sitemap main array
  440. * @param int $id_manufacturer manufacturer object identifier
  441. *
  442. * @return bool
  443. */
  444. private function _getManufacturerLink(&$link_sitemap, $lang, &$index, &$i, $id_manufacturer = 0)
  445. {
  446. $link = new Link();
  447. if (method_exists('ShopUrl', 'resetMainDomainCache'))
  448. ShopUrl::resetMainDomainCache();
  449. $manufacturers_id = Db::getInstance()->ExecuteS(
  450. 'SELECT m.`id_manufacturer` FROM `'._DB_PREFIX_.'manufacturer` m
  451. INNER JOIN `'._DB_PREFIX_.'manufacturer_lang` ml on m.`id_manufacturer` = ml.`id_manufacturer`'.
  452. ($this->tableColumnExists(_DB_PREFIX_.'manufacturer_shop') ? ' INNER JOIN `'._DB_PREFIX_.'manufacturer_shop` ms ON m.`id_manufacturer` = ms.`id_manufacturer` ' : '').
  453. ' WHERE m.`active` = 1 AND m.`id_manufacturer` > '.(int)$id_manufacturer.
  454. ($this->tableColumnExists(_DB_PREFIX_.'manufacturer_shop') ? ' AND ms.`id_shop` = '.(int)$this->context->shop->id : '').
  455. ' AND ml.`id_lang` = '.(int)$lang['id_lang'].
  456. ' ORDER BY m.`id_manufacturer` ASC'
  457. );
  458. foreach ($manufacturers_id as $manufacturer_id)
  459. {
  460. $manufacturer = new Manufacturer((int)$manufacturer_id['id_manufacturer'], $lang['id_lang']);
  461. $url = $link->getManufacturerLink($manufacturer, $manufacturer->link_rewrite, $lang['id_lang']);
  462. $image_link = 'http://'.Tools::getMediaServer(_THEME_MANU_DIR_)._THEME_MANU_DIR_.((!file_exists(_PS_MANU_IMG_DIR_.'/'.(int)$manufacturer->id.'-medium_default.jpg')) ? $lang['iso_code'].'-default' : (int)$manufacturer->id).'-medium_default.jpg';
  463. $image_link = (!in_array(rtrim(Context::getContext()->shop->virtual_uri, '/'), explode('/', $image_link))) ? str_replace(
  464. array(
  465. 'https',
  466. Context::getContext()->shop->domain.Context::getContext()->shop->physical_uri
  467. ), array(
  468. 'http',
  469. Context::getContext()->shop->domain.Context::getContext()->shop->physical_uri.Context::getContext()->shop->virtual_uri
  470. ), $image_link
  471. ) : $image_link;
  472. $file_headers = (Configuration::get('GSITEMAP_CHECK_IMAGE_FILE')) ? @get_headers($image_link) : true;
  473. $manifacturer_image = array();
  474. if ($file_headers[0] != 'HTTP/1.1 404 Not Found' || $file_headers === true)
  475. $manifacturer_image = array(
  476. 'title_img' => htmlspecialchars(strip_tags($manufacturer->name)),
  477. 'caption' => htmlspecialchars(strip_tags($manufacturer->short_description)),
  478. 'link' => $image_link
  479. );
  480. if (!$this->_addLinkToSitemap(
  481. $link_sitemap, array(
  482. 'type' => 'manufacturer',
  483. 'page' => 'manufacturer',
  484. 'lastmod' => $manufacturer->date_upd,
  485. 'link' => $url,
  486. 'image' => $manifacturer_image
  487. ), $lang['iso_code'], $index, $i, $manufacturer_id['id_manufacturer']
  488. )
  489. )
  490. return false;;
  491. }
  492. return true;
  493. }
  494. /**
  495. * @param array $link_sitemap contain all the links for the Google Sitemap file to be generated
  496. * @param string $lang language of link to add
  497. * @param int $index index of the current Google Sitemap file
  498. * @param int $i count of elements added to sitemap main array
  499. * @param int $id_supplier supplier object identifier
  500. *
  501. * @return bool
  502. */
  503. private function _getSupplierLink(&$link_sitemap, $lang, &$index, &$i, $id_supplier = 0)
  504. {
  505. $link = new Link();
  506. if (method_exists('ShopUrl', 'resetMainDomainCache'))
  507. ShopUrl::resetMainDomainCache();
  508. $suppliers_id = Db::getInstance()->ExecuteS(
  509. 'SELECT s.`id_supplier` FROM `'._DB_PREFIX_.'supplier` s
  510. INNER JOIN `'._DB_PREFIX_.'supplier_lang` sl ON s.`id_supplier` = sl.`id_supplier` '.
  511. ($this->tableColumnExists(_DB_PREFIX_.'supplier_shop') ? 'INNER JOIN `'._DB_PREFIX_.'supplier_shop` ss ON s.`id_supplier` = ss.`id_supplier`' : '').'
  512. WHERE s.`active` = 1 AND s.`id_supplier` > '.(int)$id_supplier.
  513. ($this->tableColumnExists(_DB_PREFIX_.'supplier_shop') ? ' AND ss.`id_shop` = '.(int)$this->context->shop->id : '').'
  514. AND sl.`id_lang` = '.(int)$lang['id_lang'].'
  515. ORDER BY s.`id_supplier` ASC'
  516. );
  517. foreach ($suppliers_id as $supplier_id)
  518. {
  519. $supplier = new Supplier((int)$supplier_id['id_supplier'], $lang['id_lang']);
  520. $url = $link->getSupplierLink($supplier, $supplier->link_rewrite, $lang['id_lang']);
  521. $image_link = 'http://'.Tools::getMediaServer(_THEME_SUP_DIR_)._THEME_SUP_DIR_.((!file_exists(_THEME_SUP_DIR_.'/'.(int)$supplier->id.'-medium_default.jpg')) ? $lang['iso_code'].'-default' : (int)$supplier->id).'-medium_default.jpg';
  522. $image_link = (!in_array(rtrim(Context::getContext()->shop->virtual_uri, '/'), explode('/', $image_link))) ? str_replace(
  523. array(
  524. 'https',
  525. Context::getContext()->shop->domain.Context::getContext()->shop->physical_uri
  526. ), array(
  527. 'http',
  528. Context::getContext()->shop->domain.Context::getContext()->shop->physical_uri.Context::getContext()->shop->virtual_uri
  529. ), $image_link
  530. ) : $image_link;
  531. $file_headers = (Configuration::get('GSITEMAP_CHECK_IMAGE_FILE')) ? @get_headers($image_link) : true;
  532. $supplier_image = array();
  533. if ($file_headers[0] != 'HTTP/1.1 404 Not Found' || $file_headers === true)
  534. $supplier_image = array(
  535. 'title_img' => htmlspecialchars(strip_tags($supplier->name)),
  536. 'link' => 'http'.(Configuration::get('PS_SSL_ENABLED') ? 's' : '').'://'.Tools::getMediaServer(_THEME_SUP_DIR_)._THEME_SUP_DIR_.((!file_exists(_THEME_SUP_DIR_.'/'.(int)$supplier->id.'-medium_default.jpg')) ? $lang['iso_code'].'-default' : (int)$supplier->id).'-medium_default.jpg'
  537. );
  538. if (!$this->_addLinkToSitemap(
  539. $link_sitemap, array(
  540. 'type' => 'supplier',
  541. 'page' => 'supplier',
  542. 'lastmod' => $supplier->date_upd,
  543. 'link' => $url,
  544. 'image' => $supplier_image
  545. ), $lang['iso_code'], $index, $i, $supplier_id['id_supplier']
  546. )
  547. )
  548. return false;
  549. }
  550. return true;
  551. }
  552. /**
  553. * return the link elements for the CMS object
  554. *
  555. * @param array $link_sitemap contain all the links for the Google Sitemap file to be generated
  556. * @param string $lang the language of link to add
  557. * @param int $index the index of the current Google Sitemap file
  558. * @param int $i the count of elements added to sitemap main array
  559. * @param int $id_cms the CMS object identifier
  560. *
  561. * @return bool
  562. */
  563. private function _getCmsLink(&$link_sitemap, $lang, &$index, &$i, $id_cms = 0)
  564. {
  565. $link = new Link();
  566. if (method_exists('ShopUrl', 'resetMainDomainCache'))
  567. ShopUrl::resetMainDomainCache();
  568. $cmss_id = Db::getInstance()->ExecuteS(
  569. 'SELECT c.`id_cms` FROM `'._DB_PREFIX_.'cms` c INNER JOIN `'._DB_PREFIX_.'cms_lang` cl ON c.`id_cms` = cl.`id_cms` '.
  570. ($this->tableColumnExists(_DB_PREFIX_.'supplier_shop') ? 'INNER JOIN `'._DB_PREFIX_.'cms_shop` cs ON c.`id_cms` = cs.`id_cms` ' : '').
  571. 'INNER JOIN `'._DB_PREFIX_.'cms_category` cc ON c.id_cms_category = cc.id_cms_category AND cc.active = 1
  572. WHERE c.`active` =1 AND c.`id_cms` > '.(int)$id_cms.
  573. ($this->tableColumnExists(_DB_PREFIX_.'supplier_shop') ? ' AND cs.id_shop = '.(int)$this->context->shop->id : '').
  574. ' AND cl.`id_lang` = '.(int)$lang['id_lang'].
  575. ' ORDER BY c.`id_cms` ASC'
  576. );
  577. foreach ($cmss_id as $cms_id)
  578. {
  579. $cms = new CMS((int)$cms_id['id_cms'], $lang['id_lang']);
  580. $cms->link_rewrite = urlencode((is_array($cms->link_rewrite) ? $cms->link_rewrite[(int)$lang['id_lang']] : $cms->link_rewrite));
  581. $url = $link->getCMSLink($cms, null, null, $lang['id_lang']);
  582. if (!$this->_addLinkToSitemap(
  583. $link_sitemap, array(
  584. 'type' => 'cms',
  585. 'page' => 'cms',
  586. 'link' => $url,
  587. 'image' => false
  588. ), $lang['iso_code'], $index, $i, $cms_id['id_cms']
  589. )
  590. )
  591. return false;
  592. }
  593. return true;
  594. }
  595. /**
  596. * Create the Google Sitemap by Shop
  597. *
  598. * @param int $id_shop Shop identifier
  599. *
  600. * @return bool
  601. */
  602. public function createSitemap($id_shop = 0)
  603. {
  604. if (@fopen(dirname(__FILE__).'/../../test.txt', 'w') == false)
  605. {
  606. $this->context->smarty->assign('google_maps_error', $this->l('An error occured while trying to check your file permissions. Please adjust your permissions to allow PrestaShop to write a file in your root directory.'));
  607. return false;
  608. }
  609. else
  610. @unlink(dirname(__FILE__).'/../../test.txt');
  611. if ($id_shop != 0)
  612. $this->context->shop = new Shop((int)$id_shop);
  613. /* Backward compatibility */
  614. if (_PS_VERSION_ < 1.5)
  615. require(_PS_MODULE_DIR_.'gsitemap/backward_compatibility/backward.php');
  616. $type = Tools::getValue('type') ? Tools::getValue('type') : '';
  617. $languages = Language::getLanguages();
  618. $lang_stop = Tools::getValue('lang') ? true : false;
  619. $id_obj = Tools::getValue('id') ? (int)Tools::getValue('id') : 0;
  620. $type_array = array('home', 'meta', 'product', 'category', 'manufacturer', 'supplier', 'cms');
  621. //$type_array = array('product', 'manufacturer', 'supplier', 'cms');
  622. foreach ($languages as $lang)
  623. {
  624. $i = 0;
  625. $index = (Tools::getValue('index') && Tools::getValue('lang') == $lang['iso_code']) ? (int)Tools::getValue('index') : 0;
  626. if ($lang_stop && $lang['iso_code'] != Tools::getValue('lang'))
  627. continue;
  628. elseif ($lang_stop && $lang['iso_code'] == Tools::getValue('lang'))
  629. $lang_stop = false;
  630. $link_sitemap = array();
  631. foreach ($type_array as $type_val)
  632. {
  633. if ($type == '' || $type == $type_val)
  634. {
  635. $function = '_get'.ucfirst($type_val).'Link';
  636. if (!$this->$function($link_sitemap, $lang, $index, $i, $id_obj))
  637. return false;
  638. $type = '';
  639. $id_obj = 0;
  640. }
  641. }
  642. $this->_recursiveSitemapCreator($link_sitemap, $lang['iso_code'], $index);
  643. $page = '';
  644. $index = 0;
  645. }
  646. $this->_createIndexSitemap();
  647. Configuration::updateValue('GSITEMAP_LAST_EXPORT', date('r'));
  648. Tools::file_get_contents('http://www.google.com/webmasters/sitemaps/ping?sitemap='.urlencode('http'.(Configuration::get('PS_SSL_ENABLED') ? 's' : '').'://'.Tools::getShopDomain(false, true).$this->context->shop->physical_uri.$this->context->shop->virtual_uri.$this->context->shop->id.'_index_sitemap.xml'));
  649. if ($this->cron)
  650. die();
  651. header('location: ./index.php?tab=AdminModules&configure=gsitemap&token='.Tools::getAdminTokenLite('AdminModules').'&tab_module='.$this->tab.'&module_name=gsitemap&validation');
  652. die();
  653. }
  654. /**
  655. * Store the generated Sitemap file to the database
  656. *
  657. * @param string $sitemap the name of the generated Google Sitemap file
  658. *
  659. * @return bool
  660. */
  661. private function _saveSitemapLink($sitemap)
  662. {
  663. if ($sitemap)
  664. return Db::getInstance()->Execute('INSERT INTO `'._DB_PREFIX_.'gsitemap_sitemap` (`link`, id_shop) VALUES (\''.pSQL($sitemap).'\', '.(int)$this->context->shop->id.')');
  665. return false;
  666. }
  667. /**
  668. * @param array $link_sitemap contain all the links for the Google Sitemap file to be generated
  669. * @param string $lang the language of link to add
  670. * @param int $index the index of the current Google Sitemap file
  671. *
  672. * @return bool
  673. */
  674. private function _recursiveSitemapCreator($link_sitemap, $lang, &$index)
  675. {
  676. if (!count($link_sitemap))
  677. return false;
  678. $sitemap_link = $this->context->shop->id.'_'.$lang.'_'.$index.'_sitemap.xml';
  679. $write_fd = fopen(dirname(__FILE__).'/../../'.$sitemap_link, 'w');
  680. fwrite($write_fd, '<?xml version="1.0" encoding="UTF-8"?>'."\r\n".'<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">'."\r\n");
  681. foreach ($link_sitemap as $key => $file)
  682. {
  683. fwrite($write_fd, '<url>'."\r\n");
  684. $lastmod = (isset($file['lastmod']) && !empty($file['lastmod'])) ? date('c', strtotime($file['lastmod'])) : null;
  685. $this->_addSitemapNode($write_fd, htmlspecialchars(strip_tags($file['link'])), $this->_getPriorityPage($file['page']), Configuration::get('GSITEMAP_FREQUENCY'), $lastmod);
  686. if ($file['image'])
  687. {
  688. $this->_addSitemapNodeImage(
  689. $write_fd, htmlspecialchars(strip_tags($file['image']['link'])), isset($file['image']['title_img']) ? htmlspecialchars(
  690. str_replace(
  691. array(
  692. "\r\n",
  693. "\r",
  694. "\n"
  695. ), '', strip_tags($file['image']['title_img'])
  696. )
  697. ) : '', isset($file['image']['caption']) ? htmlspecialchars(
  698. str_replace(
  699. array(
  700. "\r\n",
  701. "\r",
  702. "\n"
  703. ), '', strip_tags($file['image']['caption'])
  704. )
  705. ) : ''
  706. );
  707. }
  708. fwrite($write_fd, '</url>'."\r\n");
  709. }
  710. fwrite($write_fd, '</urlset>'."\r\n");
  711. fclose($write_fd);
  712. $this->_saveSitemapLink($sitemap_link);
  713. $index++;
  714. return true;
  715. }
  716. /**
  717. * return the priority value set in the configuration parameters
  718. *
  719. * @param string $page
  720. *
  721. * @return float|string|bool
  722. */
  723. private function _getPriorityPage($page)
  724. {
  725. return Configuration::get('GSITEMAP_PRIORITY_'.Tools::strtoupper($page)) ? Configuration::get('GSITEMAP_PRIORITY_'.Tools::strtoupper($page)) : 0.1;
  726. }
  727. /**
  728. * Add a new line to the sitemap file
  729. *
  730. * @param resource $fd file system object resource
  731. * @param string $loc string the URL of the object page
  732. * @param string $priority
  733. * @param string $change_freq
  734. * @param int $last_mod the last modification date/time as a timestamp
  735. */
  736. private function _addSitemapNode($fd, $loc, $priority, $change_freq, $last_mod = null)
  737. {
  738. fwrite($fd, '<loc>'.(Configuration::get('PS_REWRITING_SETTINGS') ? '<![CDATA['.$loc.']]>' : $loc).'</loc>'."\r\n".'<priority>'."\r\n".number_format($priority, 1, '.', '').'</priority>'."\r\n".($last_mod ? '<lastmod>'.date('c', strtotime($last_mod)).'</lastmod>' : '')."\r\n".'<changefreq>'.$change_freq.'</changefreq>'."\r\n");
  739. }
  740. private function _addSitemapNodeImage($fd, $link, $title, $caption)
  741. {
  742. fwrite($fd, '<image:image>'."\r\n".'<image:loc>'.(Configuration::get('PS_REWRITING_SETTINGS') ? '<![CDATA['.$link.']]>' : $link).'</image:loc>'."\r\n".'<image:caption><![CDATA['.$caption.']]></image:caption>'."\r\n".'<image:title><![CDATA['.$title.']]></image:title>'."\r\n".'</image:image>'."\r\n");
  743. }
  744. /**
  745. * Create the index file for all generated sitemaps
  746. * @return boolean
  747. */
  748. private function _createIndexSitemap()
  749. {
  750. $sitemaps = Db::getInstance()->ExecuteS('SELECT `link` FROM `'._DB_PREFIX_.'gsitemap_sitemap` WHERE id_shop = '.$this->context->shop->id);
  751. if (!$sitemaps)
  752. return false;
  753. $xml = '<?xml version="1.0" encoding="UTF-8"?><sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9"></sitemapindex>';
  754. $xml_feed = new SimpleXMLElement($xml);
  755. foreach ($sitemaps as $link)
  756. {
  757. $sitemap = $xml_feed->addChild('sitemap');
  758. $sitemap->addChild('loc', 'http://'.Tools::getShopDomain(false, true).__PS_BASE_URI__.$link['link']);
  759. $sitemap->addChild('lastmod', date('c'));
  760. }
  761. file_put_contents(dirname(__FILE__).'/../../'.$this->context->shop->id.'_index_sitemap.xml', $xml_feed->asXML());
  762. return true;
  763. }
  764. private function tableColumnExists($table_name, $column = null)
  765. {
  766. if (array_key_exists($table_name, $this->sql_checks))
  767. if (!empty($column) && array_key_exists($column, $this->sql_checks[$table_name]))
  768. return $this->sql_checks[$table_name][$column];
  769. else
  770. return $this->sql_checks[$table_name];
  771. $table = Db::getInstance()->ExecuteS('SHOW TABLES LIKE \''.$table_name.'\'');
  772. if (empty($column))
  773. if (count($table) < 1)
  774. return $this->sql_checks[$table_name] = false;
  775. else
  776. $this->sql_checks[$table_name] = true;
  777. else
  778. {
  779. $table = Db::getInstance()->ExecuteS('SELECT * FROM `'.$table_name.'` LIMIT 1');
  780. return $this->sql_checks[$table_name][$column] = array_key_exists($column, current($table));
  781. }
  782. return true;
  783. }
  784. }