Magento – Change updated_at date on mass action

magento-1massaction

If I change multiple attributes of many products via mass action, the updated_at date of the products is not changed.

Why does it not change and how would you implement it? Observer?

Best Answer

Good question. I didn't notice this before.
The updated_at date does not change because the updated_at attribute has a backend model that updates the value Mage_Eav_Model_Entity_Attribute_Backend_Time_Updated. The value gets updated only when you call save on the product, because that's the only time the backend models for the attributes come into play.

There are some events dispatched in the mass update process. I think you have to observe all of them:
This one should be the easiest: catalog_product_attribute_update_before.
It is dispatched in Mage_Catalog_Model_Product_Action::updateAttributes. That method is called when updating the attributes.

The idea is to add the update_at in the attributes update list.
Your observer method could looks like this:

public function beforeUpdateAttributes($observer) 
{
    //the attributes data array is passed by reference
    $attributesData = $observer->getEvent()->getAttributesData();
    //add updated at
    $attributesData['updated_at'] = Varien_Date::now();
}

But now a problem.
If you only change a website or the stock data for the products this event never gets dispatched because Mage_Catalog_Model_Product_Action::updateAttributes does not get called.
Instead you can use these events:
catalog_product_stock_item_mass_change - for stock change.
catalog_product_to_website_change - for website change.
honestly I don't know if you should even update updated_at attribute the product if you change only the stock or a website, because technically you are not changing the product entity. You are just changing some related entities.
But in case you want to change updated_at in this case also, your observer for both of these events could look like this:

public function updateUpdatedAt($observer) 
{
    $productIds = $observer->getEvent()->getProducts();
    Mage::getSingleton('catalog/product_action')->updateAttributes(
        $productIds,
        array('updated_at' => Varien_Date::now()),
        0
    );
}

my code is not perfect. It has an issue. If you change some attributes in mass action AND the stock, the event catalog_product_attribute_update_before would be triggered twice. Once by the Mage_Catalog_Model_Product_Action::updateAttributes method and once by your observer for catalog_product_stock_item_mass_change.
To avoid this you should make your observer as a singleton and remember the product ids you already updated to avoid duplicate sql queries that have the same result.
The code would work even if you update a product twice, but it might be a bit slower.