Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save vdubyna/6162493 to your computer and use it in GitHub Desktop.
Save vdubyna/6162493 to your computer and use it in GitHub Desktop.
Magento URL rewrite bug
<?php
/**
* Rewrite Mage_Catalog_Model_Resource_Url class
*
* @category Lyonscg
* @package Lyonscg_Catalog
* @author Vladimir Kosenok vkosenok@lyonscg.com
* @copyright Copyright (c) 2012 Lyons Consulting Group (www.lyonscg.com)
*/
/**
* Catalog url rewrite resource model
* Add product 'type_id' field to _getProducts() method
*
* @category Lyonscg
* @package Lyonscg_Catalog
* @author Vladimir Kosenok vkosenok@lyonscg.com
*/
class Lyonscg_Catalog_Model_Resource_Url extends Mage_Catalog_Model_Resource_Url
{
/**
* Retrieve Product data objects
* Modified: add "type_id" field to select
*
* @param int|array $productIds
* @param int $storeId
* @param int $entityId
* @param int $lastEntityId
* @return array
*/
protected function _getProducts($productIds, $storeId, $entityId, &$lastEntityId)
{
$products = array();
$websiteId = Mage::app()->getStore($storeId)->getWebsiteId();
$adapter = $this->_getReadAdapter();
if ($productIds !== null) {
if (!is_array($productIds)) {
$productIds = array($productIds);
}
}
$bind = array(
'website_id' => (int)$websiteId,
'entity_id' => (int)$entityId,
);
$select = $adapter->select()
->useStraightJoin(true)
->from(array('e' => $this->getTable('catalog/product')), array('entity_id', 'type_id'))
->join(
array('w' => $this->getTable('catalog/product_website')),
'e.entity_id = w.product_id AND w.website_id = :website_id',
array()
)
->where('e.entity_id > :entity_id')
->order('e.entity_id')
->limit($this->_productLimit);
if ($productIds !== null) {
$select->where('e.entity_id IN(?)', $productIds);
}
$rowSet = $adapter->fetchAll($select, $bind);
foreach ($rowSet as $row) {
$product = new Varien_Object($row);
$product->setIdFieldName('entity_id');
$product->setCategoryIds(array());
$product->setStoreId($storeId);
$products[$product->getId()] = $product;
$lastEntityId = $product->getId();
}
unset($rowSet);
if ($products) {
$select = $adapter->select()
->from(
$this->getTable('catalog/category_product'),
array('product_id', 'category_id')
)
->where('product_id IN(?)', array_keys($products));
$categories = $adapter->fetchAll($select);
foreach ($categories as $category) {
$productId = $category['product_id'];
$categoryIds = $products[$productId]->getCategoryIds();
$categoryIds[] = $category['category_id'];
$products[$productId]->setCategoryIds($categoryIds);
}
foreach (array('name', 'url_key', 'url_path') as $attributeCode) {
$attributes = $this->_getProductAttribute($attributeCode, array_keys($products), $storeId);
foreach ($attributes as $productId => $attributeValue) {
$products[$productId]->setData($attributeCode, $attributeValue);
}
}
}
return $products;
}
}
<?php
/**
* Rewrite Mage_Catalog_Model_Url class
*
* @category Lyonscg
* @package Lyonscg_Catalog
* @author Vladimir Kosenok vkosenok@lyonscg.com
* @copyright Copyright (c) 2012 Lyons Consulting Group (www.lyonscg.com)
*/
/**
* Catalog url model
* Override Url rewrites functionality to fix Magento bug
* Bug appears when products have equal names and enabled option
* System/Configuration/Catalog/Search Engine Optimizations/Create Permanent Redirect for URLs if URL Key Changed
* save history of url rewrites changes.
* Magento increases count of url rewrites each time after reindex, independently of catalog changes
*
* @category Lyonscg
* @package Lyonscg_Catalog
* @author Vladimir Kosenok vkosenok@lyonscg.com
*/
class Lyonscg_Catalog_Model_Url extends Mage_Catalog_Model_Url
{
/**
* Refresh all product rewrites for designated store
* Modified: exclude simples with non bounded categories (options of configurables)
*
* @param int $storeId
* @return Mage_Catalog_Model_Url
*/
public function refreshProductRewrites($storeId)
{
$this->_categories = array();
$storeRootCategoryId = $this->getStores($storeId)->getRootCategoryId();
$storeRootCategoryPath = $this->getStores($storeId)->getRootCategoryPath();
$this->_categories[$storeRootCategoryId] = $this->getResource()->getCategory($storeRootCategoryId, $storeId);
$lastEntityId = 0;
$process = true;
while ($process == true) {
$products = $this->getResource()->getProductsByStore($storeId, $lastEntityId);
if (!$products) {
$process = false;
break;
}
$this->_rewrites = $this->getResource()->prepareRewrites($storeId, false, array_keys($products));
$loadCategories = array();
foreach ($products as $product) {
foreach ($product->getCategoryIds() as $categoryId) {
if (!isset($this->_categories[$categoryId])) {
$loadCategories[$categoryId] = $categoryId;
}
}
}
if ($loadCategories) {
foreach ($this->getResource()->getCategories($loadCategories, $storeId) as $category) {
$this->_categories[$category->getId()] = $category;
}
}
foreach ($products as $product) {
//modified: exclude simples with non bounded categories (options of configurables)
if($product->getTypeId() == "simple" && !count($product->getCategoryIds())){
continue;
}
$this->_refreshProductRewrite($product, $this->_categories[$storeRootCategoryId]);
foreach ($product->getCategoryIds() as $categoryId) {
if ($categoryId != $storeRootCategoryId && isset($this->_categories[$categoryId])) {
if (strpos($this->_categories[$categoryId]['path'], $storeRootCategoryPath . '/') !== 0) {
continue;
}
$this->_refreshProductRewrite($product, $this->_categories[$categoryId]);
}
}
}
unset($products);
$this->_rewrites = array();
}
$this->_categories = array();
return $this;
}
/**
* Get unique product request path
* Modified: fix magento bug with checking of existent records
*
* @param Varien_Object $product
* @param Varien_Object $category
* @return string
*/
public function getProductRequestPath($product, $category)
{
if ($product->getUrlKey() == '') {
$urlKey = $this->getProductModel()->formatUrlKey($product->getName());
} else {
$urlKey = $this->getProductModel()->formatUrlKey($product->getUrlKey());
}
$storeId = $category->getStoreId();
$suffix = $this->getProductUrlSuffix($storeId);
$idPath = $this->generatePath('id', $product, $category);
/**
* Prepare product base request path
*/
if ($category->getLevel() > 1) {
// To ensure, that category has path either from attribute or generated now
$this->_addCategoryUrlPath($category);
$categoryUrl = Mage::helper('catalog/category')->getCategoryUrlPath($category->getUrlPath(),
false, $storeId);
$requestPath = $categoryUrl . '/' . $urlKey;
} else {
$requestPath = $urlKey;
}
if (strlen($requestPath) > self::MAX_REQUEST_PATH_LENGTH + self::ALLOWED_REQUEST_PATH_OVERFLOW) {
$requestPath = substr($requestPath, 0, self::MAX_REQUEST_PATH_LENGTH);
}
$this->_rewrite = null;
/**
* Check $requestPath should be unique
*/
if (isset($this->_rewrites[$idPath])) {
$this->_rewrite = $this->_rewrites[$idPath];
$existingRequestPath = $this->_rewrites[$idPath]->getRequestPath();
//fix magento bug, related to incorrect checking of existent urls
if (($existingRequestPath == $requestPath . $suffix)
|| ($existingRequestPath == $requestPath .'-'.$product->getId(). $suffix)
) {
return $existingRequestPath;
}
$existingRequestPath = preg_replace('/' . preg_quote($suffix, '/') . '$/', '', $existingRequestPath);
/**
* Check if existing request past can be used
*/
if ($product->getUrlKey() == '' && !empty($requestPath)
&& strpos($existingRequestPath, $requestPath) === 0
) {
$existingRequestPath = preg_replace(
'/^' . preg_quote($requestPath, '/') . '/', '', $existingRequestPath
);
if (preg_match('#^-([0-9]+)$#i', $existingRequestPath)) {
return $this->_rewrites[$idPath]->getRequestPath();
}
}
$fullPath = $requestPath.$suffix;
if ($this->_deleteOldTargetPath($fullPath, $idPath, $storeId)) {
return $fullPath;
}
}
/**
* Check 2 variants: $requestPath and $requestPath . '-' . $productId
*/
$validatedPath = $this->getResource()->checkRequestPaths(
array($requestPath.$suffix, $requestPath.'-'.$product->getId().$suffix),
$storeId
);
if ($validatedPath) {
return $validatedPath;
}
/**
* Use unique path generator
*/
return $this->getUnusedPath($storeId, $requestPath.$suffix, $idPath);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<config>
<modules>
<Lyonscg_Catalog>
<version>0.1.4</version>
</Lyonscg_Catalog>
</modules>
<global>
<models>
<lyonscg_catalog>
<class>Lyonscg_Catalog_Model</class>
</lyonscg_catalog>
<catalog>
<rewrite>
<url>Lyonscg_Catalog_Model_Url</url>
</rewrite>
</catalog>
<catalog_resource>
<rewrite>
<url>Lyonscg_Catalog_Model_Resource_Url</url>
</rewrite>
</catalog_resource>
</models>
<resources>
<lyonscg_catalog_setup>
<setup>
<module>Lyonscg_Catalog</module>
<class>Mage_Core_Model_Resource_Setup</class>
</setup>
</lyonscg_catalog_setup>
</resources>
</global>
</config>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment