How to validate a condition rules based on product attribute in magento 2
backend:
code:
$product_id = '3'; // Crown Summit Backpack sku is 24-MB03
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$rules = $objectManager->create('Vendor\Module\Model\Rule')->getCollection();
foreach ($rules as $rule) {
$product = $objectManager->get('Magento\Catalog\Model\Product')->load($product_id);
$item = $objectManager->create('Magento\Catalog\Model\Product');
$item->setProduct($product);
$validate = $rule->getActions()->validate($item);
}
var_dump($validate);
var_dump($product);
Expected result is false but it always shows true. validation not done properly on product attributes.
var_dump($validate);
var_dump($product);
Vendor\Module\Model\Rule.php
<?php
namespace Vendor\Module\Model;
use Magento\Quote\Model\Quote\Address;
use Magento\Rule\Model\AbstractModel;
/**
* Class Rule
* @package Vendor\Module\Model
*
* @method int|null getRuleId()
* @method Rule setRuleId(int $id)
*/
class Rule extends AbstractModel
{
/**
* Prefix of model events names
*
* @var string
*/
protected $_eventPrefix = 'vendor_module';
/**
* Parameter name in event
*
* In observe method you can use $observer->getEvent()->getRule() in this case
*
* @var string
*/
protected $_eventObject = 'rule';
/** @var \Magento\SalesRule\Model\Rule\Condition\CombineFactory */
protected $condCombineFactory;
/** @var \Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory */
protected $condProdCombineF;
/**
* Store already validated addresses and validation results
*
* @var array
*/
protected $validatedAddresses = [];
/**
* @param \Magento\Framework\Model\Context $context
* @param \Magento\Framework\Registry $registry
* @param \Magento\Framework\Data\FormFactory $formFactory
* @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate
* @param \Magento\SalesRule\Model\Rule\Condition\CombineFactory $condCombineFactory
* @param \Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory $condProdCombineF
* @param \Magento\Framework\Model\ResourceModel\AbstractResource $resource
* @param \Magento\Framework\Data\Collection\AbstractDb $resourceCollection
* @param array $data
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
*/
public function __construct(
\Magento\Framework\Model\Context $context,
\Magento\Framework\Registry $registry,
\Magento\Framework\Data\FormFactory $formFactory,
\Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
\Magento\SalesRule\Model\Rule\Condition\CombineFactory $condCombineFactory,
\Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory $condProdCombineF,
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
array $data = []
) {
$this->condCombineFactory = $condCombineFactory;
$this->condProdCombineF = $condProdCombineF;
parent::__construct($context, $registry, $formFactory, $localeDate, $resource, $resourceCollection, $data);
}
/**
* Set resource model and Id field name
*
* @return void
*/
protected function _construct()
{
parent::_construct();
$this->_init('Vendor\Module\Model\ResourceModel\Rule');
$this->setIdFieldName('rule_id');
}
/**
* Get rule condition combine model instance
*
* @return \Magento\SalesRule\Model\Rule\Condition\Combine
*/
public function getConditionsInstance()
{
return $this->condCombineFactory->create();
}
/**
* Get rule condition product combine model instance
*
* @return \Magento\SalesRule\Model\Rule\Condition\Product\Combine
*/
public function getActionsInstance()
{
return $this->condProdCombineF->create();
}
/**
* Check cached validation result for specific address
*
* @param Address $address
* @return bool
*/
public function hasIsValidForAddress($address)
{
$addressId = $this->_getAddressId($address);
return isset($this->validatedAddresses[$addressId]) ? true : false;
}
/**
* Set validation result for specific address to results cache
*
* @param Address $address
* @param bool $validationResult
* @return $this
*/
public function setIsValidForAddress($address, $validationResult)
{
$addressId = $this->_getAddressId($address);
$this->validatedAddresses[$addressId] = $validationResult;
return $this;
}
/**
* Get cached validation result for specific address
*
* @param Address $address
* @return bool
* @SuppressWarnings(PHPMD.BooleanGetMethodName)
*/
public function getIsValidForAddress($address)
{
$addressId = $this->_getAddressId($address);
return isset($this->validatedAddresses[$addressId]) ? $this->validatedAddresses[$addressId] : false;
}
/**
* Return id for address
*
* @param Address $address
* @return string
*/
private function _getAddressId($address)
{
if ($address instanceof Address) {
return $address->getId();
}
return $address;
}
}
Finally i done it, here my updated code
public function execute()
{
$validate = array();
$objectManager = \Magento\Framework\App\ObjectManager::getInstance();
$quoteId = $this->cart->getQuote()->getId();
$quote = $this->quoteFactory->load($quoteId);
$fakeQuote = clone $quote;
$fakeQuote->setId(null);
$items = $this->cart->getQuote()->getAllItems();
$rules = $objectManager->create('Vendor\Module\Model\Rule')->getCollection();
foreach ($rules as $rule){
foreach($items as $item){
$productId = $item->getProductId();
$product = $objectManager->create('Magento\Catalog\Model\Product')->load($productId);
$quoteItem = $objectManager->create('Magento\Quote\Model\Quote\Item');
$quoteItem->setQuote($fakeQuote)->setProduct($product);
$quoteItem->setAllItems(array($product));
$quoteItem->getProduct()->setProductId($product->getEntityId());
$validate = $rule->getConditions()->validate($quoteItem);
}
}
// var_dump($validate);
return $validate;
}