mirror of
https://github.com/bdnugget/magento2.git
synced 2026-11-07 17:27:36 +00:00
648 lines
19 KiB
PHP
648 lines
19 KiB
PHP
<?php
|
|
/**
|
|
* Copyright © Magento, Inc. All rights reserved.
|
|
* See COPYING.txt for license details.
|
|
*/
|
|
namespace Magento\SalesRule\Model;
|
|
|
|
use Magento\Framework\Api\AttributeValueFactory;
|
|
use Magento\Framework\Api\ExtensionAttributesFactory;
|
|
use Magento\Quote\Model\Quote\Address;
|
|
|
|
/**
|
|
* Shopping Cart Rule data model
|
|
*
|
|
* @api
|
|
* @method string getName()
|
|
* @method \Magento\SalesRule\Model\Rule setName(string $value)
|
|
* @method string getDescription()
|
|
* @method \Magento\SalesRule\Model\Rule setDescription(string $value)
|
|
* @method \Magento\SalesRule\Model\Rule setFromDate(string $value)
|
|
* @method \Magento\SalesRule\Model\Rule setToDate(string $value)
|
|
* @method int getUsesPerCustomer()
|
|
* @method \Magento\SalesRule\Model\Rule setUsesPerCustomer(int $value)
|
|
* @method int getUsesPerCoupon()
|
|
* @method \Magento\SalesRule\Model\Rule setUsesPerCoupon(int $value)
|
|
* @method \Magento\SalesRule\Model\Rule setCustomerGroupIds(string $value)
|
|
* @method int getIsActive()
|
|
* @method \Magento\SalesRule\Model\Rule setIsActive(int $value)
|
|
* @method string getConditionsSerialized()
|
|
* @method \Magento\SalesRule\Model\Rule setConditionsSerialized(string $value)
|
|
* @method string getActionsSerialized()
|
|
* @method \Magento\SalesRule\Model\Rule setActionsSerialized(string $value)
|
|
* @method int getStopRulesProcessing()
|
|
* @method \Magento\SalesRule\Model\Rule setStopRulesProcessing(int $value)
|
|
* @method int getIsAdvanced()
|
|
* @method \Magento\SalesRule\Model\Rule setIsAdvanced(int $value)
|
|
* @method string getProductIds()
|
|
* @method \Magento\SalesRule\Model\Rule setProductIds(string $value)
|
|
* @method int getSortOrder()
|
|
* @method \Magento\SalesRule\Model\Rule setSortOrder(int $value)
|
|
* @method \Magento\SalesRule\Model\Rule setSimpleAction(string $value)
|
|
* @method float getDiscountAmount()
|
|
* @method \Magento\SalesRule\Model\Rule setDiscountAmount(float $value)
|
|
* @method float getDiscountQty()
|
|
* @method \Magento\SalesRule\Model\Rule setDiscountQty(float $value)
|
|
* @method int getDiscountStep()
|
|
* @method \Magento\SalesRule\Model\Rule setDiscountStep(int $value)
|
|
* @method int getApplyToShipping()
|
|
* @method \Magento\SalesRule\Model\Rule setApplyToShipping(int $value)
|
|
* @method int getTimesUsed()
|
|
* @method \Magento\SalesRule\Model\Rule setTimesUsed(int $value)
|
|
* @method int getIsRss()
|
|
* @method \Magento\SalesRule\Model\Rule setIsRss(int $value)
|
|
* @method string getWebsiteIds()
|
|
* @method \Magento\SalesRule\Model\Rule setWebsiteIds(string $value)
|
|
* @method int getCouponType()
|
|
* @method \Magento\SalesRule\Model\Rule setCouponType(int $value)
|
|
* @method int getUseAutoGeneration()
|
|
* @method \Magento\SalesRule\Model\Rule setUseAutoGeneration(int $value)
|
|
* @method string getCouponCode()
|
|
* @method \Magento\SalesRule\Model\Rule setCouponCode(string $value)
|
|
* @method int getRuleId()
|
|
* @method \Magento\SalesRule\Model\Rule setRuleId(int $ruleId)
|
|
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
|
|
* @since 100.0.2
|
|
*/
|
|
class Rule extends \Magento\Rule\Model\AbstractModel
|
|
{
|
|
/**
|
|
* Coupon types
|
|
*/
|
|
public const COUPON_TYPE_NO_COUPON = 1;
|
|
|
|
public const COUPON_TYPE_SPECIFIC = 2;
|
|
|
|
public const COUPON_TYPE_AUTO = 3;
|
|
|
|
/**
|
|
* Rule type actions
|
|
*/
|
|
public const TO_PERCENT_ACTION = 'to_percent';
|
|
|
|
public const BY_PERCENT_ACTION = 'by_percent';
|
|
|
|
public const TO_FIXED_ACTION = 'to_fixed';
|
|
|
|
public const BY_FIXED_ACTION = 'by_fixed';
|
|
|
|
public const CART_FIXED_ACTION = 'cart_fixed';
|
|
|
|
public const BUY_X_GET_Y_ACTION = 'buy_x_get_y';
|
|
|
|
/**
|
|
* Store coupon code generator instance
|
|
*
|
|
* @var \Magento\SalesRule\Model\Coupon\CodegeneratorInterface
|
|
*/
|
|
protected $_couponCodeGenerator;
|
|
|
|
/**
|
|
* Prefix of model events names
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $_eventPrefix = 'salesrule_rule';
|
|
|
|
/**
|
|
* Parameter name in event
|
|
*
|
|
* In observe method you can use $observer->getEvent()->getRule() in this case
|
|
*
|
|
* @var string
|
|
*/
|
|
protected $_eventObject = 'rule';
|
|
|
|
/**
|
|
* Rule's primary coupon
|
|
*
|
|
* @var \Magento\SalesRule\Model\Coupon
|
|
*/
|
|
protected $_primaryCoupon;
|
|
|
|
/**
|
|
* Rule's subordinate coupons
|
|
*
|
|
* @var \Magento\SalesRule\Model\Coupon[]
|
|
*/
|
|
protected $_coupons;
|
|
|
|
/**
|
|
* Coupon types cache for lazy getter
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_couponTypes;
|
|
|
|
/**
|
|
* Store already validated addresses and validation results
|
|
*
|
|
* @var array
|
|
*/
|
|
protected $_validatedAddresses = [];
|
|
|
|
/**
|
|
* @var \Magento\SalesRule\Model\CouponFactory
|
|
*/
|
|
protected $_couponFactory;
|
|
|
|
/**
|
|
* @var \Magento\SalesRule\Model\Coupon\CodegeneratorFactory
|
|
*/
|
|
protected $_codegenFactory;
|
|
|
|
/**
|
|
* @var \Magento\SalesRule\Model\Rule\Condition\CombineFactory
|
|
*/
|
|
protected $_condCombineFactory;
|
|
|
|
/**
|
|
* @var \Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory
|
|
*/
|
|
protected $_condProdCombineF;
|
|
|
|
/**
|
|
* @var \Magento\SalesRule\Model\ResourceModel\Coupon\Collection
|
|
*/
|
|
protected $_couponCollection;
|
|
|
|
/**
|
|
* @var \Magento\Store\Model\StoreManagerInterface
|
|
*/
|
|
protected $_storeManager;
|
|
|
|
/**
|
|
* Rule constructor
|
|
*
|
|
* @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 CouponFactory $couponFactory
|
|
* @param Coupon\CodegeneratorFactory $codegenFactory
|
|
* @param Rule\Condition\CombineFactory $condCombineFactory
|
|
* @param Rule\Condition\Product\CombineFactory $condProdCombineF
|
|
* @param ResourceModel\Coupon\Collection $couponCollection
|
|
* @param \Magento\Store\Model\StoreManagerInterface $storeManager
|
|
* @param \Magento\Framework\Model\ResourceModel\AbstractResource|null $resource
|
|
* @param \Magento\Framework\Data\Collection\AbstractDb|null $resourceCollection
|
|
* @param array $data
|
|
* @param ExtensionAttributesFactory|null $extensionFactory
|
|
* @param AttributeValueFactory|null $customAttributeFactory
|
|
* @param \Magento\Framework\Serialize\Serializer\Json $serializer
|
|
*
|
|
* @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\CouponFactory $couponFactory,
|
|
\Magento\SalesRule\Model\Coupon\CodegeneratorFactory $codegenFactory,
|
|
\Magento\SalesRule\Model\Rule\Condition\CombineFactory $condCombineFactory,
|
|
\Magento\SalesRule\Model\Rule\Condition\Product\CombineFactory $condProdCombineF,
|
|
\Magento\SalesRule\Model\ResourceModel\Coupon\Collection $couponCollection,
|
|
\Magento\Store\Model\StoreManagerInterface $storeManager,
|
|
\Magento\Framework\Model\ResourceModel\AbstractResource $resource = null,
|
|
\Magento\Framework\Data\Collection\AbstractDb $resourceCollection = null,
|
|
array $data = [],
|
|
ExtensionAttributesFactory $extensionFactory = null,
|
|
AttributeValueFactory $customAttributeFactory = null,
|
|
\Magento\Framework\Serialize\Serializer\Json $serializer = null
|
|
) {
|
|
$this->_couponFactory = $couponFactory;
|
|
$this->_codegenFactory = $codegenFactory;
|
|
$this->_condCombineFactory = $condCombineFactory;
|
|
$this->_condProdCombineF = $condProdCombineF;
|
|
$this->_couponCollection = $couponCollection;
|
|
$this->_storeManager = $storeManager;
|
|
parent::__construct(
|
|
$context,
|
|
$registry,
|
|
$formFactory,
|
|
$localeDate,
|
|
$resource,
|
|
$resourceCollection,
|
|
$data,
|
|
$extensionFactory,
|
|
$customAttributeFactory,
|
|
$serializer
|
|
);
|
|
}
|
|
|
|
/**
|
|
* Set resource model and Id field name
|
|
*
|
|
* @return void
|
|
*/
|
|
protected function _construct()
|
|
{
|
|
parent::_construct();
|
|
$this->_init(\Magento\SalesRule\Model\ResourceModel\Rule::class);
|
|
$this->setIdFieldName('rule_id');
|
|
}
|
|
|
|
/**
|
|
* Set coupon code and uses per coupon
|
|
*
|
|
* @return $this
|
|
*/
|
|
protected function _afterLoad()
|
|
{
|
|
$this->loadRelations();
|
|
return parent::_afterLoad();
|
|
}
|
|
|
|
/**
|
|
* Load all relative data
|
|
*
|
|
* @return void
|
|
*/
|
|
public function loadRelations()
|
|
{
|
|
$this->loadCouponCode();
|
|
}
|
|
|
|
/**
|
|
* Load coupon code
|
|
*
|
|
* @return void
|
|
*/
|
|
public function loadCouponCode()
|
|
{
|
|
$this->setCouponCode($this->getPrimaryCoupon()->getCode());
|
|
if ($this->getUsesPerCoupon() == null && !$this->getUseAutoGeneration()) {
|
|
$this->setUsesPerCoupon($this->getPrimaryCoupon()->getUsageLimit());
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Save/delete coupon
|
|
*
|
|
* @return $this
|
|
*/
|
|
public function afterSave()
|
|
{
|
|
$couponCode = is_string($this->getCouponCode()) ? trim($this->getCouponCode()) : '';
|
|
if (strlen(
|
|
$couponCode
|
|
) && $this->getCouponType() == self::COUPON_TYPE_SPECIFIC && !$this->getUseAutoGeneration()
|
|
) {
|
|
$this->getPrimaryCoupon()->setCode(
|
|
$couponCode
|
|
)->setUsageLimit(
|
|
$this->getUsesPerCoupon() ? $this->getUsesPerCoupon() : null
|
|
)->setUsagePerCustomer(
|
|
$this->getUsesPerCustomer() ? $this->getUsesPerCustomer() : null
|
|
)->save();
|
|
} else {
|
|
$this->getPrimaryCoupon()->delete();
|
|
}
|
|
|
|
parent::afterSave();
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* Initialize rule model data from array. Set store labels if applicable.
|
|
*
|
|
* @param array $data
|
|
* @return $this
|
|
*/
|
|
public function loadPost(array $data)
|
|
{
|
|
parent::loadPost($data);
|
|
|
|
if (isset($data['store_labels'])) {
|
|
$this->setStoreLabels($data['store_labels']);
|
|
}
|
|
|
|
return $this;
|
|
}
|
|
|
|
/**
|
|
* 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();
|
|
}
|
|
|
|
/**
|
|
* Returns code generator instance for auto generated coupons
|
|
*
|
|
* @return \Magento\SalesRule\Model\Coupon\CodegeneratorInterface
|
|
*/
|
|
public function getCouponCodeGenerator()
|
|
{
|
|
if (!$this->_couponCodeGenerator) {
|
|
return $this->_codegenFactory->create(['data' => ['length' => 16]]);
|
|
}
|
|
return $this->_couponCodeGenerator;
|
|
}
|
|
|
|
/**
|
|
* Set code generator instance for auto generated coupons
|
|
*
|
|
* @param \Magento\SalesRule\Model\Coupon\CodegeneratorInterface $codeGenerator
|
|
* @return void
|
|
*/
|
|
public function setCouponCodeGenerator(\Magento\SalesRule\Model\Coupon\CodegeneratorInterface $codeGenerator)
|
|
{
|
|
$this->_couponCodeGenerator = $codeGenerator;
|
|
}
|
|
|
|
/**
|
|
* Retrieve rule's primary coupon
|
|
*
|
|
* @return \Magento\SalesRule\Model\Coupon
|
|
*/
|
|
public function getPrimaryCoupon()
|
|
{
|
|
if ($this->_primaryCoupon === null) {
|
|
$this->_primaryCoupon = $this->_couponFactory->create();
|
|
$this->_primaryCoupon->loadPrimaryByRule($this->getId());
|
|
$this->_primaryCoupon->setRule($this)->setIsPrimary(true);
|
|
}
|
|
return $this->_primaryCoupon;
|
|
}
|
|
|
|
/**
|
|
* Get sales 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');
|
|
}
|
|
|
|
/**
|
|
* Get Rule label by specified store
|
|
*
|
|
* @param \Magento\Store\Model\Store|int|bool|null $store
|
|
* @return string|bool
|
|
*/
|
|
public function getStoreLabel($store = null)
|
|
{
|
|
$storeId = $this->_storeManager->getStore($store)->getId();
|
|
$labels = (array)$this->getStoreLabels();
|
|
|
|
if (isset($labels[$storeId])) {
|
|
return $labels[$storeId];
|
|
} elseif (isset($labels[0]) && $labels[0]) {
|
|
return $labels[0];
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Set if not yet and retrieve rule store labels
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getStoreLabels()
|
|
{
|
|
if (!$this->hasStoreLabels()) {
|
|
$linkedField = $this->_getResource()->getLinkField();
|
|
$labels = $this->_getResource()->getStoreLabels($this->getData($linkedField));
|
|
$this->setStoreLabels($labels);
|
|
}
|
|
|
|
return $this->_getData('store_labels');
|
|
}
|
|
|
|
/**
|
|
* Retrieve subordinate coupons
|
|
*
|
|
* @return \Magento\SalesRule\Model\Coupon[]
|
|
*/
|
|
public function getCoupons()
|
|
{
|
|
if ($this->_coupons === null) {
|
|
$this->_couponCollection->addRuleToFilter($this);
|
|
$this->_coupons = $this->_couponCollection->getItems();
|
|
}
|
|
return $this->_coupons;
|
|
}
|
|
|
|
/**
|
|
* Retrieve coupon types
|
|
*
|
|
* @return array
|
|
*/
|
|
public function getCouponTypes()
|
|
{
|
|
if ($this->_couponTypes === null) {
|
|
$this->_couponTypes = [
|
|
\Magento\SalesRule\Model\Rule::COUPON_TYPE_NO_COUPON => __('No Coupon'),
|
|
\Magento\SalesRule\Model\Rule::COUPON_TYPE_SPECIFIC => __('Specific Coupon'),
|
|
];
|
|
$transport = new \Magento\Framework\DataObject(
|
|
['coupon_types' => $this->_couponTypes, 'is_coupon_type_auto_visible' => false]
|
|
);
|
|
$this->_eventManager->dispatch('salesrule_rule_get_coupon_types', ['transport' => $transport]);
|
|
$this->_couponTypes = $transport->getCouponTypes();
|
|
if ($transport->getIsCouponTypeAutoVisible()) {
|
|
$this->_couponTypes[\Magento\SalesRule\Model\Rule::COUPON_TYPE_AUTO] = __('Auto');
|
|
}
|
|
}
|
|
return $this->_couponTypes;
|
|
}
|
|
|
|
/**
|
|
* Acquire coupon instance
|
|
*
|
|
* @param bool $saveNewlyCreated Whether or not to save newly created coupon
|
|
* @param int $saveAttemptCount Number of attempts to save newly created coupon
|
|
* @return \Magento\SalesRule\Model\Coupon|null
|
|
* @throws \Exception|\Magento\Framework\Exception\LocalizedException
|
|
* @SuppressWarnings(PHPMD.CyclomaticComplexity)
|
|
* @SuppressWarnings(PHPMD.NPathComplexity)
|
|
*/
|
|
public function acquireCoupon($saveNewlyCreated = true, $saveAttemptCount = 10)
|
|
{
|
|
if ($this->getCouponType() == self::COUPON_TYPE_NO_COUPON) {
|
|
return null;
|
|
}
|
|
if ($this->getCouponType() == self::COUPON_TYPE_SPECIFIC) {
|
|
return $this->getPrimaryCoupon();
|
|
}
|
|
/** @var \Magento\SalesRule\Model\Coupon $coupon */
|
|
$coupon = $this->_couponFactory->create();
|
|
$coupon->setRule(
|
|
$this
|
|
)->setIsPrimary(
|
|
false
|
|
)->setUsageLimit(
|
|
$this->getUsesPerCoupon() ? $this->getUsesPerCoupon() : null
|
|
)->setUsagePerCustomer(
|
|
$this->getUsesPerCustomer() ? $this->getUsesPerCustomer() : null
|
|
)->setType(
|
|
\Magento\SalesRule\Api\Data\CouponInterface::TYPE_GENERATED
|
|
);
|
|
|
|
$couponCode = self::getCouponCodeGenerator()->generateCode();
|
|
$coupon->setCode($couponCode);
|
|
|
|
$ok = false;
|
|
if (!$saveNewlyCreated) {
|
|
$ok = true;
|
|
} else {
|
|
if ($this->getId()) {
|
|
for ($attemptNum = 0; $attemptNum < $saveAttemptCount; $attemptNum++) {
|
|
try {
|
|
$coupon->save();
|
|
} catch (\Exception $e) {
|
|
if ($e instanceof \Magento\Framework\Exception\LocalizedException || $coupon->getId()) {
|
|
throw $e;
|
|
}
|
|
$coupon->setCode(
|
|
$couponCode . self::getCouponCodeGenerator()->getDelimiter() . sprintf(
|
|
'%04u',
|
|
random_int(0, 9999)
|
|
)
|
|
);
|
|
continue;
|
|
}
|
|
$ok = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
if (!$ok) {
|
|
throw new \Magento\Framework\Exception\LocalizedException(__('Can\'t acquire coupon.'));
|
|
}
|
|
|
|
return $coupon;
|
|
}
|
|
|
|
/**
|
|
* Get from date.
|
|
*
|
|
* @return string
|
|
* @since 100.1.0
|
|
*/
|
|
public function getFromDate()
|
|
{
|
|
return $this->getData('from_date');
|
|
}
|
|
|
|
/**
|
|
* Get from date.
|
|
*
|
|
* @return string
|
|
* @since 100.1.0
|
|
*/
|
|
public function getSimpleAction()
|
|
{
|
|
return $this->_getData('simple_action');
|
|
}
|
|
|
|
/**
|
|
* Get to date.
|
|
*
|
|
* @return string
|
|
* @since 100.1.0
|
|
*/
|
|
public function getToDate()
|
|
{
|
|
return $this->getData('to_date');
|
|
}
|
|
|
|
/**
|
|
* 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;
|
|
}
|
|
|
|
/**
|
|
* Get conditions field set id.
|
|
*
|
|
* @param string $formName
|
|
* @return string
|
|
* @since 100.1.0
|
|
*/
|
|
public function getConditionsFieldSetId($formName = '')
|
|
{
|
|
return $formName . 'rule_conditions_fieldset_' . $this->getId();
|
|
}
|
|
|
|
/**
|
|
* Get actions field set id.
|
|
*
|
|
* @param string $formName
|
|
* @return string
|
|
* @since 100.1.0
|
|
*/
|
|
public function getActionsFieldSetId($formName = '')
|
|
{
|
|
return $formName . 'rule_actions_fieldset_' . $this->getId();
|
|
}
|
|
}
|