Question

I am using Magento Enterprise Edition 1.13.1.0 Running Multiple Store in Following Order:

  • Store 1:
    1. English
    1. Français
  • Store 2:
    1. English
    1. Français
  • Store 3:
    1. English
    1. Français
  • Main Store:
    1. Default Store View

We have multiple categories setup on Default Scope and change their status on each specific store.

The problem is occasionally we get some random numbers added to category URL_KEYS.

We have checked for duplicate url_key+store_id and duplicate request_path+store_id but there are none.

The problem does get resolve if we clear the enterprise_url_rewrite and run reindex, but after some time the issue appears again. So we would like to see a permanent solution to this problem.

There are couple of similar problems available here but they are related to Community Edition, and since EE uses a separate module for URL Rewrites those solutions appear to have no affect.

AFAIK below are the 2 functions which handle URL rewrites and adding numbers to them in Enterprise Edition

Enterprise_Catalog_Model_Index_Action_Url_Rewrite_Category_Refresh > _reindexCategoryUrlKey

protected function _reindexCategoryUrlKey(Mage_Catalog_Model_Category $category, Mage_Core_Model_Store $store)
{
    $requestPath = trim($category->getParentUrl(), '/');
    $requestPath = (!empty($requestPath) ? $requestPath . '/' : '') . $category->getUrlKey();
    $requestPath = $this->_cutRequestPath($requestPath);
    $urlKeyValue = $this->_getUrlKeyAttributeValueId($category, $store);
    /*
     * if this category created on store view level, we should write default url key for this category,
     * or this category will be unaccessible from frontend
     */
    if (empty($urlKeyValue) && empty($urlKeyValue['value_id'])) {
        $category = $this->_setUrlKeyForDefaultStore($category, $store);
        //get url key value id from backend table after changes
        $urlKeyValue = $this->_getUrlKeyAttributeValueId($category, $store);
    }
    $valueId = $urlKeyValue['value_id'];

    /**
     * Check if we should insert rewrite into table
     */
    $rewriteRow = $this->_getRewrite($requestPath, $store->getId());
    if (!$rewriteRow || $rewriteRow['value_id'] != $valueId) {
        //get current url path from enterprise_url_rewrite
        $rewriteForValueId = $this->_getRewriteForValueId($store->getId(), $valueId);
        $suffix = trim(str_replace($requestPath, '', $category->getRequestPath()), '-');
        /*
         * theoretically we may face with situation when several categories have url_key like:
         * id url_key request path
         * 1  abc     abc
         * 2  abc     abc-1
         * 3  abc     abc-2
         * and we should reindex category with id 2, we can't be sure should we add prefix or not
         * so workaround with regexp cover most cases of this problem
         */
        /*
        $requestPathIncrement = (int) $this->_getRewriteRequestIncrement($requestPath, $store);
        if (!$rewriteForValueId || !preg_match('#^(\d)+$#', $suffix) || ($suffix > $requestPathIncrement)) {
            if ($rewriteRow && $rewriteRow['value_id'] != $valueId) {
                $requestPath .= '-' . ++$requestPathIncrement;
            }
            $category = $this->_saveRewrite($category, $store, $requestPath, $valueId);
            // clean full page cache for category
        }
        */
    }
    // save id of already indexed category into list
    $this->_indexedCategoryIds[$store->getId()][$category->getId()] = 1;

    return $category;
} // _reindexCategoryUrlKey

Enterprise_Catalog_Model_Index_Action_Url_Rewrite_Category_Refresh > _getRewriteRequestIncrement

protected function _getRewriteRequestIncrement($urlPath, Mage_Core_Model_Store $store)
{
    // match request_url abcdef1234(-12)(.html) pattern
    $match = array();
    $regularExpression = '#^([0-9a-z/-]+)(-([0-9]+))?$#i';
    preg_match($regularExpression, $urlPath, $match);
    $match[1] = $match[1] . '-';
    $match[4] = isset($match[4]) ? $match[4] : '';
    $prefix = $match[1];

    $requestPathField = new Zend_Db_Expr($this->_connection->quoteIdentifier('request_path'));
    //select increment part of request path and cast expression to integer
    $urlIncrementPartExpression = $this->_eavHelper->getCastToIntExpression(
        $this->_connection->getSubstringSql(
            $requestPathField,
            strlen($prefix) + 1,
            $this->_connection->getLengthSql($requestPathField) . ' - ' . strlen($prefix)
        )
    );

    $select = $this->_connection->select()
        ->from(
            $this->_getTable('enterprise_urlrewrite/url_rewrite'),
            new Zend_Db_Expr('MAX(' . $urlIncrementPartExpression . ')')
        )
        ->where('entity_type = :entity_type')
        ->where('store_id = :store_id')
        ->where('request_path LIKE :request_path')
        ->where(
            $this->_connection->prepareSqlCondition(
                'request_path',
                array(
                    'regexp' => '^' . preg_quote($prefix) . '[0-9]*$',
                )
            )
        );
    $bind = array(
        'store_id'=> (int) $store->getId(),
        'request_path' => $prefix . '%',
        'entity_type' => Enterprise_Catalog_Model_Category::URL_REWRITE_ENTITY_TYPE,
    );

    return (int)$this->_connection->fetchOne($select, $bind);
} // _getRewriteRequestIncrement

So I went ahead and overridden these but still not sure which line of code to modify to fix this issue.

Kindly feel free to ask if you need more information, Any help would be highly appreciated.

Thank You, Z

Was it helpful?

Solution

It turns out there is some nasty bug in EE 1.13 when stores with different language and same url keys exist.

I was unable to find the root cause of this issue but here is my solution:

I overriden the Enterprise_Catalog_Model_Index_Action_Url_Rewrite_Category_Refresh class in a custom module and than modified _reindexCategoryUrlKey as follows

protected function _reindexCategoryUrlKey(Mage_Catalog_Model_Category $category, Mage_Core_Model_Store $store)
{
    $requestPath = trim($category->getParentUrl(), '/');
    $requestPath = (!empty($requestPath) ? $requestPath . '/' : '') . $category->getUrlKey();
    $requestPath = $this->_cutRequestPath($requestPath);
    $urlKeyValue = $this->_getUrlKeyAttributeValueId($category, $store);
    /*
     * if this category created on store view level, we should write default url key for this category,
     * or this category will be unaccessible from frontend
     */
    if (empty($urlKeyValue) && empty($urlKeyValue['value_id'])) {
        $category = $this->_setUrlKeyForDefaultStore($category, $store);
        //get url key value id from backend table after changes
        $urlKeyValue = $this->_getUrlKeyAttributeValueId($category, $store);
    }
    $valueId = $urlKeyValue['value_id'];

    /**
     * Check if we should insert rewrite into table
     */
    $rewriteRow = $this->_getRewrite($requestPath, $store->getId());
    if (!$rewriteRow || $rewriteRow['value_id'] != $valueId) {
        //get current url path from enterprise_url_rewrite
        $rewriteForValueId = $this->_getRewriteForValueId($store->getId(), $valueId);
        $suffix = trim(str_replace($requestPath, '', $category->getRequestPath()), '-');

        $requestPathIncrement = (int)$this->_getRewriteRequestIncrement($requestPath, $store);
        if (!$rewriteForValueId || !preg_match('#^(\d)+$#', $suffix) || ($suffix > $requestPathIncrement)) {
            if ($rewriteRow && $rewriteRow['value_id'] != $valueId) {
                /*
                 * disabled request path increment here
                 * skip URL Rewrite if URL_KEY is same.
                 */
            } else {
                $category = $this->_saveRewrite($category, $store, $requestPath, $valueId);
            }
        }
    }
    // save id of already indexed category into list
    $this->_indexedCategoryIds[$store->getId()][$category->getId()] = 1;

    return $category;
} // _reindexCategoryUrlKey

as you will notice, i modified below part of the function:

 if ($rewriteRow && $rewriteRow['value_id'] != $valueId) {
                    $requestPath .= '-' . ++$requestPathIncrement;
                }
                $category = $this->_saveRewrite($category, $store, $requestPath, $valueId);

with this:

if ($rewriteRow && $rewriteRow['value_id'] != $valueId) {
                /*
                 * disabled request path increment here
                 * skip URL Rewrite if URL_KEY is same.
                 */
            } else {
                $category = $this->_saveRewrite($category, $store, $requestPath, $valueId);
            }

then i cleared enterprise_url_rewrites table and run reindex. Now everything appears to be working fine.

Note: This solution has its own limitations i.e. if you create a duplicate url_key only the first category will work, you will need to update url_key of newer category to be different in order for them to visible on frontend.

Thank You

Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top