Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Class hierarchy of Shopping Cart Price Rules

Class Mage_SalesRule_Model_Validator has an object of salesrule/rule_collection, and that object calls a function validate of class Mage_SalesRule_Model_Rule_Condition_Product_Found, what I didn't understand is how the object of salesrule/rule_collection is related to Found class, and if we add any other function to this class and try to access it will throw an Exception Undefined Function, I just want to understand whats going on behind the scenes

Mage_SalesRule_Model_Rule_Condition_Product_Found extends the class Mage_SalesRule_Model_Rule_Condition_Product_Combine but when from process function of the Mage_SalesRule_Model_Validator called it calls the validate function of the Found class Mage_SalesRule_Model_Validator object call to process

try {
   $validator = Mage::getModel('module/validator')
                    ->init($customer->getWebsiteId(), $customerGroupId);
} catch (Exception $e) {
   Mage::log('Exception: ' . $e . ' in ' . __CLASS__ . ' on ' . __LINE__);
}
$v  = $validator->process($quote);

And the process function of Mage_SalesRule_Model_Validator which calls the validate function of Found class

public function process($_quote) 
{
         $quote           = $_quote;
         $customerSession = Mage::getSingleton('customer/session');
         foreach ($this->_rules as $rule) {

            if ($rule->getIsValid() === false) {
              continue;
            }
            if ($rule->getIsValid() !== true) { 
                $rule->afterLoad();
                if (!$rule->validate($quote)) { // quote does not meet rule's conditions , //Call Found.php
                $rule->setIsValid(false);
                continue;
                }
                $rule->setIsValid(true); // passed all validations, remember to be valid
            }
    }
    return $this;
}

And the validate function of Found class

   public function validate(Varien_Object $object) 
   {
//Called form Validator.php
    $all       = $this->getAggregator() === 'all';
    $true      = (bool)$this->getValue();
    $found     = false;

    $Count =  count($object->getAllItems()); 
    $i = 0;
    foreach ($object->getAllItems() as $item) {
        $found = $all ? true : false;
        foreach ($this->getConditions() as $cond) {

            $validated = $cond->validate($item); // Call to Product.php's function 'validate'

            if($validated) {
                $this->_ProductId[] = $item->getProductId();
            }

            if($i == $Count) {
                if ($all && !$validated) {
                $found = false;
                break;
                } elseif (!$all && $validated) {
                $found = true;
                break 2;
                }
            }

                }
            if($i == $Count) {
            if ($found && $true) {
                break;
            }
            }
            $i = $i + 1;
        }
    return false;
}

Now what I didn't understand is if I write any other function in Found class let it be public function Foo() and try to call it from process function of class Validator like

    $rule->Foo();

it will throw an Exception Undefined Function I just want to know the reason why I can't write any function in Found class and call like process Thanks

like image 402
Ahmed Avatar asked Jan 28 '14 04:01

Ahmed


1 Answers

Magento's core developers sometimes like to use additional abstraction that makes things a bit more difficult to see. Why? maybe they intended to develop this section further, maybe they thought it makes it even easier to override, one thing is certain they didn't think of the cost associated with complexity.

The whole salesrule module is broken down to many many subclasses of which each individual class holds a unique piece of logic. The core logic actually lies within that main file you were looking at: Mage_SalesRule_Model_Validator inside the process() method.

The line you are referring to is 294 in the code, which is inside a loop of all the rules applied to the specific quote item (a quote item is essentially a product that was added to the shopping cart and converted to hold additional meta data).

    if (!$rule->getActions()->validate($item)) {
        continue;
    }

So here they are using same strategy as within the product and product types. You got a rule as a general model and a bunch of sibling classes that each hold unique logic. The Found/Combine/Subselect child classes of a rule (which help facilitate the logic of AND/OR and combo rules with priorities). Here is the kicker: A Rule in Magento was abstracted to its own unique module. Take a look at Mage_Rule module - that is probably where you will find all the missing pieces.

I hope this helps a bit.

like image 114
Ron Avatar answered Oct 12 '22 17:10

Ron