![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/vendor/magento/module-sales-rule/Model/ResourceModel/Rule/ |
<?php /** * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ namespace Magento\SalesRule\Model\ResourceModel\Rule; use Magento\Framework\DB\Select; use Magento\Framework\Serialize\Serializer\Json; use Magento\Quote\Model\Quote\Address; use Magento\SalesRule\Api\Data\CouponInterface; use Magento\SalesRule\Model\Coupon; use Magento\SalesRule\Model\Rule; /** * Sales Rules resource collection model. * * @api * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @since 100.0.2 */ class Collection extends \Magento\Rule\Model\ResourceModel\Rule\Collection\AbstractCollection { /** * Store associated with rule entities information map * * @var array */ protected $_associatedEntitiesMap; /** * SaleRule Event prefix * * @var string */ protected $_eventPrefix = 'salesrule_rule_collection'; /** * SaleRule Event object * * @var string */ protected $_eventObject = 'rule_collection'; /** * @var \Magento\SalesRule\Model\ResourceModel\Rule\DateApplier * @since 100.1.0 */ protected $dateApplier; /** * @var \Magento\Framework\Stdlib\DateTime\TimezoneInterface */ protected $_date; /** * @var Json $serializer */ private $serializer; /** * @param \Magento\Framework\Data\Collection\EntityFactory $entityFactory * @param \Psr\Log\LoggerInterface $logger * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy * @param \Magento\Framework\Event\ManagerInterface $eventManager * @param \Magento\Framework\Stdlib\DateTime\TimezoneInterface $date * @param mixed $connection * @param \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource * @param Json $serializer Optional parameter for backward compatibility */ public function __construct( \Magento\Framework\Data\Collection\EntityFactory $entityFactory, \Psr\Log\LoggerInterface $logger, \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy, \Magento\Framework\Event\ManagerInterface $eventManager, \Magento\Framework\Stdlib\DateTime\TimezoneInterface $date, \Magento\Framework\DB\Adapter\AdapterInterface $connection = null, \Magento\Framework\Model\ResourceModel\Db\AbstractDb $resource = null, Json $serializer = null ) { parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $connection, $resource); $this->_date = $date; $this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance()->get(Json::class); $this->_associatedEntitiesMap = $this->getAssociatedEntitiesMap(); } /** * Set resource model and determine field mapping * * @return void */ protected function _construct() { $this->_init(\Magento\SalesRule\Model\Rule::class, \Magento\SalesRule\Model\ResourceModel\Rule::class); $this->_map['fields']['rule_id'] = 'main_table.rule_id'; } /** * Map data for associated entities * * @param string $entityType * @param string $objectField * @throws \Magento\Framework\Exception\LocalizedException * @return void * @since 100.1.0 */ protected function mapAssociatedEntities($entityType, $objectField) { if (!$this->_items) { return; } $entityInfo = $this->_getAssociatedEntityInfo($entityType); $ruleIdField = $entityInfo['rule_id_field']; $entityIds = $this->getColumnValues($ruleIdField); $select = $this->getConnection()->select()->from( $this->getTable($entityInfo['associations_table']) )->where( $ruleIdField . ' IN (?)', $entityIds ); $associatedEntities = $this->getConnection()->fetchAll($select); array_map( function ($associatedEntity) use ($entityInfo, $ruleIdField, $objectField) { $item = $this->getItemByColumnValue($ruleIdField, $associatedEntity[$ruleIdField]); $itemAssociatedValue = $item->getData($objectField) ?? []; $itemAssociatedValue[] = $associatedEntity[$entityInfo['entity_id_field']]; $item->setData($objectField, $itemAssociatedValue); }, $associatedEntities ); } /** * Add website ids and customer group ids to rules data * * @return $this * @throws \Exception * @since 100.1.0 */ protected function _afterLoad() { $this->mapAssociatedEntities('website', 'website_ids'); $this->mapAssociatedEntities('customer_group', 'customer_group_ids'); $this->setFlag('add_websites_to_result', false); return parent::_afterLoad(); } /** * Filter collection by specified website, customer group, coupon code, date. * Filter collection to use only active rules. * Involved sorting by sort_order column. * * @param int $websiteId * @param int $customerGroupId * @param string $couponCode * @param string|null $now * @param Address $address allow extensions to further filter out rules based on quote address * @throws \Zend_Db_Select_Exception * @use $this->addWebsiteGroupDateFilter() * @SuppressWarnings(PHPMD.UnusedFormalParameter) * @return $this */ public function setValidationFilter( $websiteId, $customerGroupId, $couponCode = '', $now = null, Address $address = null ) { if (!$this->getFlag('validation_filter')) { $this->prepareSelect($websiteId, $customerGroupId, $now); $noCouponRules = $this->getNoCouponCodeSelect(); if ($couponCode) { $couponRules = $this->getCouponCodeSelect($couponCode); $allAllowedRules = $this->getConnection()->select(); $allAllowedRules->union([$noCouponRules, $couponRules], Select::SQL_UNION_ALL); $wrapper = $this->getConnection()->select(); $wrapper->from($allAllowedRules); $this->_select = $wrapper; } else { $this->_select = $noCouponRules; } $this->setOrder('sort_order', self::SORT_ORDER_ASC); $this->setFlag('validation_filter', true); } return $this; } /** * Recreate the default select object for specific needs of salesrule evaluation with coupon codes. * * @param int $websiteId * @param int $customerGroupId * @param string $now */ private function prepareSelect($websiteId, $customerGroupId, $now) { $this->getSelect()->reset(); parent::_initSelect(); $this->addWebsiteGroupDateFilter($websiteId, $customerGroupId, $now); } /** * Return select object to determine all active rules not needing a coupon code. * * @return Select */ private function getNoCouponCodeSelect() { $noCouponSelect = clone $this->getSelect(); $noCouponSelect->where( 'main_table.coupon_type = ?', Rule::COUPON_TYPE_NO_COUPON ); $noCouponSelect->columns([Coupon::KEY_CODE => new \Zend_Db_Expr('NULL')]); return $noCouponSelect; } /** * Determine all active rules that are valid for the given coupon code. * * @param string $couponCode * @return Select */ private function getCouponCodeSelect($couponCode) { $couponSelect = clone $this->getSelect(); $this->joinCouponTable($couponCode, $couponSelect); $isAutogenerated = $this->getConnection()->quoteInto('main_table.coupon_type = ?', Rule::COUPON_TYPE_AUTO) . ' AND ' . $this->getConnection()->quoteInto('rule_coupons.type = ?', CouponInterface::TYPE_GENERATED); $isValidSpecific = $this->getConnection()->quoteInto('(main_table.coupon_type = ?)', Rule::COUPON_TYPE_SPECIFIC) . ' AND (' . '(main_table.use_auto_generation = 1 AND rule_coupons.type = 1)' . ' OR ' . '(main_table.use_auto_generation = 0 AND rule_coupons.type = 0)' . ')'; $couponSelect->where( "$isAutogenerated OR $isValidSpecific", null, Select::TYPE_CONDITION ); return $couponSelect; } /** * Join coupong table to select. * * @param string $couponCode * @param Select $couponSelect */ private function joinCouponTable($couponCode, Select $couponSelect) { $couponJoinCondition = 'main_table.rule_id = rule_coupons.rule_id' . ' AND ' . $this->getConnection()->quoteInto('main_table.coupon_type <> ?', Rule::COUPON_TYPE_NO_COUPON) . ' AND ' . $this->getConnection()->quoteInto('rule_coupons.code = ?', $couponCode); $couponSelect->joinInner( ['rule_coupons' => $this->getTable('salesrule_coupon')], $couponJoinCondition, [Coupon::KEY_CODE] ); } /** * Filter collection by website(s), customer group(s) and date. * Filter collection to only active rules. * Sorting is not involved * * @param int $websiteId * @param int $customerGroupId * @param string|null $now * @use $this->addWebsiteFilter() * @return $this */ public function addWebsiteGroupDateFilter($websiteId, $customerGroupId, $now = null) { if (!$this->getFlag('website_group_date_filter')) { if ($now === null) { $now = $this->_date->date()->format('Y-m-d'); } $this->addWebsiteFilter($websiteId); $entityInfo = $this->_getAssociatedEntityInfo('customer_group'); $connection = $this->getConnection(); $this->getSelect()->joinInner( ['customer_group_ids' => $this->getTable($entityInfo['associations_table'])], $connection->quoteInto( 'main_table.' . $entityInfo['rule_id_field'] . ' = customer_group_ids.' . $entityInfo['rule_id_field'] . ' AND customer_group_ids.' . $entityInfo['entity_id_field'] . ' = ?', (int)$customerGroupId ), [] ); // exclude websites that are limited for customer group $this->getSelect()->joinLeft( ['cgw' => $this->getTable('customer_group_excluded_website')], 'customer_group_ids.' . $entityInfo['entity_id_field'] . ' = cgw.' . $entityInfo['entity_id_field'] . ' AND ' . $websiteId . ' = cgw.website_id', [] )->where( 'cgw.website_id IS NULL', $websiteId, \Zend_Db::INT_TYPE ); $this->getDateApplier()->applyDate($this->getSelect(), $now); $this->addIsActiveFilter(); $this->setFlag('website_group_date_filter', true); } return $this; } /** * Add primary coupon to collection * * @return $this */ public function _initSelect() { parent::_initSelect(); $this->getSelect()->joinLeft( ['rule_coupons' => $this->getTable('salesrule_coupon')], 'main_table.rule_id = rule_coupons.rule_id AND rule_coupons.is_primary = 1', ['code'] ); return $this; } /** * Find product attribute in conditions or actions * * @param string $attributeCode * @return $this */ public function addAttributeInConditionFilter($attributeCode) { $match = sprintf('%%%s%%', substr($this->serializer->serialize(['attribute' => $attributeCode]), 1, -1)); /** * Information about conditions and actions stored in table as JSON encoded array * in fields conditions_serialized and actions_serialized. * If you want to find rules that contains some particular attribute, the easiest way to do so is serialize * attribute code in the same way as it stored in the serialized columns and execute SQL search * with like condition. * Table * +-------------------------------------------------------------------+ * | conditions_serialized | actions_serialized | * +-------------------------------------------------------------------+ * | {..."attribute":"attr_name"...} | {..."attribute":"attr_name"...} | * +---------------------------------|---------------------------------+ * From attribute code "attr_code", will be generated such SQL: * `condition_serialized` LIKE '%"attribute":"attr_name"%' * OR `actions_serialized` LIKE '%"attribute":"attr_name"%' */ $field = $this->_getMappedField('conditions_serialized'); $cCond = $this->_getConditionSql($field, ['like' => $match]); $field = $this->_getMappedField('actions_serialized'); $aCond = $this->_getConditionSql($field, ['like' => $match]); $this->getSelect()->where( sprintf('(%s OR %s)', $cCond, $aCond), null, Select::TYPE_CONDITION ); return $this; } /** * Excludes price rules with generated specific coupon codes from collection * * @return $this */ public function addAllowedSalesRulesFilter() { $this->addFieldToFilter('main_table.use_auto_generation', ['neq' => 1]); return $this; } /** * Limit rules collection by specific customer group * * @param int $customerGroupId * @return $this * @since 100.1.0 */ public function addCustomerGroupFilter($customerGroupId) { $entityInfo = $this->_getAssociatedEntityInfo('customer_group'); if (!$this->getFlag('is_customer_group_joined')) { $this->setFlag('is_customer_group_joined', true); $this->getSelect()->join( ['customer_group' => $this->getTable($entityInfo['associations_table'])], $this->getConnection() ->quoteInto('customer_group.' . $entityInfo['entity_id_field'] . ' = ?', $customerGroupId) . ' AND main_table.' . $entityInfo['rule_id_field'] . ' = customer_group.' . $entityInfo['rule_id_field'], [] ); } return $this; } // phpcs:disable /** * Getter for _associatedEntitiesMap property * * @return array * @deprecated 100.1.0 */ private function getAssociatedEntitiesMap() { if (!$this->_associatedEntitiesMap) { $this->_associatedEntitiesMap = \Magento\Framework\App\ObjectManager::getInstance() // phpstan:ignore "Class Magento\SalesRule\Model\ResourceModel\Rule\AssociatedEntityMap not found." ->get(\Magento\SalesRule\Model\ResourceModel\Rule\AssociatedEntityMap::class) ->getData(); } return $this->_associatedEntitiesMap; } /** * Getter for dateApplier property * * @return DateApplier * @deprecated 100.1.0 */ private function getDateApplier() { if (null === $this->dateApplier) { $this->dateApplier = \Magento\Framework\App\ObjectManager::getInstance() ->get(\Magento\SalesRule\Model\ResourceModel\Rule\DateApplier::class); } return $this->dateApplier; } // phpcs:enable }