Skip to content

Instantly share code, notes, and snippets.

@mshmsh5000
Created August 23, 2012 18:52
Show Gist options
  • Save mshmsh5000/3440260 to your computer and use it in GitHub Desktop.
Save mshmsh5000/3440260 to your computer and use it in GitHub Desktop.
Magento fix for parse_str() bug in CategoryController
/**
* Addresses this bug: http://www.magentocommerce.com/bug-tracking/issue/?issue=13203
*
* See app/code/core/Mage/Adminhtml/controllers/Catalog/CategoryController.php
* Mage_Adminhtml_Catalog_CategoryController::saveAction(), starting around
* line 307
*/
if (isset($data['category_products']) &&
!$category->getProductsReadonly()) {
$products = array();
// This can be a massive request -- i.e., all product IDs in this category.
// So we need to step through this instead of calling parse_str(), which can
// run up against the max_input_vars limit.
// parse_str($data['category_products'], $products);
$cat_products_split = explode('&', $data['category_products']);
foreach($cat_products_split as $row)
{
$arr = array();
// This will always work.
parse_str($row, $arr);
list($k, $v) = each($arr);
if (!empty($k) && !empty($v))
{
$products[$k] = $v;
}
}
if (!empty($products))
{
$category->setPostedProducts($products);
}
}
@bannostookaylo
Copy link

I'm not sure why but this chunk of code doesn't seem to work for me on Magento 1.7.0.2 ... I wish I could figure out how to debug it for you to get you further details.

@bannostookaylo
Copy link

Just a heads up this code worked

        if (isset($data['category_products']) && !$category->getProductsReadonly()) {
            $products = array();

            $records = preg_split('/&/',$data['category_products'],-1,PREG_SPLIT_NO_EMPTY);
            if(count($records) > 0){
                foreach($records as $record){
                    $record = trim($record);
                    if(preg_match('/([0-9]*)=([0-9]*)/',$record,$matches)){
                        $products[$matches[1]] = $matches[2];
                    }
                }
            }

            $category->setPostedProducts($products);
        }

@emrahuyanik
Copy link

ts magento bug.in php.ini file, set
max_input_vars =10000

parse_str function can not parse an array above this number, and its "1000" at default configuration.

@Maksold
Copy link

Maksold commented Feb 26, 2014

Better is to use observer event "catalog_category_prepare_save".

        /**
         * Fix bug with saving only first 1000 products in a category
         * It's related to default php config 'max_input_vars' = 1000
         *
         * @param Varien_Event_Observer $observer
         */
         public function onCatalogCategoryPrepareSave(Varien_Event_Observer $observer)
         {
             $phpDefaultMaxInputVars = (int)ini_get('max_input_vars');
            /** @var Mage_Core_Controller_Request_Http $request */
            $request = $observer->getRequest();
            $dataProducts = $request->getPost('category_products');
            $dataProducts = preg_split('/&/', $dataProducts, -1, PREG_SPLIT_NO_EMPTY);
            /** @var Mage_Catalog_Model_Category $category */
            $category = $observer->getCategory();

            if ($dataProducts && !$category->getProductsReadonly() && count($dataProducts) > $phpDefaultMaxInputVars) {
                $products = array();
                foreach ($dataProducts as $_product) {
                    $_product = trim($_product);
                    if (preg_match('/([0-9]*)=([\-]?[0-9]*)/', $_product, $matches)) {
                        $products[$matches[1]] = $matches[2];
                    }
                }
                $category->setPostedProducts($products);
            }
        }

@profago
Copy link

profago commented Jul 18, 2014

I'm using Magento 1.8 and I have solved the problem with a modification in

app/code/core/Mage/Adminhtml/controllers/Catalog/CategoryController.php

changing parse_str($data['category_products'], $products);

to:

            $cat_products_split = explode('&', $data['category_products']);
            foreach($cat_products_split as $row) {
            $arr = array();
            parse_str($row, $arr); //This will always work
            list($k, $v) = each($arr);
            if (!empty($k)) {
            $products[$k] = $v;
            }
            }

now it works fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment