Actually, by default Magento does verify the user input for custom options not only via JS - else your shop would be at huge risk of falling for XSS and what not all.
This validation is happening on multiple levels, for example, for text input at Mage_Catalog_Model_Product_Option_Type_Default::validateUserValue()
and Mage_Catalog_Model_Product_Option_Type_Text::validateUserValue()
- i.e.
/**
* Validate user input for option
*
* @throws Mage_Core_Exception
* @param array $values All product option values, i.e. array (option_id => mixed, option_id => mixed...)
* @return Mage_Catalog_Model_Product_Option_Type_Default
*/
public function validateUserValue($values)
{
Mage::getSingleton('checkout/session')->setUseNotice(false);
$this->setIsValid(false);
$option = $this->getOption();
if (!isset($values[$option->getId()]) && $option->getIsRequire() && !$this->getSkipCheckRequiredOption()) {
Mage::throwException(Mage::helper('catalog')->__('Please specify the product required option(s).'));
} elseif (isset($values[$option->getId()])) {
$this->setUserValue($values[$option->getId()]);
$this->setIsValid(true);
}
return $this;
}
Hover, even if you bypass these checks you may add the item to the quote, however, in cart you then will be see a messages such as "* The product has required options" disallowing you to continue to checkout.
Since this validation seems not to apply to your store I assume you got some third party/custom module installed in your shop that is preventing Magento from running all its validations. This may be related to an extended custom option's based calculation module or something similar.
Now, assuming that it is not possible to change the given logic for what ever reason (even though I highly recommend you to first of all try to figure out why the default server-side validation is not working for you) you can go the most dirty way (since applying a bad workaround on a bug isn't the best thing to do) you could simply do a check in the mentioned addAction()
like so:
$options = $product->getOptions();
foreach($options as $option) {
$optionData = $option->getData();
if($optionData['is_require']) {
// ...
}
}
Yet, this will just help you at the time of adding the product to cart but not when you update a product from cart.
A better approach (still, not good, but better than above one) is to use observers to check certain conditions when a product is added to cart using the events such as controller_action_predispatch_checkout_cart_add
(some similar event might be needed for when the product is updated). Further references on this can be found here: