diff --git a/app/code/core/Mage/Catalog/Model/Indexer/Url.php b/app/code/core/Mage/Catalog/Model/Indexer/Url.php
index aeda8341a9d2..3d1db33adfca 100644
--- a/app/code/core/Mage/Catalog/Model/Indexer/Url.php
+++ b/app/code/core/Mage/Catalog/Model/Indexer/Url.php
@@ -182,6 +182,7 @@ protected function _registerProductEvent(Mage_Index_Model_Event $event)
{
$product = $event->getDataObject();
$dataChange = $product->dataHasChangedFor('url_key')
+ || $product->dataHasChangedFor('status')
|| $product->getIsChangedCategories()
|| $product->getIsChangedWebsites();
@@ -199,7 +200,11 @@ protected function _registerCategoryEvent(Mage_Index_Model_Event $event)
{
$category = $event->getDataObject();
if (!$category->getInitialSetupFlag() && $category->getLevel() > 1) {
- if ($category->dataHasChangedFor('url_key') || $category->getIsChangedProductList()) {
+ if (
+ $category->dataHasChangedFor('url_key')
+ || $category->getIsChangedProductList()
+ || $category->dataHasChangedFor('is_active')
+ ) {
$event->addNewData('rewrite_category_ids', array($category->getId()));
}
/**
diff --git a/app/code/core/Mage/Catalog/Model/Resource/Url.php b/app/code/core/Mage/Catalog/Model/Resource/Url.php
index e76055577281..859cca887528 100644
--- a/app/code/core/Mage/Catalog/Model/Resource/Url.php
+++ b/app/code/core/Mage/Catalog/Model/Resource/Url.php
@@ -688,9 +688,10 @@ protected function _prepareStoreRootCategories($stores)
* @param int|array $categoryIds
* @param int $storeId
* @param string $path
+ * @param bool $withDisabled
* @return array
*/
- protected function _getCategories($categoryIds, $storeId = null, $path = null)
+ protected function _getCategories($categoryIds, $storeId = null, $path = null, $withDisabled = true)
{
$isActiveAttribute = Mage::getSingleton('eav/config')
->getAttribute(Mage_Catalog_Model_Category::ENTITY, 'is_active');
@@ -738,6 +739,10 @@ protected function _getCategories($categoryIds, $storeId = null, $path = null)
$rootCategoryPath = $this->getStores($storeId)->getRootCategoryPath();
$rootCategoryPathLength = strlen($rootCategoryPath);
}
+ if (!$withDisabled) {
+ $select->where('IF(c.value_id > 0, c.value, d.value) = 1');
+ }
+
$bind = array(
'attribute_id' => (int)$isActiveAttribute->getId(),
'store_id' => (int)$storeId
@@ -808,15 +813,16 @@ public function getCategory($categoryId, $storeId)
*
* @param int|array $categoryIds
* @param int $storeId
+ * @param bool $withDisabled
* @return Mage_Catalog_Model_Category[]|false
*/
- public function getCategories($categoryIds, $storeId)
+ public function getCategories($categoryIds, $storeId, $withDisabled = true)
{
if (!$categoryIds || !$storeId) {
return false;
}
- return $this->_getCategories($categoryIds, $storeId);
+ return $this->_getCategories($categoryIds, $storeId, null, $withDisabled);
}
/**
@@ -939,9 +945,11 @@ public function getProductIdsByCategory($category)
* @param int $storeId
* @param int $entityId
* @param int $lastEntityId
+ * @param bool $withDisabled
* @return array
+ * @throws Mage_Core_Model_Store_Exception
*/
- protected function _getProducts($productIds, $storeId, $entityId, &$lastEntityId)
+ protected function _getProducts($productIds, $storeId, $entityId, &$lastEntityId, $withDisabled = true)
{
$products = array();
$websiteId = Mage::app()->getStore($storeId)->getWebsiteId();
@@ -969,6 +977,16 @@ protected function _getProducts($productIds, $storeId, $entityId, &$lastEntityId
if ($productIds !== null) {
$select->where('e.entity_id IN(?)', $productIds);
}
+ if (!$withDisabled) {
+ $statusId = Mage::getResourceModel('eav/entity_attribute')
+ ->getIdByCode('catalog_product', 'status');
+ $select->join(
+ ['cpei' => 'catalog_product_entity_int'],
+ 'cpei.entity_id = e.entity_id AND cpei.entity_type_id = 4 AND cpei.attribute_id = ' . (int)$statusId,
+ []
+ );
+ $select->where('cpei.value <> 2');
+ }
$rowSet = $adapter->fetchAll($select, $bind);
foreach ($rowSet as $row) {
@@ -1013,12 +1031,14 @@ protected function _getProducts($productIds, $storeId, $entityId, &$lastEntityId
*
* @param int $productId
* @param int $storeId
+ * @param bool $withDisabled
* @return Varien_Object|false
+ * @throws Mage_Core_Model_Store_Exception
*/
- public function getProduct($productId, $storeId)
+ public function getProduct($productId, $storeId, $withDisabled = true)
{
$entityId = 0;
- $products = $this->_getProducts($productId, $storeId, 0, $entityId);
+ $products = $this->_getProducts($productId, $storeId, 0, $entityId, $withDisabled);
if (isset($products[$productId])) {
return $products[$productId];
}
@@ -1030,11 +1050,12 @@ public function getProduct($productId, $storeId)
*
* @param int $storeId
* @param int $lastEntityId
+ * @param bool $withDisabled
* @return Mage_Catalog_Model_Product[]
*/
- public function getProductsByStore($storeId, &$lastEntityId)
+ public function getProductsByStore($storeId, &$lastEntityId, $withDisabled = true)
{
- return $this->_getProducts(null, $storeId, $lastEntityId, $lastEntityId);
+ return $this->_getProducts(null, $storeId, $lastEntityId, $lastEntityId, $withDisabled);
}
/**
@@ -1054,32 +1075,87 @@ public function getProductsByCategory(Varien_Object $category, &$lastEntityId)
}
/**
- * Find and remove unused products rewrites - a case when products were moved away from the category
- * (either to other category or deleted), so rewrite "category_id-product_id" is invalid
+ * Unused function. Left for backward compatibility
*
* @param int $storeId
* @return $this
*/
public function clearCategoryProduct($storeId)
+ {
+ return $this->clearRewrites($storeId);
+ }
+
+ /**
+ * Find and remove unused rewrites a case when
+ * - products were moved away from the category (either to other category or deleted), so rewrite "category_id-product_id" is invalid
+ * - category
+ *
+ * @param int $storeId
+ * @return $this
+ */
+ public function clearRewrites($storeId)
{
$adapter = $this->_getWriteAdapter();
+ list($select, $bind) = $this->getSelectToClearRewrites($adapter, $storeId);
- $productUseCategories = Mage::getStoreConfigFlag('catalog/seo/product_use_categories');
+ $rewriteIds = $adapter->fetchCol($select, $bind);
+ if ($rewriteIds) {
+ $where = array($this->getIdFieldName() . ' IN(?)' => $rewriteIds);
+ $adapter->delete($this->getMainTable(), $where);
+ }
+
+ return $this;
+ }
+
+ /**
+ * Find and remove unused category rewrites - a case when category is disabled and in config field
+ * catalog/seo/create_url_for_disabled is set as false
+ *
+ * @param int $categoryId
+ * @param int|null $storeId
+ * @return $this
+ */
+ public function clearDisabledCategory($categoryId, $storeId = null)
+ {
+ if (Mage::getStoreConfigFlag('catalog/seo/create_url_for_disabled')) {
+ return $this;
+ }
+
+ if (is_null($storeId)) {
+ foreach ($this->getStores() as $store) {
+ $this->clearDisabledCategory($categoryId, $store);
+ }
+ return $this;
+ }
+
+ $adapter = $this->_getWriteAdapter();
+
+ $table = $this->getTable(array('catalog/category', 'int'));
$select = $adapter->select()
->from(array('tur' => $this->getMainTable()), $this->getIdFieldName())
->joinLeft(
- array('tcp' => $this->getTable('catalog/category_product')),
- 'tur.category_id = tcp.category_id AND tur.product_id = tcp.product_id',
+ array('ccei1' => $table),
+ 'ccei1.attribute_id = :is_active_category_attribute_id AND ccei1.store_id = 0 AND ccei1.entity_id = tur.category_id',
+ array()
+ )
+ ->joinLeft(
+ array('ccei2' => $table),
+ 'ccei2.attribute_id = :is_active_category_attribute_id AND ccei2.store_id = :store_id AND ccei2.entity_id = tur.category_id',
array()
)
+ ->where('IF(ccei2.value_id > 0, ccei2.value, ccei1.value) = 0')
->where('tur.store_id = :store_id')
- ->where('tur.category_id IS NOT NULL')
- ->where('tur.product_id IS NOT NULL');
+ ->where('tur.category_id = :category_id');
- if ($productUseCategories) {
- $select->where('tcp.category_id IS NULL');
- }
- $rewriteIds = $adapter->fetchCol($select, array('store_id' => $storeId));
+ $isActiveCategoryAttribute = Mage::getSingleton('eav/config')
+ ->getAttribute(Mage_Catalog_Model_Category::ENTITY, 'is_active');
+ $bind = [
+ 'store_id' => $storeId,
+ 'is_active_category_attribute_id' => $isActiveCategoryAttribute->getId(),
+ 'category_id' => $categoryId
+ ];
+
+ $rewriteIds = $adapter->fetchCol($select, $bind);
if ($rewriteIds) {
$where = array($this->getIdFieldName() . ' IN(?)' => $rewriteIds);
$adapter->delete($this->getMainTable(), $where);
@@ -1088,6 +1164,93 @@ public function clearCategoryProduct($storeId)
return $this;
}
+ /**
+ * Prepare select to find unused rewrites
+ * as set in configuration fields catalog/seo/product_use_categories and catalog/seo/create_url_for_disabled
+ *
+ * @param Magento_Db_Adapter_Pdo_Mysql $adapter
+ * @param int $storeId
+ * @return array
+ */
+ protected function getSelectToClearRewrites($adapter, $storeId)
+ {
+ $productUseCategories = Mage::getStoreConfigFlag('catalog/seo/product_use_categories');
+ $createUrlForDisabled = Mage::getStoreConfigFlag('catalog/seo/create_url_for_disabled');
+
+ $bind = ['store_id' => $storeId];
+ $select = $adapter->select()
+ ->from(array('tur' => $this->getMainTable()), $this->getIdFieldName())
+ ->where('tur.store_id = :store_id')
+ ->where('tur.is_system = 1');
+
+ if ($createUrlForDisabled) {
+
+ // Find rewrites for cartegory/product
+ $select->where('tur.category_id IS NOT NULL')
+ ->where('tur.product_id IS NOT NULL');
+
+ // Find unused products rewrites - a case when products were moved away from the category
+ // (either to other category or deleted), so rewrite "category_id-product_id" is invalid
+ if ($productUseCategories) {
+ $select->joinLeft(
+ array('tcp' => $this->getTable('catalog/category_product')),
+ 'tur.category_id = tcp.category_id AND tur.product_id = tcp.product_id',
+ array()
+ )
+ ->where('tcp.category_id IS NULL');
+ }
+
+ } else {
+ // Find products, cartegories and cartegory/product rewrites for disabled products or cartegories
+ $productTable = $this->getTable(array('catalog/product', 'int'));
+ $categoryTable = $this->getTable(array('catalog/category', 'int'));
+ $select->joinLeft(
+ ['cpei' => $productTable],
+ 'cpei.entity_id = tur.product_id AND cpei.attribute_id = :product_status_attribute_id',
+ []
+ )
+ ->joinLeft(
+ array('ccei1' => $categoryTable),
+ 'ccei1.attribute_id = :is_active_category_attribute_id AND ccei1.store_id = 0 AND ccei1.entity_id = tur.category_id',
+ array()
+ )
+ ->joinLeft(
+ array('ccei2' => $categoryTable),
+ 'ccei2.attribute_id = :is_active_category_attribute_id AND ccei2.store_id = :store_id AND ccei2.entity_id = tur.category_id',
+ array()
+ );
+ $productStatusAttributeId = Mage::getSingleton('eav/config')
+ ->getAttribute(Mage_Catalog_Model_Product::ENTITY, 'status');
+ $bind['product_status_attribute_id'] = $productStatusAttributeId->getId();
+
+ $isActiveCategoryAttribute = Mage::getSingleton('eav/config')
+ ->getAttribute(Mage_Catalog_Model_Category::ENTITY, 'is_active');
+ $bind['is_active_category_attribute_id'] = $isActiveCategoryAttribute->getId();
+
+ // product_is_disabled OR (category is disabled) OR (cartegory/product rewrite)
+ $where = '(cpei.value = 2 OR (IF(ccei2.value_id > 0, ccei2.value, ccei1.value) = 0) OR (tur.category_id IS NOT NULL AND tur.product_id IS NOT NULL) )';
+
+ // Find products, categories and cartegory/product rewrites for disabled products or categories
+ if ($productUseCategories) {
+ $select
+ ->joinLeft(
+ array('tcp' => $this->getTable('catalog/category_product')),
+ 'tcp.category_id = tur.category_id AND tcp.product_id = tur.product_id',
+ array()
+ );
+ // product_is_disabled OR (category is disabled) OR (cartegory/product rewrite AND product were moved away from the category)
+ $where ='(cpei.value = 2 OR (IF(ccei2.value_id > 0, ccei2.value, ccei1.value) = 0) OR (tur.category_id IS NOT NULL AND tur.product_id IS NOT NULL AND tcp.category_id IS NULL))';
+ }
+ $select->where($where);
+ }
+ $select->group('url_rewrite_id');
+
+ return [
+ $select,
+ $bind
+ ];
+ }
+
/**
* Remove unused rewrites for product - called after we created all needed rewrites for product and know the categories
* where the product is contained ($excludeCategoryIds), so we can remove all invalid product rewrites that have other category ids
diff --git a/app/code/core/Mage/Catalog/Model/Url.php b/app/code/core/Mage/Catalog/Model/Url.php
index 278b60fae65b..de0fb38fde70 100644
--- a/app/code/core/Mage/Catalog/Model/Url.php
+++ b/app/code/core/Mage/Catalog/Model/Url.php
@@ -116,12 +116,18 @@ class Mage_Catalog_Model_Url
*/
protected $productUseCategories;
+ /**
+ * @var bool
+ */
+ protected $createForDisabled;
+
/**
* Neuca_Base_Model_Url constructor.
*/
public function __construct()
{
$this->productUseCategories = Mage::getStoreConfigFlag('catalog/seo/product_use_categories');
+ $this->createForDisabled = Mage::getStoreConfigFlag('catalog/seo/create_url_for_disabled');
}
/**
@@ -267,7 +273,7 @@ public function refreshRewrites($storeId = null)
$this->clearStoreInvalidRewrites($storeId);
$this->refreshCategoryRewrite($this->getStores($storeId)->getRootCategoryId(), $storeId, false);
$this->refreshProductRewrites($storeId);
- $this->getResource()->clearCategoryProduct($storeId);
+ $this->getResource()->clearRewrites($storeId);
return $this;
}
@@ -393,7 +399,7 @@ protected function _refreshProductRewrite(Varien_Object $product, Varien_Object
}
/**
- * Refresh products for catwgory
+ * Refresh products for category
*
* @param Varien_Object|Mage_Catalog_Model_Category $category
* @return $this
@@ -448,7 +454,7 @@ protected function _refreshCategoryProductRewrites(Varien_Object $category)
* @param bool $refreshProducts
* @return $this
*/
- public function refreshCategoryRewrite($categoryId, $storeId = null, $refreshProducts = null)
+ public function refreshCategoryRewrite($categoryId, $storeId = null, $refreshProducts = true)
{
if (!$refreshProducts) {
$refreshProducts = $this->productUseCategories;
@@ -465,6 +471,11 @@ public function refreshCategoryRewrite($categoryId, $storeId = null, $refreshPro
return $this;
}
+ if (!$this->createForDisabled && !$category->getIsActive()) {
+ $this->getResource()->clearDisabledCategory($category->getId());
+ return $this;
+ }
+
// Load all childs and refresh all categories
$category = $this->getResource()->loadCategoryChilds($category);
$categoryIds = array($category->getId());
@@ -497,7 +508,7 @@ public function refreshProductRewrite($productId, $storeId = null)
return $this;
}
- $product = $this->getResource()->getProduct($productId, $storeId);
+ $product = $this->getResource()->getProduct($productId, $storeId, $this->createForDisabled);
if (!$product) {
// Product doesn't belong to this store - clear all its url rewrites including root one
$this->getResource()->clearProductRewrites($productId, $storeId, array());
@@ -529,6 +540,11 @@ public function refreshProductRewrite($productId, $storeId = null)
// Remove all other product rewrites created earlier for this store - they're invalid now
$excludeCategoryIds = array_keys($categories);
+
+ // Product is disabled and in configuration set to not create for disabled - clear all its url rewrites including root one
+ if (!$this->createForDisabled && $product->getStatus() === Mage_Catalog_Model_Product_Status::STATUS_DISABLED) {
+ $excludeCategoryIds = [];
+ }
$this->getResource()->clearProductRewrites($productId, $storeId, $excludeCategoryIds);
unset($categories);
@@ -554,7 +570,8 @@ public function refreshProductRewrites($storeId)
$process = true;
while ($process == true) {
- $products = $this->getResource()->getProductsByStore($storeId, $lastEntityId);
+ $products = $this->getResource()->getProductsByStore($storeId, $lastEntityId, $this->createForDisabled);
+
if (!$products) {
$process = false;
break;
@@ -573,7 +590,7 @@ public function refreshProductRewrites($storeId)
}
}
if ($loadCategories) {
- foreach ($this->getResource()->getCategories($loadCategories, $storeId) as $category) {
+ foreach ($this->getResource()->getCategories($loadCategories, $storeId, $this->createForDisabled) as $category) {
$this->_categories[$category->getId()] = $category;
}
}
diff --git a/app/code/core/Mage/Catalog/etc/config.xml b/app/code/core/Mage/Catalog/etc/config.xml
index 4f048020615c..9f3bbe181050 100644
--- a/app/code/core/Mage/Catalog/etc/config.xml
+++ b/app/code/core/Mage/Catalog/etc/config.xml
@@ -814,6 +814,7 @@
.html
.html
1
+ 1
1
-
0
diff --git a/app/code/core/Mage/Catalog/etc/system.xml b/app/code/core/Mage/Catalog/etc/system.xml
index 9eac9e58ba6b..effde3b852c5 100644
--- a/app/code/core/Mage/Catalog/etc/system.xml
+++ b/app/code/core/Mage/Catalog/etc/system.xml
@@ -291,6 +291,15 @@
1
1
+
+
+ select
+ adminhtml/system_config_source_yesno
+ 4
+ 1
+ 0
+ 1
+
select