На одном из проектов неожиданно столкнулись с проблемой, при которой sitemap.xml генерировался некорректно.
Суть проблемы заключалась в том, что в конец URL категорий/продуктов добавлялся символ "." в случае, когда URL суффикс категорий/продуктов был пустым.
Кроме того, Magento позволяет задать для каждого Store свой URL суффикс для продуктов/категорий, а при генерации всегда используется дефолтный суффикс.
Баги были замечены в версии Magento Enterprise 1.14.1.0.
Каким образом в Magento Enterprise добавлялся URL суффикс?
В модуле `Enterprise_Catalog` есть эвенты `sitemap_categories_generating_before` и `sitemap_products_generating_before`.
Код:
/**
* Add Seo suffix to category's URL if doesn't exists.
*
* @param Varien_Event_Observer $observer
*/
public function addSeoSuffixToCategoryUrl(Varien_Event_Observer $observer)
{
$seoSuffix = (string) Mage::app()->getStore()->getConfig(
Mage_Catalog_Helper_Category::XML_PATH_CATEGORY_URL_SUFFIX
);
$this->_addSuffixToUrl($observer->getCollection()->getItems(), $seoSuffix);
}
/**
* Add Seo suffix to product's URL if doesn't exists.
*
* @param Varien_Event_Observer $observer
*/
public function addSeoSuffixToProductUrl(Varien_Event_Observer $observer)
{
$seoSuffix = (string) Mage::app()->getStore()->getConfig(
Mage_Catalog_Helper_Product::XML_PATH_PRODUCT_URL_SUFFIX
);
$this->_addSuffixToUrl($observer->getCollection()->getItems(), $seoSuffix);
}
/**
* Iterate via items and add suffix to item's URL.
*
* @param $items
* @param $seoSuffix
*/
protected function _addSuffixToUrl($items, $seoSuffix)
{
foreach ($items as $item) {
if ($item->getUrl() && strpos($item->getUrl(), $seoSuffix) === false) {
$item->setUrl($item->getUrl() . '.' . $seoSuffix);
}
}
}
Здесь видно, что нет проверки на пустоту URL суффикса и всегда добавляется точка. Кроме того, всегда берётся суффикс для дефолтного Store.
Этот баг довольно просто пофиксить. Сначала переопределим эвенты. Вместо выполнения эвентов из модуля `Enterprise_Catalog`, выполним свои.
В config.xml в секции adminhtml/events добавляем:
<sitemap_categories_generating_before> <observers> <set_category_url_suffix> <class>turnkeye_catalog/observer</class> <method>addSeoSuffixToCategoryUrl</method> </set_category_url_suffix> </observers> </sitemap_categories_generating_before> <sitemap_products_generating_before> <observers> <set_product_url_suffix> <class>turnkeye_catalog/observer</class> <method>addSeoSuffixToProductUrl</method> </set_product_url_suffix> </observers> </sitemap_products_generating_before>
В обсервере Turnkeye_Catalog_Model_Observer ставим пустые методы:
/**
* REWRITE DEFAULT ENTERPRISE OBSERVER: DO NOTHING!
*
* event: sitemap_categories_generating_before
*
* @param Varien_Event_Observer $observer
* @return $this
*/
public function addSeoSuffixToCategoryUrl(Varien_Event_Observer $observer)
{
return $this;
}
/**
* REWRITE DEFAULT ENTERPRISE OBSERVER: DO NOTHING!
*
* event: sitemap_products_generating_before
*
* @param Varien_Event_Observer $observer
* @return $this
*/
public function addSeoSuffixToProductUrl(Varien_Event_Observer $observer)
{
return $this;
}
С этого момента URL суффиксы для категорий/продуктов не будут добавляться.
Теперь добавим их с учётом Store. "Зареврайтим" стандартный класс Mage_Sitemap_Model_Sitemap, в config.xml вашего модуля в секции global/models добавим:
<sitemap> <rewrite> <sitemap>Turnkeye_Catalog_Rewrite_Mage_Sitemap_Model_Sitemap</sitemap> </rewrite> </sitemap>
Здесь Turnkeye_Catalog_Rewrite_Mage_Sitemap_Model_Sitemap - класс, который наследуется от Mage_Sitemap_Model_Sitemap и переписывает его.
Определим и добавим два метода в наш класс Turnkeye_Catalog_Rewrite_Mage_Sitemap_Model_Sitemap:
protected function _getCategoryUrlSuffix($storeId)
{
$suffix = (string) Mage::app()->getStore()->getConfig(
Mage_Catalog_Helper_Category::XML_PATH_CATEGORY_URL_SUFFIX, $storeId
);
$suffix = ltrim($suffix, '.');
if ($suffix) {
$suffix = '.' . $suffix;
}
return $suffix;
}
protected function _getProductUrlSuffix($storeId)
{
$suffix = (string) Mage::app()->getStore()->getConfig(
Mage_Catalog_Helper_Product::XML_PATH_PRODUCT_URL_SUFFIX, $storeId
);
$suffix = ltrim($suffix, '.');
if ($suffix) {
$suffix = '.' . $suffix;
}
return $suffix;
}
После этого переопределим метод generateXml в классе Turnkeye_Catalog_Rewrite_Mage_Sitemap_Model_Sitemap следующим образом:
/**
* Generate XML file
*
* @return Mage_Sitemap_Model_Sitemap
*/
public function generateXml()
{
$io = new Varien_Io_File();
$io->setAllowCreateFolders(true);
$io->open(array('path' => $this->getPath()));
if ($io->fileExists($this->getSitemapFilename()) && !$io->isWriteable($this->getSitemapFilename())) {
Mage::throwException(Mage::helper('sitemap')->__('File "%s" cannot be saved. Please, make sure the directory "%s" is writeable by web server.', $this->getSitemapFilename(), $this->getPath()));
}
$io->streamOpen($this->getSitemapFilename());
$io->streamWrite('<?xml version="1.0" encoding="UTF-8"?>' . "\n");
$io->streamWrite('<urlset xmlns="http: // www. sitemaps.org/schemas/sitemap/0.9">');
$storeId = $this->getStoreId();
$date = Mage::getSingleton('core/date')->gmtDate('Y-m-d');
$baseUrl = Mage::app()->getStore($storeId)->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK);
/**
* Generate categories sitemap
*/
$changefreq = (string)Mage::getStoreConfig('sitemap/category/changefreq', $storeId);
$priority = (string)Mage::getStoreConfig('sitemap/category/priority', $storeId);
$collection = Mage::getResourceModel('sitemap/catalog_category')->getCollection($storeId);
$categories = new Varien_Object();
$categories->setItems($collection);
Mage::dispatchEvent('sitemap_categories_generating_before', array(
'collection' => $categories
));
$suffix = $this->_getCategoryUrlSuffix($storeId);
foreach ($categories->getItems() as $item) {
if (mb_strpos($item->getUrl(), 'catalog/category/view/id/', null, 'UTF-8') === false) {
$item->setUrl($item->getUrl() . $suffix);
}
$xml = sprintf(
'<url><loc>%s</loc><lastmod>%s</lastmod><changefreq>%s</changefreq><priority>%.1f</priority></url>',
htmlspecialchars($baseUrl . $item->getUrl()),
$date,
$changefreq,
$priority
);
$io->streamWrite($xml);
}
unset($collection);
/**
* Generate products sitemap
*/
$changefreq = (string)Mage::getStoreConfig('sitemap/product/changefreq', $storeId);
$priority = (string)Mage::getStoreConfig('sitemap/product/priority', $storeId);
$collection = Mage::getResourceModel('sitemap/catalog_product')->getCollection($storeId);
$products = new Varien_Object();
$products->setItems($collection);
Mage::dispatchEvent('sitemap_products_generating_before', array(
'collection' => $products
));
$suffix = $this->_getProductUrlSuffix($storeId);
foreach ($products->getItems() as $item) {
if (mb_strpos($item->getUrl(), 'catalog/product/view/id/', null, 'UTF-8') === false) {
$item->setUrl($item->getUrl() . $suffix);
}
$xml = sprintf(
'<url><loc>%s</loc><lastmod>%s</lastmod><changefreq>%s</changefreq><priority>%.1f</priority></url>',
htmlspecialchars($baseUrl . $item->getUrl()),
$date,
$changefreq,
$priority
);
$io->streamWrite($xml);
}
unset($collection);
/**
* Generate cms pages sitemap
*/
$changefreq = (string)Mage::getStoreConfig('sitemap/page/changefreq', $storeId);
$priority = (string)Mage::getStoreConfig('sitemap/page/priority', $storeId);
$collection = Mage::getResourceModel('sitemap/cms_page')->getCollection($storeId);
foreach ($collection as $item) {
$xml = sprintf(
'<url><loc>%s</loc><lastmod>%s</lastmod><changefreq>%s</changefreq><priority>%.1f</priority></url>',
htmlspecialchars($baseUrl . $item->getUrl()),
$date,
$changefreq,
$priority
);
$io->streamWrite($xml);
}
unset($collection);
$io->streamWrite('</urlset>');
$io->streamClose();
$this->setSitemapTime(Mage::getSingleton('core/date')->gmtDate('Y-m-d H:i:s'));
$this->save();
return $this;
}
Возможно возникнет вопрос, для чего необходима проверка вида "mb_strpos($item->getUrl(), 'catalog/category/view/id/', null, 'UTF-8')". Для некоторых категорий/продуктов может отсутствовать URL Rewrite и для них будет сгенерирован URL стандартного роутера такого вида. Добавлять к нему суффикс не нужно.
С этого момента в URL продуктов/категорий в sitemap.xml будет генерироваться корректно.
