На одном из проектов неожиданно столкнулись с проблемой, при которой 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 будет генерироваться корректно.