I’ve previously posted here about the complexities involved in Magento Salesrules and Coupon codes. While I don’t like the way Magento Rules are designed, I still have to work with them.
I put together a little module this morning because I needed to clone a coupon code, and I couldn’t find any native support to get this done.
For the lazy, I’ve put together the files required to get this functioning.
Download Mby_Rules.zip
Tested on EE 1.11.
For those of you interested in how this works, have a look at my run-down of conditions/actions first. Then, basically, I have extended the Mage_Salesrule_Model_Rule class and added some extra functions. Here’s the extended class, with minimal notes:
<?php class Mby_Rules_Model_Salesrule extends Mage_SalesRule_Model_Rule { /** * Makes a clone of a coupon code. Returns false if desired coupon code already exists. * * Usage: $salesrule = Mage::getModel("salesrule/rule")->load($ruleId); if ($clone = $salesrule->makeClone("NEWCOUPONCODE")) { // Work with $clone } else { // Coupon code already exists. } * * @param string $couponCode the desired code for the cloned coupon. * return bool || Mby_Rules_Model_Salesrule */ public function makeClone($couponCode) { // Ensure no coupon code double up $rules = Mage::getModel("salesrule/rule")->getCollection()->addFieldToFilter('code', $couponCode); foreach ($rules as $rule) { return false; } $parentData = $this->getData(); // Assign desired code $parentData['coupon_code'] = $couponCode; // Flatten conditions and actions $flatConditions = $this->_flatten('conditions', $parentData); $flatActions = $this->_flatten('actions', $parentData); // Unset unnecessary data unset($parentData['rule_id']); unset($parentData['conditions_serialized']); unset($parentData['actions_serialized']); // Init clone and assign data $clone = Mage::getModel("salesrule/rule")->setData($parentData)->save(); $clone->setData('conditions', $flatConditions); $clone->setData('actions', $flatActions); // Setup data and finalise before save $cloneData = $clone->getData(); if ($cloneData['from_date'] == "NULL") unset($cloneData['from_date']); if ($cloneData['to_date'] == "NULL") unset($cloneData['to_date']); $clone->loadPost($cloneData); $clone->save(); return $clone; } /** * Sets up data and returns flattened data * @param string $type Must be "actions" or "conditions" * @param array $parentData Full data from the parent code. * return array */ protected function _flatten($type, $parentData) { $unserialized = unserialize($parentData[$type.'_serialized']); $flatData = array(); $this->_convertRecursiveToFlat("1", $unserialized, $flatData); ksort($flatData); return $flatData; } /** * Reverse of Mage_Rule_Model_Rule::_convertFlatToRecursive * Takes recursive Array and makes it flat again. * @param string $finalKey the key of $conditions in the final flat array * @param array $conditions a condition to insert * @param array &$finalContainer the final array to end up flattened * return void */ protected function _convertRecursiveToFlat($finalKey, array $conditions, array &$finalContainer = array()) { foreach ($conditions['conditions'] as $key => $subconditions) { $this->_convertRecursiveToFlat($finalKey."--".($key+1), $subconditions, $finalContainer); } unset($conditions['is_value_processed']); unset($conditions['conditions']); $finalContainer[$finalKey] = $conditions; return; } }