*/ class Mage_CatalogRule_Model_Rule extends Mage_Rule_Model_Abstract { /** * Related cache types config path */ const XML_NODE_RELATED_CACHE = 'global/catalogrule/related_cache_types'; /** * Prefix of model events names * * @var string */ protected $_eventPrefix = 'catalogrule_rule'; /** * Parameter name in event * * In observe method you can use $observer->getEvent()->getRule() in this case * * @var string */ protected $_eventObject = 'rule'; /** * Store matched product Ids * * @var array */ protected $_productIds; /** * Limitation for products collection * * @var int|array|null */ protected $_productsFilter = null; /** * Store current date at "Y-m-d H:i:s" format * * @var string */ protected $_now; /** * Cached data of prices calculated by price rules * * @var array */ protected static $_priceRulesData = array(); /** * Init resource model and id field */ protected function _construct() { parent::_construct(); $this->_init('catalogrule/rule'); $this->setIdFieldName('rule_id'); } /** * Getter for rule conditions collection * * @return Mage_CatalogRule_Model_Rule_Condition_Combine */ public function getConditionsInstance() { return Mage::getModel('catalogrule/rule_condition_combine'); } /** * Getter for rule actions collection * * @return Mage_CatalogRule_Model_Rule_Action_Collection */ public function getActionsInstance() { return Mage::getModel('catalogrule/rule_action_collection'); } /** * Get catalog rule customer group Ids * * @return array */ public function getCustomerGroupIds() { if (!$this->hasCustomerGroupIds()) { $customerGroupIds = $this->_getResource()->getCustomerGroupIds($this->getId()); $this->setData('customer_group_ids', (array)$customerGroupIds); } return $this->_getData('customer_group_ids'); } /** * Retrieve current date for current rule * * @return string */ public function getNow() { if (!$this->_now) { return now(); } return $this->_now; } /** * Set current date for current rule * * @param string $now */ public function setNow($now) { $this->_now = $now; } /** * Get array of product ids which are matched by rule * * @return array */ public function getMatchingProductIds() { if (is_null($this->_productIds)) { $this->_productIds = array(); $this->setCollectedAttributes(array()); if ($this->getWebsiteIds()) { /** @var $productCollection Mage_Catalog_Model_Resource_Eav_Mysql4_Product_Collection */ $productCollection = Mage::getResourceModel('catalog/product_collection'); $productCollection->addWebsiteFilter($this->getWebsiteIds()); if ($this->_productsFilter) { $productCollection->addIdFilter($this->_productsFilter); } $this->getConditions()->collectValidatedAttributes($productCollection); Mage::getSingleton('core/resource_iterator')->walk( $productCollection->getSelect(), array(array($this, 'callbackValidateProduct')), array( 'attributes' => $this->getCollectedAttributes(), 'product' => Mage::getModel('catalog/product'), ) ); } } return $this->_productIds; } /** * Callback function for product matching * * @param $args * @return void */ public function callbackValidateProduct($args) { $product = clone $args['product']; $product->setData($args['row']); if ($this->getConditions()->validate($product)) { $this->_productIds[] = $product->getId(); } } /** * Apply rule to product * * @param int|Mage_Catalog_Model_Product $product * @param array|null $websiteIds * * @return void */ public function applyToProduct($product, $websiteIds = null) { if (is_numeric($product)) { $product = Mage::getModel('catalog/product')->load($product); } if (is_null($websiteIds)) { $websiteIds = $this->getWebsiteIds(); } $this->getResource()->applyToProduct($this, $product, $websiteIds); } /** * Apply all price rules, invalidate related cache and refresh price index * * @return Mage_CatalogRule_Model_Rule */ public function applyAll() { $this->getResourceCollection()->walk(array($this->_getResource(), 'updateRuleProductData')); $this->_getResource()->applyAllRulesForDateRange(); $this->_invalidateCache(); $indexProcess = Mage::getSingleton('index/indexer')->getProcessByCode('catalog_product_price'); if ($indexProcess) { $indexProcess->reindexAll(); } } /** * Apply all price rules to product * * @param int|Mage_Catalog_Model_Product $product * @return Mage_CatalogRule_Model_Rule */ public function applyAllRulesToProduct($product) { $this->_getResource()->applyAllRulesForDateRange(NULL, NULL, $product); $this->_invalidateCache(); if ($product instanceof Mage_Catalog_Model_Product) { $productId = $product->getId(); } else { $productId = $product; } if ($productId) { Mage::getSingleton('index/indexer')->processEntityAction( new Varien_Object(array('id' => $productId)), Mage_Catalog_Model_Product::ENTITY, Mage_Catalog_Model_Product_Indexer_Price::EVENT_TYPE_REINDEX_PRICE ); } } /** * Calculate price using catalog price rule of product * * @param Mage_Catalog_Model_Product $product * @param float $price * @return float|null */ public function calcProductPriceRule(Mage_Catalog_Model_Product $product, $price) { $priceRules = null; $productId = $product->getId(); $storeId = $product->getStoreId(); $websiteId = Mage::app()->getStore($storeId)->getWebsiteId(); if ($product->hasCustomerGroupId()) { $customerGroupId = $product->getCustomerGroupId(); } else { $customerGroupId = Mage::getSingleton('customer/session')->getCustomerGroupId(); } $dateTs = Mage::app()->getLocale()->storeTimeStamp($storeId); $cacheKey = date('Y-m-d', $dateTs) . "|$websiteId|$customerGroupId|$productId|$price"; if (!array_key_exists($cacheKey, self::$_priceRulesData)) { $rulesData = $this->_getResource()->getRulesFromProduct($dateTs, $websiteId, $customerGroupId, $productId); if ($rulesData) { foreach ($rulesData as $ruleData) { if ($product->getParentId()) { if (!empty($ruleData['sub_simple_action'])) { $priceRules = Mage::helper('catalogrule')->calcPriceRule( $ruleData['sub_simple_action'], $ruleData['sub_discount_amount'], $priceRules ? $priceRules : $price ); } else { $priceRules = $price; } if ($ruleData['action_stop']) { break; } } else { $priceRules = Mage::helper('catalogrule')->calcPriceRule( $ruleData['action_operator'], $ruleData['action_amount'], $priceRules ? $priceRules : $price ); if ($ruleData['action_stop']) { break; } } } return self::$_priceRulesData[$cacheKey] = $priceRules; } else { self::$_priceRulesData[$cacheKey] = null; } } else { return self::$_priceRulesData[$cacheKey]; } return null; } /** * Filtering products that must be checked for matching with rule * * @param int|array $productIds */ public function setProductsFilter($productIds) { $this->_productsFilter = $productIds; } /** * Returns products filter * * @return array|int|null */ public function getProductsFilter() { return $this->_productsFilter; } /** * Invalidate related cache types * * @return Mage_CatalogRule_Model_Rule */ protected function _invalidateCache() { $types = Mage::getConfig()->getNode(self::XML_NODE_RELATED_CACHE); if ($types) { $types = $types->asArray(); Mage::app()->getCacheInstance()->invalidateType(array_keys($types)); } return $this; } /** * @deprecated after 1.11.2.0 * * @param string $format * * @return string */ public function toString($format='') { return ''; } /** * Returns rule as an array for admin interface * * @deprecated after 1.11.2.0 * * @param array $arrAttributes * * Output example: * array( * 'name'=>'Example rule', * 'conditions'=>{condition_combine::toArray} * 'actions'=>{action_collection::toArray} * ) * * @return array */ public function toArray(array $arrAttributes = array()) { return parent::toArray($arrAttributes); } }