Pages

Sunday, June 30, 2013

Programmatically create Shopping Cart Price Rules with Conditions and Actions

Rather than going into detail of creating the Shopping Cart Price Rule from scratch, this post is specifically about conditions and actions.



If you have ever needed to programmatically create Magento Shopping Cart Price Rules, then you may have wondered how you attach conditions and actions.

Prior to saving your Mage_Salesrule_Model_Rule object, you will need to assign the following data:

<?php
    $rule->setData('actions',$actions);       
    $rule->setData('conditions',$conditions);
?>

Where $actions and $conditions are Array’s of a very specific format.

We then call Mage_Salesrule_Model_Rule::loadPost():

<?php
    $rule->loadPost($rule->getData());
?>

The format that is required for conditions and actions is significantly outside Magento’s EAV model, and is not documented as far as I can see. So to find it out we are required to trace it a little further.

Conditions and actions are processed within the Mage_Salesrule_Model_Rule::loadPost() function, and are converted to a recursive format that you find serialized in the database as conditions_serialized and actions_serialized table columns. This is done via Mage_Rule_Model_Rule::_convertFlatToRecursive() which is called within Mage_Salesrule_Model_Rule::loadPost().

But I digress, a little. What this means for us is that we need to put our data in a specific format prior to saving. I’ve established that format for you below. If you hijack Mage_Salesrule_Model_Rule::loadPost() and print_r() the content of a rule as it’s being saved, you’ll see the format:


    [conditions] => Array
        (
            [1] => Array
                (
                    [type] => salesrule/rule_condition_combine
                    [aggregator] => all
                    [value] => 1
                    [new_child] =>
                )
            [1--1] => Array
                (
                    [type] => salesrule/rule_condition_product_found
                    [value] => 1
                    [aggregator] => all
                    [new_child] =>
                )
            [1--1--1] => Array
                (
                    [type] => salesrule/rule_condition_product
                    [attribute] => sku
                    [operator] => ==
                    [value] => SKU123
                )
        )

    [actions] => Array
        (
            [1] => Array
                (
                    [type] => salesrule/rule_condition_product_combine
                    [aggregator] => all
                    [value] => 1
                    [new_child] =>
                )
            [1--1] => Array
                (
                    [type] => salesrule/rule_condition_product
                    [attribute] => sku
                    [operator] => ==
                    [value] => SKU123
                )
        )

In Layman’s terms, this is saying:


    [conditions][1]        
        "If ALL(aggregator) of these conditions are TRUE(value)"
    [conditions][1--1]     
        "If an item is FOUND(type, value) with ALL(aggregator) of these conditions true"
    [conditions][1--1--1]  
        "SKU(attribute) is(operator) SKU123(value)"
   
    [actions][1]           
        "if ALL(aggregator) of these conditions are TRUE(value)"
    [actions][1--1]        
        "SKU(attribute) is(operator) SKU123(value)"

So what are we really looking at? We’re looking at an array of arrays that uses the array keys to establish the heirarchy. The array keys are exploded by “--” in Mage_Rule_Model_Rule::_convertFlatToRecursive() and are converted to recursive arrays before being stored in the database.

This is how we can write it:

<?php
    $rule = Mage::getModel('salesrule/rule')->load($my_rule_id);
    $conditions = array(
        "1"         => array(
                "type"          => "salesrule/rule_condition_combine",
                "aggregator"    => "all",
                "value"         => "1",
                "new_child"     => null
            ),
        "1--1"      => array(
                "type"          => "salesrule/rule_condition_product_found",
                "aggregator"    => "all",
                "value"         => "1",
                "new_child"     => null
            ),
        "1--1--1"   => array(
                "type"          => "salesrule/rule_condition_product",
                "attribute"     => "sku",
                "operator"      => "==",
                "value"         => "SKU123"
            )
    );
    $actions = array(
        "1"         => array(
                "type"          => "salesrule/rule_condition_product",
                "aggregator"    => "all",
                "value"         => "1",
                "new_child"     => false
            ),
        "1--1"      => array(
                "type"          => "salesrule/rule_condition_product",
                "attribute"     => "sku",
                "operator"      => "==",
                "value"         => "SKU123"
            )
    );
    $rule->setData("conditions",$conditions);
    $rule->setData("actions",$actions);
    $rule->loadPost($rule->getData());
    $rule->save();
?>

No comments:

Post a Comment