I am currently developing a module working with the product edit in the backend. Its purpose is to retrieve categories the product belongs to and populate an attribute (the Brand attribute) with the list of selected categories.
It is mandatory for the admin to select at least one category.
My module works as expected except that I don't know how to stop the saving process if the admin hasn't selected any category while editing a product.
Here is the workflow
--> If there are selected categories
--> Else
The generic question would maybe be : how to pass a "stop save" argument to an observer ?
Here are a sample of my config.xml file and the method that deals with the workflow I explained above.
Thanks a lot for your help and have fun Magentoing !
config.xml
<catalog_product_prepare_save>
<observers>
<brands_product_save_observer>
<type>singleton</type>
<class>brands/observer</class>
<method>saveProductBrand</method>
</brands_product_save_observer>
</observers>
</catalog_product_prepare_save>
Observer.php
public function saveProductBrand($observer) {
$product = $observer->getProduct();
$categoryIds = $product->getCategoryIds();
if (isset($categoryIds)) {
foreach ($categoryIds as $categoryId) {
$isBrandCategory = Mage::getModel('brands/navigation')->isBrandCategory($categoryId);
if ($isBrandCategory)
$brandCategories[] = $categoryId;
}
if (isset($brandCategories)) {
$brandId = Mage::getModel('brands/navigation')->getBrand($brandCategories[0]);
if ($brandId) {
$attribute = Mage::getModel('eav/config')->getAttribute('catalog_product', 140);
foreach ($attribute->getSource()->getAllOptions(true, true) as $option) {
$attributeArray[$option['label']] = $option['value'];
}
$categoryName = Mage::getModel('catalog/category')->load($brandId)->getName();
$product->setData('brand', $attributeArray[$categoryName]);
}
} else {
Mage::getSingleton('adminhtml/session')->addError(Mage::helper('catalog')->__('Please add this product to a brand in the "Categories" tab.'));
HERE SOME CODE TO TELL MAGENTO TO STOP SAVING THE PRODUCT
return;
}
}
}
It's always a crap shoot as to which sections of Magento support this, but throwing an exception is often the prescribed way of telling Magento that something went wrong. The layers higher up the stack are set to catch these exceptions and use them to go back to the form and display an error message. Give this a try
Mage::throwException(Mage::helper('adminhtml')->__('You totally failed at that.'));
If you take a look at the Adminhtml
module's Catalog/ProductController.php
(1.5, but I'd assume a similar format in previous versions)
function saveAction()
{
...
$product = $this->_initProductSave();
try {
$product->save();
$productId = $product->getId();
...
}
The _initProductSave
method is where the catalog_product_prepare_save
event is fired. Since this is outside the saveAction
's try/catch block, the exception won't be caught (as described in the comments below).
You'll need to move you validation code into the product model's before save event (catalog_product_save_before
). Doing that should let you throw an exception and have the admin display the error message and represent the form for editing.