Last active
November 9, 2017 12:42
-
-
Save vdubyna/6162493 to your computer and use it in GitHub Desktop.
Magento URL rewrite bug
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?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