diff --git a/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Seo.php b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Seo.php new file mode 100644 index 00000000000..b81d168917a --- /dev/null +++ b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Seo.php @@ -0,0 +1,37 @@ +isValueChanged()) { + Mage::getModel('index/indexer') + ->getProcessByCode(Mage_Catalog_Helper_Category_Flat::CATALOG_CATEGORY_FLAT_PROCESS_CODE) + ->changeStatus(Mage_Index_Model_Process::STATUS_REQUIRE_REINDEX); + + Mage::getModel('index/indexer') + ->getProcessByCode(Mage_Catalog_Helper_Product_Flat::CATALOG_FLAT_PROCESS_CODE) + ->changeStatus(Mage_Index_Model_Process::STATUS_REQUIRE_REINDEX); + } + return $this; + } +} diff --git a/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Seo/Product.php b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Seo/Product.php index fdc4c3b9fec..c7ddf64be58 100644 --- a/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Seo/Product.php +++ b/app/code/core/Mage/Adminhtml/Model/System/Config/Backend/Seo/Product.php @@ -20,12 +20,18 @@ class Mage_Adminhtml_Model_System_Config_Backend_Seo_Product extends Mage_Core_Model_Config_Data { /** - * Refresh category url rewrites if configuration was changed + * Refresh products url rewrites if configuration was changed * * @return $this */ protected function _afterSave() { + if ($this->isValueChanged()) { + Mage::getModel('index/indexer') + ->getProcessByCode(Mage_Catalog_Helper_Product_Flat::CATALOG_FLAT_PROCESS_CODE) + ->changeStatus(Mage_Index_Model_Process::STATUS_REQUIRE_REINDEX); + } + return $this; } } diff --git a/app/code/core/Mage/Catalog/Model/Indexer/Url.php b/app/code/core/Mage/Catalog/Model/Indexer/Url.php index a6f5b42bb67..757957001e2 100644 --- a/app/code/core/Mage/Catalog/Model/Indexer/Url.php +++ b/app/code/core/Mage/Catalog/Model/Indexer/Url.php @@ -40,7 +40,8 @@ class Mage_Catalog_Model_Indexer_Url extends Mage_Index_Model_Indexer_Abstract */ protected $_matchedEntities = [ Mage_Catalog_Model_Product::ENTITY => [ - Mage_Index_Model_Event::TYPE_SAVE + Mage_Index_Model_Event::TYPE_SAVE, + Mage_Index_Model_Event::TYPE_MASS_ACTION ], Mage_Catalog_Model_Category::ENTITY => [ Mage_Index_Model_Event::TYPE_SAVE @@ -173,12 +174,36 @@ protected function _registerEvent(Mage_Index_Model_Event $event) protected function _registerProductEvent(Mage_Index_Model_Event $event) { $product = $event->getDataObject(); - $dataChange = $product->dataHasChangedFor('url_key') - || $product->getIsChangedCategories() - || $product->getIsChangedWebsites(); + $dataChange = false; + $products = []; + + if ($product instanceof Mage_Catalog_Model_Product_Action) { + $attributesData = $product->getData('attributes_data'); + $productsIds = $product->getData('product_ids'); + $dataChange = isset($attributesData['status']) && isset($productsIds) && count($productsIds) > 0; + if ($dataChange) { + $products = Mage::getModel('catalog/product')->getCollection() + ->addFieldToFilter('entity_id', ['in'=> $productsIds]); + } else { + return; + } + } + + if ($product instanceof Mage_Catalog_Model_Product) { + $dataChange = + ( + $product->dataHasChangedFor('url_key') + || $product->dataHasChangedFor('status') + || $product->getIsChangedCategories() + || $product->getIsChangedWebsites() + ) && !$product->getExcludeUrlRewrite(); + $products = [$product]; + } - if (!$product->getExcludeUrlRewrite() && $dataChange) { - $event->addNewData('rewrite_product_ids', [$product->getId()]); + if ($dataChange) { + foreach ($products as $product) { + $event->addNewData('rewrite_product_ids', [$product->getId()]); + } } } @@ -191,7 +216,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', [$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 6e15bccce99..63c092eed84 100644 --- a/app/code/core/Mage/Catalog/Model/Resource/Url.php +++ b/app/code/core/Mage/Catalog/Model/Resource/Url.php @@ -56,6 +56,16 @@ class Mage_Catalog_Model_Resource_Url extends Mage_Core_Model_Resource_Db_Abstra */ protected $_rootChildrenIds = []; + /** + * @var int + */ + protected $_productEntityTypeId; + + /** + * @var int + */ + protected $_statusAttributeId; + /** * Load core Url rewrite model * @@ -63,6 +73,9 @@ class Mage_Catalog_Model_Resource_Url extends Mage_Core_Model_Resource_Db_Abstra protected function _construct() { $this->_init('core/url_rewrite', 'url_rewrite_id'); + $this->_productEntityTypeId = Mage::getSingleton('eav/config')->getEntityType(Mage_Catalog_Model_Product::ENTITY)->getId(); + $this->_statusAttributeId = Mage::getModel('catalog/resource_eav_attribute') + ->loadByCode($this->_productEntityTypeId, 'status')->getId(); } /** @@ -678,9 +691,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'); @@ -728,6 +742,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 = [ 'attribute_id' => (int)$isActiveAttribute->getId(), 'store_id' => (int)$storeId @@ -796,15 +814,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); } /** @@ -927,9 +946,10 @@ public function getProductIdsByCategory($category) * @param int $storeId * @param int $entityId * @param int $lastEntityId + * @param bool $withDisabled * @return array */ - protected function _getProducts($productIds, $storeId, $entityId, &$lastEntityId) + protected function _getProducts($productIds, $storeId, $entityId, &$lastEntityId, $withDisabled = true) { $products = []; $websiteId = Mage::app()->getStore($storeId)->getWebsiteId(); @@ -957,6 +977,14 @@ protected function _getProducts($productIds, $storeId, $entityId, &$lastEntityId if ($productIds !== null) { $select->where('e.entity_id IN(?)', $productIds); } + if (!$withDisabled) { + $select->join( + ['cpei' => 'catalog_product_entity_int'], + 'cpei.entity_id = e.entity_id AND cpei.entity_type_id = ' . $this->_productEntityTypeId . ' AND cpei.attribute_id = ' . $this->_statusAttributeId, + [] + ); + $select->where('cpei.value <> ' . Mage_Catalog_Model_Product_Status::STATUS_DISABLED); + } $rowSet = $adapter->fetchAll($select, $bind); foreach ($rowSet as $row) { @@ -1001,9 +1029,11 @@ 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); @@ -1015,11 +1045,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); } /** @@ -1028,6 +1059,7 @@ public function getProductsByStore($storeId, &$lastEntityId) * @param Varien_Object $category * @param int $lastEntityId * @return array + * @throws Mage_Core_Model_Store_Exception */ public function getProductsByCategory(Varien_Object $category, &$lastEntityId) { @@ -1039,27 +1071,93 @@ 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 + * @deprecated */ 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); + + $rewriteIds = $adapter->fetchCol($select, $bind); + if ($rewriteIds) { + $where = [$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|Mage_Core_Model_Store|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; + } + if ($storeId instanceof Mage_Core_Model_Store) { + $storeId = $storeId->getStoreId(); + } elseif (!is_int($storeId)) { + throw new Exception('StoreId must by int or Mage_Core_Model_Store'); + } + + $adapter = $this->_getWriteAdapter(); + + $table = $this->getTable(['catalog/category', 'int']); $select = $adapter->select() ->from(['tur' => $this->getMainTable()], $this->getIdFieldName()) ->joinLeft( - ['tcp' => $this->getTable('catalog/category_product')], - 'tur.category_id = tcp.category_id AND tur.product_id = tcp.product_id', + ['ccei1' => $table], + 'ccei1.attribute_id = :is_active_category_attribute_id AND ccei1.store_id = 0 AND ccei1.entity_id = tur.category_id', [] ) + ->joinLeft( + ['ccei2' => $table], + 'ccei2.attribute_id = :is_active_category_attribute_id AND ccei2.store_id = :store_id AND ccei2.entity_id = tur.category_id', + [] + ) + ->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('tcp.category_id IS NULL'); - $rewriteIds = $adapter->fetchCol($select, ['store_id' => $storeId]); + ->where('tur.category_id = :category_id'); + + $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 = [$this->getIdFieldName() . ' IN(?)' => $rewriteIds]; $adapter->delete($this->getMainTable(), $where); @@ -1068,6 +1166,91 @@ 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(['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( + ['tcp' => $this->getTable('catalog/category_product')], + 'tur.category_id = tcp.category_id AND tur.product_id = tcp.product_id', + [] + ) + ->where('tcp.category_id IS NULL'); + } + } else { + // Find products, cartegories and cartegory/product rewrites for disabled products or cartegories + $productTable = $this->getTable(['catalog/product', 'int']); + $categoryTable = $this->getTable(['catalog/category', 'int']); + $select->joinLeft( + ['cpei' => $productTable], + 'cpei.entity_id = tur.product_id AND cpei.attribute_id = :product_status_attribute_id', + [] + ) + ->joinLeft( + ['ccei1' => $categoryTable], + 'ccei1.attribute_id = :is_active_category_attribute_id AND ccei1.store_id = 0 AND ccei1.entity_id = tur.category_id', + [] + ) + ->joinLeft( + ['ccei2' => $categoryTable], + 'ccei2.attribute_id = :is_active_category_attribute_id AND ccei2.store_id = :store_id AND ccei2.entity_id = tur.category_id', + [] + ); + $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( + ['tcp' => $this->getTable('catalog/category_product')], + 'tcp.category_id = tur.category_id AND tcp.product_id = tur.product_id', + [] + ); + // 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 e68b3ee259b..6911ca21f6b 100644 --- a/app/code/core/Mage/Catalog/Model/Url.php +++ b/app/code/core/Mage/Catalog/Model/Url.php @@ -36,6 +36,9 @@ class Mage_Catalog_Model_Url */ public const ALLOWED_REQUEST_PATH_OVERFLOW = 10; + public const XML_PATH_PRODUCT_USE_CATEGORIES = 'catalog/seo/product_use_categories'; + public const XML_PATH_CREATE_URL_FOR_DISABLED = 'catalog/seo/create_url_for_disabled'; + /** * Resource model * @@ -71,20 +74,6 @@ class Mage_Catalog_Model_Url */ protected $_rewrite; - /** - * Cache for product rewrite suffix - * - * @var array - */ - protected $_productUrlSuffix = []; - - /** - * Cache for category rewrite suffix - * - * @var array - */ - protected $_categoryUrlSuffix = []; - /** * Flag to overwrite config settings for Catalog URL rewrites history maintainance * @@ -238,7 +227,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; } @@ -364,7 +353,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 @@ -375,7 +364,7 @@ protected function _refreshCategoryProductRewrites(Varien_Object $category) $process = true; $lastEntityId = 0; $firstIteration = true; - while ($process == true) { + while ($process === true) { $products = $this->getResource()->getProductsByCategory($category, $lastEntityId); if (!$products) { if ($firstIteration) { @@ -419,19 +408,28 @@ protected function _refreshCategoryProductRewrites(Varien_Object $category) * @param bool $refreshProducts * @return $this */ - public function refreshCategoryRewrite($categoryId, $storeId = null, $refreshProducts = true) + public function refreshCategoryRewrite($categoryId, $storeId = null, $refreshProducts = null) { if (is_null($storeId)) { foreach ($this->getStores() as $store) { - $this->refreshCategoryRewrite($categoryId, $store->getId(), $refreshProducts); + $this->refreshCategoryRewrite($categoryId, $store->getId()); } return $this; } + if (is_null($refreshProducts)) { + $refreshProducts = Mage::getStoreConfigFlag(self::XML_PATH_PRODUCT_USE_CATEGORIES, $storeId); + } $category = $this->getResource()->getCategory($categoryId, $storeId); if (!$category) { return $this; } + $createForDisabled = Mage::getStoreConfigFlag(self::XML_PATH_CREATE_URL_FOR_DISABLED, $storeId); + + if (!$createForDisabled && !$category->getIsActive()) { + $this->getResource()->clearDisabledCategory($category->getId()); + return $this; + } // Load all childs and refresh all categories $category = $this->getResource()->loadCategoryChilds($category); @@ -466,35 +464,41 @@ public function refreshProductRewrite($productId, $storeId = null) } $product = $this->getResource()->getProduct($productId, $storeId); - if ($product) { - $store = $this->getStores($storeId); - $storeRootCategoryId = $store->getRootCategoryId(); + if (!$product) { + // Product doesn't belong to this store - clear all its url rewrites including root one + $this->getResource()->clearProductRewrites($productId, $storeId, []); + return $this; + } + $store = $this->getStores($storeId); + $storeRootCategoryId = $store->getRootCategoryId(); + + $this->_rewrites = $this->getResource()->prepareRewrites($storeId, '', $productId); + + $categories = []; + if (Mage::getStoreConfigFlag(self::XML_PATH_PRODUCT_USE_CATEGORIES, $storeId)) { // List of categories the product is assigned to, filtered by being within the store's categories root $categories = $this->getResource()->getCategories($product->getCategoryIds(), $storeId); - $this->_rewrites = $this->getResource()->prepareRewrites($storeId, '', $productId); + } - // Add rewrites for all needed categories - // If product is assigned to any of store's categories - - // we also should use store root category to create root product url rewrite - if (!isset($categories[$storeRootCategoryId])) { - $categories[$storeRootCategoryId] = $this->getResource()->getCategory($storeRootCategoryId, $storeId); - } + // Add rewrites for all needed categories + // If product is assigned to any of store's categories - + // we also should use store root category to create root product url rewrite + if (!isset($categories[$storeRootCategoryId])) { + $categories[$storeRootCategoryId] = $this->getResource()->getCategory($storeRootCategoryId, $storeId); + } - // Create product url rewrites - foreach ($categories as $category) { - $this->_refreshProductRewrite($product, $category); - } + // Create product url rewrites + foreach ($categories as $category) { + $this->_refreshProductRewrite($product, $category); + } - // Remove all other product rewrites created earlier for this store - they're invalid now - $excludeCategoryIds = array_keys($categories); - $this->getResource()->clearProductRewrites($productId, $storeId, $excludeCategoryIds); + // Remove all other product rewrites created earlier for this store - they're invalid now + $excludeCategoryIds = array_keys($categories); - unset($categories); - unset($product); - } else { - // Product doesn't belong to this store - clear all its url rewrites including root one - $this->getResource()->clearProductRewrites($productId, $storeId, []); + // Product is disabled and in configuration set to not create for disabled - clear all its url rewrites including root one + if ($product->getStatus() === Mage_Catalog_Model_Product_Status::STATUS_DISABLED) { + $excludeCategoryIds = []; } return $this; @@ -512,36 +516,42 @@ public function refreshProductRewrites($storeId) $storeRootCategoryId = $this->getStores($storeId)->getRootCategoryId(); $storeRootCategoryPath = $this->getStores($storeId)->getRootCategoryPath(); $this->_categories[$storeRootCategoryId] = $this->getResource()->getCategory($storeRootCategoryId, $storeId); + $productUseCategories = Mage::getStoreConfigFlag(self::XML_PATH_PRODUCT_USE_CATEGORIES, $storeId); + $createForDisabled = Mage::getStoreConfigFlag(self::XML_PATH_CREATE_URL_FOR_DISABLED, $storeId); $lastEntityId = 0; - $process = true; - while ($process == true) { - $products = $this->getResource()->getProductsByStore($storeId, $lastEntityId); + while (true) { + $products = $this->getResource()->getProductsByStore($storeId, $lastEntityId, $createForDisabled); + if (!$products) { - $process = false; break; } $this->_rewrites = $this->getResource()->prepareRewrites($storeId, false, array_keys($products)); $loadCategories = []; - foreach ($products as $product) { - foreach ($product->getCategoryIds() as $categoryId) { - if (!isset($this->_categories[$categoryId])) { - $loadCategories[$categoryId] = $categoryId; + + if ($productUseCategories) { + 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) { + foreach ($this->getResource()->getCategories($loadCategories, $storeId, $createForDisabled) as $category) { $this->_categories[$category->getId()] = $category; } } + } - foreach ($products as $product) { - $this->_refreshProductRewrite($product, $this->_categories[$storeRootCategoryId]); + foreach ($products as $product) { + $this->_refreshProductRewrite($product, $this->_categories[$storeRootCategoryId]); + if ($productUseCategories) { foreach ($product->getCategoryIds() as $categoryId) { if ($categoryId != $storeRootCategoryId && isset($this->_categories[$categoryId])) { if (strpos($this->_categories[$categoryId]['path'], $storeRootCategoryPath . '/') !== 0) { @@ -574,6 +584,7 @@ public function clearStoreInvalidRewrites($storeId = null) } return $this; } + $createForDisabled = Mage::getStoreConfigFlag(self::XML_PATH_CREATE_URL_FOR_DISABLED, $storeId); $this->getResource()->clearStoreInvalidRewrites($storeId); return $this; @@ -974,6 +985,7 @@ protected function _saveRewriteHistory($rewriteData, $rewrite) $rewriteData['options'] = 'RP'; // Redirect = Permanent $this->getResource()->saveRewriteHistory($rewriteData); } + $this->getResource()->clearProductRewrites($productId, $storeId); return $this; } diff --git a/app/code/core/Mage/Catalog/etc/config.xml b/app/code/core/Mage/Catalog/etc/config.xml index 61cfb611821..fb292685d90 100644 --- a/app/code/core/Mage/Catalog/etc/config.xml +++ b/app/code/core/Mage/Catalog/etc/config.xml @@ -803,6 +803,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 3b099086c8b..1888e50ddda 100644 --- a/app/code/core/Mage/Catalog/etc/system.xml +++ b/app/code/core/Mage/Catalog/etc/system.xml @@ -265,6 +265,16 @@ 1 1 + + + select + adminhtml/system_config_source_yesno + adminhtml/system_config_backend_seo + 4 + 1 + 1 + 1 + select diff --git a/phpstan.dist.baseline.neon b/phpstan.dist.baseline.neon index 8a1e7f903af..188d240e82e 100644 --- a/phpstan.dist.baseline.neon +++ b/phpstan.dist.baseline.neon @@ -1915,16 +1915,6 @@ parameters: count: 1 path: app/code/core/Mage/Catalog/Model/Resource/Product/Link/Product/Collection.php - - - message: "#^Variable \\$category might not be defined\\.$#" - count: 1 - path: app/code/core/Mage/Catalog/Model/Resource/Url.php - - - - message: "#^Loose comparison using \\=\\= between true and true will always evaluate to true\\.$#" - count: 2 - path: app/code/core/Mage/Catalog/Model/Url.php - - message: "#^Property Mage_Catalog_Model_Url\\:\\:\\$_saveRewritesHistory \\(bool\\) on left side of \\?\\? is not nullable\\.$#" count: 1