*/ /** * Klasa stSitemapGenerator * * @package stPositioningPlugin * @subpackage libs * @author Piotr Halas */ class stSitemapGenerator { /** * Pozycja początku linków dla produkty * @var integer */ protected $productStart = 0; /** * Pozycja początku linków dla grup produktów * @var integer */ protected $productGroupStart = 0; /** * Pozycja początku linków dla stron www * @var integer */ protected $webpageStart = 0; /** * Pozycja początku linków dla bloga * @var integer */ protected $blogStart = 0; /** * Pozycja początku linków dla kategorii * @var integer */ protected $categoryStart = 0; /** * Wiadomosc dla progressBara * @var string */ protected $msg = ''; /** * tablica linków do zapisania * @var array */ protected $writeData = array(); /** * limit linków dla jednego pliku xml * @var integer */ protected $linksPerPage = 1000; /** * Uchwyt pliku do zapisu * @var object */ protected $fileHandle = false; /** * Dostępne języki dla tworzenia linków * @var array */ protected $langs = array(); /** * Konfiguracja modulu pozycjonowania * @var object */ protected $config = null; /** * Adres sklepu * @var string */ protected $host = ''; /** * Domyslny jezyk * @var string */ protected $defalutLang = ''; protected $lang = 'pl_PL'; protected $culture = 'pl_PL'; /** * Konstruktor klasy * @return null */ public function __construct() { sfLoader::loadHelpers('Helper'); sfLoader::loadHelpers('Tag'); sfLoader::loadHelpers('stUrl'); $this->caclualteItems(); $context = sfContext::getInstance(); $this->config = stConfig::getInstance($context,null,'stPositioningBackend'); $this->config->load(); $context->getRequest()->setScriptNameByApp('frontend'); $this->addRouting(); } /** * Destruktor klasy */ public function __destruct() { $context = sfContext::getInstance(); $context->getRequest()->setScriptNameByApp(null); } protected function addRouting() { stPluginHelper::addRouting('stBackendProductUrlLang', '/:lang/:url.html', 'stProduct', 'show', 'backend', array(), array('lang' => '[a-z]{2,4}')); stPluginHelper::addRouting('stBackendProductUrl', '/:url.html', 'stProduct', 'show', 'backend'); stPluginHelper::addRouting('stBackendProductCategoryUrlLang3', '/category/:lang/:url', 'stProduct', 'list', 'backend', array(), array('lang' => '[a-z]{2,4}')); stPluginHelper::addRouting('stBackendProductCategoryUrl3', '/category/:url', 'stProduct', 'list', 'backend'); stPluginHelper::addRouting('stBackendWebpageUrlLang', '/webpage/:lang/:url.html', 'stWebpageFrontend', 'index', 'backend'); stPluginHelper::addRouting('stBackendWebpageUrl', '/webpage/:url.html', 'stWebpageFrontend', 'index', 'backend'); stPluginHelper::addRouting('stBackendBlogUrlLang', '/blog/:lang/:url', 'stBlogFrontend', 'index', 'backend'); stPluginHelper::addRouting('stBackendBlogUrl', '/blog/:url', 'stBlogFrontend', 'index', 'backend'); stPluginHelper::addRouting('stBackendProductGroupUrlLang4', '/group/:lang/:url', 'stProduct', 'groupList', 'backend', array(), array('lang' => '[a-z]{2,4}')); stPluginHelper::addRouting('stBackendProductGroupUrl4', '/group/:url', 'stProduct', 'groupList', 'backend'); } /** * Funkja progressBara * * @param $step integer */ public function step($step, $lang = null) { $this->initLangs($lang); $this->openFile($step); $prevStep = $step; $old_conf = sfConfig::get('sf_no_script_name'); sfConfig::set('sf_no_script_name',1); if ($step<$this->productGroupStart) { $step += $this->processCategory($step); } elseif ($step<$this->webpageStart) { $step += $this->processProductGroup($step-$this->productGroupStart); } elseif ($step<$this->blogStart) { $step += $this->processWebpage($step-$this->webpageStart); } elseif ($step<$this->productStart) { $step += $this->processBlog($step-$this->blogStart); } else { $step += $this->processProduct($step-$this->productStart); } $this->writeDatatoFile($prevStep); $this->closeFile(); sfConfig::set('sf_no_script_name',$old_conf); return $step; } protected function initLangs($lang) { $this->langs = array('pl'=>'pl_PL'); $this->host = sfContext::getInstance()->getRequest()->getHost(); $this->defalutLang = $shortcut = 'pl'; $this->culture = 'pl_PL'; $c = new Criteria(); $c->add(LanguagePeer::LANGUAGE, $lang); $langO = LanguagePeer::doSelectOne($c); if (is_object($langO)) { $this->langs = array($langO->getShortcut()=>$langO->getOriginalLanguage()); $this->culture = $langO->getOriginalLanguage(); $shortcut = $langO->getShortcut(); } $domains = LanguageHasDomainPeer::doSelectByLanguageShortcut($shortcut); foreach ($domains as $domain) { if ($domain->getIsDefault()) { $this->host = $domain->getDomain(); $this->defalutLang = $shortcut; } } $this->lang = $shortcut; } /** * Oblicza liczbe poszczegolnych elemento mapy strony * */ protected function caclualteItems() { $categoryCount = CategoryPeer::doCount(new Criteria()); $c = new Criteria(); $c->add(ProductGroupPeer::OPT_NAME,null, Criteria::ISNOTNULL); $productGroupCount = ProductGroupPeer::doCount($c); $c = new Criteria(); $c->add(WebpagePeer::ACTIVE, 1); $c->add(WebpagePeer::OPT_CONTENT, null, Criteria::ISNOTNULL); $webpageCount = WebpagePeer::doCount($c); $c = new Criteria(); $c->add(BlogPeer::ACTIVE, 1); $blogCount = BlogPeer::doCount($c); $config = stConfig::getInstance('stProduct'); $c->add(ProductPeer::ACTIVE,1); if ($config->get('show_without_price')) { $c->add(ProductPeer::PRICE,0,Criteria::GREATER_THAN); } stEventDispatcher::getInstance()->notify(new sfEvent($this, 'stProductActions.postAddProductCriteria', array('criteria' => $c))); $ProductCount = ProductPeer::doCount($c); $this->productGroupStart = $categoryCount; $this->webpageStart = $this->productGroupStart + $productGroupCount; $this->blogStart = $this->webpageStart + $webpageCount; $this->productStart = $this->blogStart + $blogCount; } /** * Generuje linki dla kategorii * @param $step integer */ protected function processCategory($step) { $i18n = sfContext::getInstance()->getI18N(); $c = new Criteria(); $c->setLimit(20); $c->setOffset($step); $categeories = CategoryPeer::doSelect($c); $config = stConfig::getInstance(sfContext::getInstance(), array( 'show_without_price' => stConfig::BOOL),'stProduct' ); $config->load(); $c = new Criteria(); $c->add(ProductPeer::ACTIVE,1); if ($config->get('show_without_price')) { $c->add(ProductPeer::PRICE,0,Criteria::GREATER_THAN); } stEventDispatcher::getInstance()->notify(new sfEvent($this, 'stProductActions.postAddProductCriteria', array('criteria' => $c))); $c->addJoin(ProductPeer::ID, ProductHasCategoryPeer::PRODUCT_ID); $c->addJoin(ProductHasCategoryPeer::CATEGORY_ID, CategoryPeer::ID); foreach ($categeories as $category) { $c->add(CategoryPeer::LFT, $category->getLft(), Criteria::GREATER_EQUAL); $c->add(CategoryPeer::RGT, $category->getRgt(), Criteria::LESS_EQUAL); if (ProductPeer::doCount($c) == 0) {$this->writeData[]=''; continue;} if ($category->getIsActive() == 1) { foreach ($this->langs as $key=>$value) { $category->setCulture($value); try {$friendyurl = $category->getFriendlyUrl();} catch (Exception $e) {$friendyurl = "";} if (!empty($friendyurl)) { $this->writeData[] = $this->generateSitemapLink(st_url_for("stProduct/list?url=".$category->getFriendlyUrl(),true, 'frontend', $this->host, $key), $category->getUpdatedAt(DATE_ATOM), 0.8); } else { $this->writeData[] = $this->generateSitemapLink(st_url_for('stProduct/list?id_category='.$category->getId()."&lang=".$key,true, 'frontend', $this->host, $key), $category->getUpdatedAt(DATE_ATOM), 0.8); } } }else{ {$this->writeData[]=''; continue;} } } $this->msg = $i18n->__('Generuje mape witryny dla kategorii', array(), 'stPositioningBackend'); return count($categeories); } /** * Generuje linki dla grup produktów * @param $step integer */ protected function processProductGroup($step) { $i18n = sfContext::getInstance()->getI18N(); $c = new Criteria(); $c->setLimit(20); $c->setOffset($step); $c->add(ProductGroupPeer::OPT_NAME,null, Criteria::ISNOTNULL); $productGroups = ProductGroupPeer::doSelect($c); foreach ($productGroups as $productGroup) { foreach ($this->langs as $key=>$value) { try {$friendyurl = $productGroup->getFriendlyUrl();} catch (Exception $e) {$friendyurl = "";} $productGroup->setCulture($value); if (!empty($friendyurl)) { $this->writeData[] = $this->generateSitemapLink(st_url_for("stProduct/groupList?url=".$productGroup->getFriendlyUrl(),true, 'frontend', $this->host, $key), $productGroup->getUpdatedAt(DATE_ATOM), 0.5); } else { $this->writeData[] = $this->generateSitemapLink(st_url_for('stProduct/list?group_id='.$productGroup->getId()."&lang=".$key,true, 'frontend', $this->host, $key), $productGroup->getUpdatedAt(DATE_ATOM), 0.5); } } } $this->msg = $i18n->__('Generuje mape witryny dla grup produktów', array(), 'stPositioningBackend'); return count($productGroups); } /** * Generuje linki dla stron www * @param $step integer */ protected function processWebpage($step) { $i18n = sfContext::getInstance()->getI18N(); $c = new Criteria(); $c->setLimit(20); $c->setOffset($step); $c->add(WebpagePeer::ACTIVE, 1); $c->add(WebpagePeer::OPT_CONTENT, null, Criteria::ISNOTNULL); $webpages = WebpagePeer::doSelect($c); foreach ($webpages as $webpage) { foreach ($this->langs as $key=>$value) { $webpage->setCulture($value); try {$friendyurl = $webpage->getFriendlyUrl();} catch (Exception $e) {$friendyurl = "";} if (!empty($friendyurl)) { $this->writeData[] = $this->generateSitemapLink(st_url_for("stWebpageFrontend/index?url=".$webpage->getFriendlyUrl(),true, 'frontend', $this->host, $key), $webpage->getUpdatedAt(DATE_ATOM), 0.8); } else { $this->writeData[] = $this->generateSitemapLink(st_url_for('stWebpageFrontend/index?webpage_id='.$webpage->getId()."&lang=".$key,true, 'frontend', $this->host, $key), $webpage->getUpdatedAt(DATE_ATOM), 0.8); } } } $this->msg = $i18n->__('Generuje mape witryny dla stron www', array(), 'stPositioningBackend'); return count($webpages); } /** * Generuje linki dla bloga * @param $step integer */ protected function processBlog($step) { $i18n = sfContext::getInstance()->getI18N(); $c = new Criteria(); $c->setLimit(20); $c->setOffset($step); $c->add(BlogPeer::ACTIVE, 1); $blogs = BlogPeer::doSelect($c); foreach ($blogs as $blog) { foreach ($this->langs as $key=>$value) { $blog->setCulture($value); try {$friendyurl = $blog->getFriendlyUrl();} catch (Exception $e) {$friendyurl = "";} if (!empty($friendyurl)) { $this->writeData[] = $this->generateSitemapLink(st_url_for("stBlogFrontend/index?url=".$blog->getFriendlyUrl(),true, 'frontend', $this->host, $key), $blog->getUpdatedAt(DATE_ATOM), 0.8); } else { $this->writeData[] = $this->generateSitemapLink(st_url_for('stBlogFrontend/index?blog_id='.$blog->getId()."&lang=".$key,true, 'frontend', $this->host, $key), $blog->getUpdatedAt(DATE_ATOM), 0.8); } } } $this->msg = $i18n->__('Generuje mape witryny dla bloga', array(), 'stPositioningBackend'); return count($blogs); } /** * Generuje linki dla produktów * @param $step integer */ protected function processProduct($step) { $i18n = sfContext::getInstance()->getI18N(); $c = new Criteria(); $c->setLimit(20); $c->setOffset($step); $config = stConfig::getInstance('stProduct'); $c->add(ProductPeer::ACTIVE,1); if ($config->get('show_without_price')) { $c->add(ProductPeer::PRICE,0,Criteria::GREATER_THAN); } stEventDispatcher::getInstance()->notify(new sfEvent($this, 'stProductActions.postAddProductCriteria', array('criteria' => $c))); $products = ProductPeer::doSelect($c); foreach ($products as $product) { foreach ($this->langs as $key=>$value) { $product->setCulture($value); try {$friendyurl = $product->getFriendlyUrl();} catch (Exception $e) {$friendyurl = "";} if (!empty($friendyurl)) { $this->writeData[] = $this->generateSitemapLink(st_url_for("stProduct/show?url=".$product->getFriendlyUrl(),true, 'frontend', $this->host, $key), $product->getUpdatedAt(DATE_ATOM), 1.0); } else { $this->writeData[] = $this->generateSitemapLink(st_url_for('stProduct/show?id='.$product->getId()."&lang=".$key,true, 'frontend', $this->host, $key), $product->getUpdatedAt(DATE_ATOM), 1.0); } } } $this->msg = $i18n->__('Generuje mape witryny dla produktów', array(), 'stPositioningBackend'); return count($products); } /** * funkcja pomocnicza generujaca przyjazny link * @param $loc string * @param $lastmod string; * @param $priority double * @param $changefreq string */ protected function generateSitemapLink($loc, $lastmod, $priority=0.5, $changefreq = 'weekly') { return content_tag('url',content_tag('loc',$loc).content_tag('lastmod',$lastmod).content_tag('priority',$priority).content_tag('changefreq',$changefreq)); } /** * Zapisuje dane do pliku * @param $step integer */ protected function writeDatatoFile($step) { $file_index = $step?floor($step/$this->linksPerPage):0; foreach ($this->writeData as $data) { if ($this->fileHandle === false) $this->openFile($step); if (!empty($data)) fputs($this->fileHandle,$data."\n"); $step++; $new_file_index = $step?floor($step/$this->linksPerPage):0; if ($new_file_index != $file_index) { $this->writeFooter(); $file_index = $new_file_index; } } } /** * Zapisuje nagłówek pliku * */ protected function writeHeader() { fputs($this->fileHandle,''."\n"); fputs($this->fileHandle,''."\n"); } /** * Zapisuje stopke pliku * */ protected function writeFooter() { fputs($this->fileHandle,''."\n"); $this->closeFile(); } /** * Otwiera plik xml do zapisu */ protected function openFile($step) { if ($this->fileHandle === false) { $file_index = $step?floor($step/$this->linksPerPage):0; $filename = sfConfig::get('sf_cache_dir').DIRECTORY_SEPARATOR.'sitemap_index_'.$this->lang.'_'.$file_index.'.xml'; if (!file_exists($filename)) { $this->fileHandle = fopen($filename,'a+'); $this->writeHeader(); } else { $this->fileHandle = fopen($filename,'a+'); } } } /** * Zamyka plik xml * */ protected function closeFile() { if ($this->fileHandle) { fclose($this->fileHandle); } $this->fileHandle=false; } /** * Inicjalizacja progressBara * */ public function init() { $filename = sfConfig::get('sf_cache_dir').DIRECTORY_SEPARATOR.'sitemap_index_*.xml'; $files = glob($filename); foreach($files as $file) { unlink($file); } } /** * Zwraca wiadomość do progressBara * */ public function getMessage() { return $this->msg; } /** * Konczy prace progressBara * */ public function close() { $this->initLangs($this->getLangFromFunction(sfContext::getInstance()->getRequest()->getParameterHolder()->get('name'))); $progressBarInformation = sfContext::getInstance()->getUser()->getAttribute('stPositioning_sitemap_'.$this->culture, array(), 'soteshop/stProgressBarPlugin'); if ($progressBarInformation['steps']%$this->linksPerPage) { $steps = $progressBarInformation['steps']; $this->openFile($steps); $this->writeFooter(); } $this->generateGlobalSiteMap(); sfLoader::loadHelpers('Helper'); sfLoader::loadHelpers('Url'); sfLoader::loadHelpers('stAdminGenerator'); $this->msg = sfContext::getInstance()->getI18N()->__('Mapa witryny', null, 'stPositioningBackend').": ".st_external_link_to("http://".$this->host."/sitemap_".$this->lang.".xml", "http://".$this->host."/sitemap_".$this->lang.".xml", array('target'=>'_new')); } /** * Tworzy główny plik z sitemap * */ protected function generateGlobalSiteMap() { $filename = sfConfig::get('sf_web_dir').DIRECTORY_SEPARATOR.'xml'.DIRECTORY_SEPARATOR.'sitemap_index_'.$this->lang.'_*.xml'; $files = glob($filename); foreach($files as $file) { unlink($file); } $fh = fopen(sfConfig::get('sf_web_dir').DIRECTORY_SEPARATOR.'sitemap_'.$this->lang.'.xml','w+'); fputs($fh,''."\n"); fputs($fh,''."\n"); $filename = sfConfig::get('sf_cache_dir').DIRECTORY_SEPARATOR.'sitemap_index_'.$this->lang.'_*.xml'; $files = glob($filename); foreach($files as $file) { rename($file,sfConfig::get('sf_web_dir').DIRECTORY_SEPARATOR.'xml'.DIRECTORY_SEPARATOR.basename($file)); fputs($fh,content_tag('sitemap', content_tag('loc',sfContext::getInstance()->getController()->genUrl("http://".$this->host.'/xml/'.basename($file),true)). content_tag('lastmod',date(DATE_ATOM)) )."\n"); } fputs($fh,''."\n"); fclose($fh); } public function __call($method, $args = array()) { if (strpos($method, 'step') === 0) { $x = explode("_", $method, 2); return $this->step($args[0], $x[1]); } else { throw new Exception(sprintf('Method %s does not exist', $method)); } } protected function getLangFromFunction($method) { $x = explode("_", $method,3); if (count($x)==3) { return $x[2]; } return 'pl_PL'; } public static function getDefaultDomainForLang($shortcut) { $domains = LanguageHasDomainPeer::doSelectByLanguageShortcut($shortcut); foreach ($domains as $domain) { if ($domain->getIsDefault()) { return $domain->getDomain(); } } return sfContext::getInstance()->getRequest()->getHost(); } }