From e9c62c1f428e660f786a8c4981a56827d16a785d Mon Sep 17 00:00:00 2001 From: sergey Date: Tue, 7 Jun 2022 21:27:07 +0300 Subject: [PATCH] Admin user can call arbitrary Module class's constructor via Cart Price Rules #35135 --- .../Controller/Adminhtml/Promo/Catalog.php | 2 +- .../Adminhtml/Promo/Catalog/NewActionHtml.php | 30 +- .../Promo/Catalog/NewConditionHtml.php | 31 +- .../Adminhtml/Promo/Catalog/NewHtml.php | 69 ++ app/code/Magento/Rule/Block/Actions.php | 23 - app/code/Magento/Rule/Block/Conditions.php | 23 - app/code/Magento/Rule/Block/Editable.php | 101 -- app/code/Magento/Rule/Block/Newchild.php | 32 - app/code/Magento/Rule/Block/Rule.php | 10 - app/code/Magento/Rule/LICENSE.txt | 48 - app/code/Magento/Rule/LICENSE_AFL.txt | 48 - app/code/Magento/Rule/Model/AbstractModel.php | 509 ---------- .../Rule/Model/Action/AbstractAction.php | 371 ------- .../Rule/Model/Action/ActionInterface.php | 14 - .../Magento/Rule/Model/Action/Collection.php | 197 ---- app/code/Magento/Rule/Model/ActionFactory.php | 39 - .../Model/Condition/AbstractCondition.php | 925 ------------------ .../Magento/Rule/Model/Condition/Combine.php | 459 --------- .../Model/Condition/ConditionInterface.php | 34 - .../Magento/Rule/Model/Condition/Context.php | 110 --- .../Condition/Product/AbstractProduct.php | 734 -------------- .../Rule/Model/Condition/Sql/Builder.php | 300 ------ .../Rule/Model/Condition/Sql/Expression.php | 23 - .../Magento/Rule/Model/ConditionFactory.php | 60 -- .../Magento/Rule/Model/Renderer/Actions.php | 23 - .../Rule/Model/Renderer/Conditions.php | 23 - .../Model/ResourceModel/AbstractResource.php | 248 ----- .../Rule/Collection/AbstractCollection.php | 159 --- app/code/Magento/Rule/README.md | 1 - .../Rule/Test/Mftf/Helper/RuleHelper.php | 62 -- app/code/Magento/Rule/Test/Mftf/LICENSE.txt | 48 - .../Magento/Rule/Test/Mftf/LICENSE_AFL.txt | 48 - app/code/Magento/Rule/Test/Mftf/README.md | 3 - .../Test/Unit/Model/AbstractModelTest.php | 220 ----- .../Test/Unit/Model/ActionFactoryTest.php | 53 - .../Model/Condition/AbstractConditionTest.php | 242 ----- .../Test/Unit/Model/Condition/CombineTest.php | 156 --- .../Condition/Product/AbstractProductTest.php | 566 ----------- .../Unit/Model/Condition/Sql/BuilderTest.php | 150 --- .../Model/Condition/Sql/ExpressionTest.php | 24 - .../Test/Unit/Model/ConditionFactoryTest.php | 106 -- .../Test/Unit/Model/Renderer/ActionsTest.php | 67 -- .../Unit/Model/Renderer/ConditionsTest.php | 67 -- app/code/Magento/Rule/composer.json | 29 - app/code/Magento/Rule/etc/module.xml | 14 - app/code/Magento/Rule/i18n/en_US.csv | 34 - app/code/Magento/Rule/registration.php | 9 - .../web/conditions-data-normalizer.js | 140 --- .../Magento/Rule/view/adminhtml/web/rules.js | 443 --------- .../Controller/Adminhtml/Promo/Quote.php | 38 +- .../Adminhtml/Promo/Quote/NewActionHtml.php | 42 +- .../Promo/Quote/NewConditionHtml.php | 42 +- .../Adminhtml/Promo/Quote/NewHtml.php | 79 ++ 53 files changed, 248 insertions(+), 7080 deletions(-) create mode 100644 app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewHtml.php delete mode 100644 app/code/Magento/Rule/Block/Actions.php delete mode 100644 app/code/Magento/Rule/Block/Conditions.php delete mode 100644 app/code/Magento/Rule/Block/Editable.php delete mode 100644 app/code/Magento/Rule/Block/Newchild.php delete mode 100644 app/code/Magento/Rule/Block/Rule.php delete mode 100644 app/code/Magento/Rule/LICENSE.txt delete mode 100644 app/code/Magento/Rule/LICENSE_AFL.txt delete mode 100644 app/code/Magento/Rule/Model/AbstractModel.php delete mode 100644 app/code/Magento/Rule/Model/Action/AbstractAction.php delete mode 100644 app/code/Magento/Rule/Model/Action/ActionInterface.php delete mode 100644 app/code/Magento/Rule/Model/Action/Collection.php delete mode 100644 app/code/Magento/Rule/Model/ActionFactory.php delete mode 100644 app/code/Magento/Rule/Model/Condition/AbstractCondition.php delete mode 100644 app/code/Magento/Rule/Model/Condition/Combine.php delete mode 100644 app/code/Magento/Rule/Model/Condition/ConditionInterface.php delete mode 100644 app/code/Magento/Rule/Model/Condition/Context.php delete mode 100644 app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php delete mode 100644 app/code/Magento/Rule/Model/Condition/Sql/Builder.php delete mode 100644 app/code/Magento/Rule/Model/Condition/Sql/Expression.php delete mode 100644 app/code/Magento/Rule/Model/ConditionFactory.php delete mode 100644 app/code/Magento/Rule/Model/Renderer/Actions.php delete mode 100644 app/code/Magento/Rule/Model/Renderer/Conditions.php delete mode 100644 app/code/Magento/Rule/Model/ResourceModel/AbstractResource.php delete mode 100644 app/code/Magento/Rule/Model/ResourceModel/Rule/Collection/AbstractCollection.php delete mode 100644 app/code/Magento/Rule/README.md delete mode 100644 app/code/Magento/Rule/Test/Mftf/Helper/RuleHelper.php delete mode 100644 app/code/Magento/Rule/Test/Mftf/LICENSE.txt delete mode 100644 app/code/Magento/Rule/Test/Mftf/LICENSE_AFL.txt delete mode 100644 app/code/Magento/Rule/Test/Mftf/README.md delete mode 100644 app/code/Magento/Rule/Test/Unit/Model/AbstractModelTest.php delete mode 100644 app/code/Magento/Rule/Test/Unit/Model/ActionFactoryTest.php delete mode 100644 app/code/Magento/Rule/Test/Unit/Model/Condition/AbstractConditionTest.php delete mode 100644 app/code/Magento/Rule/Test/Unit/Model/Condition/CombineTest.php delete mode 100644 app/code/Magento/Rule/Test/Unit/Model/Condition/Product/AbstractProductTest.php delete mode 100644 app/code/Magento/Rule/Test/Unit/Model/Condition/Sql/BuilderTest.php delete mode 100644 app/code/Magento/Rule/Test/Unit/Model/Condition/Sql/ExpressionTest.php delete mode 100644 app/code/Magento/Rule/Test/Unit/Model/ConditionFactoryTest.php delete mode 100644 app/code/Magento/Rule/Test/Unit/Model/Renderer/ActionsTest.php delete mode 100644 app/code/Magento/Rule/Test/Unit/Model/Renderer/ConditionsTest.php delete mode 100644 app/code/Magento/Rule/composer.json delete mode 100644 app/code/Magento/Rule/etc/module.xml delete mode 100644 app/code/Magento/Rule/i18n/en_US.csv delete mode 100644 app/code/Magento/Rule/registration.php delete mode 100644 app/code/Magento/Rule/view/adminhtml/web/conditions-data-normalizer.js delete mode 100644 app/code/Magento/Rule/view/adminhtml/web/rules.js create mode 100644 app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/NewHtml.php diff --git a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog.php b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog.php index c0c4b5c6fa12c..58566b57bf5df 100644 --- a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog.php +++ b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog.php @@ -43,7 +43,7 @@ abstract class Catalog extends Action /** * Date filter instance * - * @var \Magento\Framework\Stdlib\DateTime\Filter\Date + * @var Date */ protected $_dateFilter; diff --git a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewActionHtml.php b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewActionHtml.php index 65a73b62fd705..91135d027e475 100644 --- a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewActionHtml.php +++ b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewActionHtml.php @@ -4,15 +4,17 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ -namespace Magento\CatalogRule\Controller\Adminhtml\Promo\Catalog; -use Magento\Rule\Model\Action\AbstractAction; +declare(strict_types=1); +namespace Magento\CatalogRule\Controller\Adminhtml\Promo\Catalog; /** * @SuppressWarnings(PHPMD.AllPurposeAction) */ -class NewActionHtml extends \Magento\CatalogRule\Controller\Adminhtml\Promo\Catalog +class NewActionHtml extends NewHtml { + protected string $typeChecked = 'Magento\Rule\Model\Action\AbstractAction'; + /** * Execute new action html. * @@ -24,21 +26,21 @@ public function execute() $typeArr = explode('|', str_replace('-', '/', $this->getRequest()->getParam('type', ''))); $type = $typeArr[0]; - $model = $this->_objectManager->create($type) - ->setId($id) - ->setType($type) - ->setRule($this->_objectManager->create(\Magento\CatalogRule\Model\Rule::class)) - ->setPrefix('actions'); + $model = $this->_objectManager->create($type); + if ($this->verifyClassName($model)) { + $model->setId($id) + ->setType($type) + ->setRule($this->_objectManager->create(\Magento\CatalogRule\Model\Rule::class)) + ->setPrefix('actions'); - if (!empty($typeArr[1])) { - $model->setAttribute($typeArr[1]); - } + if (!empty($typeArr[1])) { + $model->setAttribute($typeArr[1]); + } - if ($model instanceof AbstractAction) { $model->setJsFormObject($this->getRequest()->getParam('form')); $html = $model->asHtmlRecursive(); - } else { - $html = ''; + }else { + $html = $this->getErrorJson(); } $this->getResponse()->setBody($html); } diff --git a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewConditionHtml.php b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewConditionHtml.php index 2aaaddf1e2b34..1849ad6f53a12 100644 --- a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewConditionHtml.php +++ b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewConditionHtml.php @@ -4,15 +4,18 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + +declare(strict_types=1); namespace Magento\CatalogRule\Controller\Adminhtml\Promo\Catalog; +use Magento\CatalogRule\Model\Rule; use Magento\Framework\App\Action\HttpGetActionInterface; use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface; -use Magento\Rule\Model\Condition\AbstractCondition; -use Magento\CatalogRule\Controller\Adminhtml\Promo\Catalog as CatalogAction; -class NewConditionHtml extends CatalogAction implements HttpPostActionInterface, HttpGetActionInterface +class NewConditionHtml extends NewHtml implements HttpPostActionInterface, HttpGetActionInterface { + protected string $typeChecked = 'Magento\Rule\Model\Condition\AbstractCondition'; + /** * Execute new condition html. * @@ -25,23 +28,25 @@ public function execute() $typeArr = explode('|', str_replace('-', '/', $this->getRequest()->getParam('type', ''))); $type = $typeArr[0]; - $model = $this->_objectManager->create($type) - ->setId($id) - ->setType($type) - ->setRule($this->_objectManager->create(\Magento\CatalogRule\Model\Rule::class)) - ->setPrefix('conditions'); + $model = $this->_objectManager->create($type); - if (!empty($typeArr[1])) { - $model->setAttribute($typeArr[1]); - } + if ($this->verifyClassName($model)) { + $model->setId($id) + ->setType($type) + ->setRule($this->_objectManager->create(Rule::class)) + ->setPrefix('conditions'); + + if (!empty($typeArr[1])) { + $model->setAttribute($typeArr[1]); + } - if ($model instanceof AbstractCondition) { $model->setJsFormObject($this->getRequest()->getParam('form')); $model->setFormName($formName); $html = $model->asHtmlRecursive(); } else { - $html = ''; + $html = $this->getErrorJson(); } + $this->getResponse()->setBody($html); } } diff --git a/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewHtml.php b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewHtml.php new file mode 100644 index 0000000000000..7f80e0967492c --- /dev/null +++ b/app/code/Magento/CatalogRule/Controller/Adminhtml/Promo/Catalog/NewHtml.php @@ -0,0 +1,69 @@ +serializer = $serializer; + } + + /** + * Verify class instance + * + * @param mixed $verifyClass + * @return bool + */ + public function verifyClassName($verifyClass): bool + { + if ($verifyClass instanceof $this->typeChecked) { + return true; + } + + return false; + } + + /** + * Get Error json + * + * @return bool|string + */ + protected function getErrorJson() + { + return $this->serializer->serialize( + [ + 'error' => true, + 'message' => __('Selected type is not inherited from type %1', $this->typeChecked) + ] + ); + } +} \ No newline at end of file diff --git a/app/code/Magento/Rule/Block/Actions.php b/app/code/Magento/Rule/Block/Actions.php deleted file mode 100644 index a192cadf447ba..0000000000000 --- a/app/code/Magento/Rule/Block/Actions.php +++ /dev/null @@ -1,23 +0,0 @@ -getRule() && $element->getRule()->getActions()) { - return $element->getRule()->getActions()->asHtmlRecursive(); - } - return ''; - } -} diff --git a/app/code/Magento/Rule/Block/Conditions.php b/app/code/Magento/Rule/Block/Conditions.php deleted file mode 100644 index e22a95cd1dad1..0000000000000 --- a/app/code/Magento/Rule/Block/Conditions.php +++ /dev/null @@ -1,23 +0,0 @@ -getRule() && $element->getRule()->getConditions()) { - return $element->getRule()->getConditions()->asHtmlRecursive(); - } - return ''; - } -} diff --git a/app/code/Magento/Rule/Block/Editable.php b/app/code/Magento/Rule/Block/Editable.php deleted file mode 100644 index 57bbc72ff2660..0000000000000 --- a/app/code/Magento/Rule/Block/Editable.php +++ /dev/null @@ -1,101 +0,0 @@ -inlineTranslate = $inlineTranslate; - parent::__construct($context, $data); - } - - /** - * Render element - * - * @param \Magento\Framework\Data\Form\Element\AbstractElement $element - * @return string - * - * @see RendererInterface::render() - */ - public function render(\Magento\Framework\Data\Form\Element\AbstractElement $element) - { - $element->addClass('element-value-changer'); - $valueName = $element->getValueName(); - - if ($valueName === '') { - $valueName = '...'; - } - - if ($element->getShowAsText()) { - $html = ' ' . - $this->escapeHtml( - $valueName - ) . ' '; - } else { - $html = ' getParamId() ? ' id="' . - $element->getParamId() . - '"' : '') . - '>' . - ''; - - if ($this->inlineTranslate->isAllowed()) { - $html .= $this->escapeHtml($valueName); - } else { - $html .= $this->escapeHtml( - $this->filterManager->truncate($valueName, ['length' => 33, 'etc' => '...']) - ); - } - - $html .= ' ' . $element->getElementHtml(); - - if ($element->getExplicitApply()) { - $html .= ' ' . __(
-                    'Apply'
-                ) . ' '; - } - - $html .= ' '; - } - - return $html; - } -} diff --git a/app/code/Magento/Rule/Block/Newchild.php b/app/code/Magento/Rule/Block/Newchild.php deleted file mode 100644 index 859b92b03e3b0..0000000000000 --- a/app/code/Magento/Rule/Block/Newchild.php +++ /dev/null @@ -1,32 +0,0 @@ -addClass('element-value-changer'); - $html = ' getParamId() ? ' id="' . - $element->getParamId() . - '"' : '') . - '>'; - $html .= ''; - $html .= $element->getValueName(); - $html .= ''; - $html .= $element->getElementHtml(); - $html .= ' '; - return $html; - } -} diff --git a/app/code/Magento/Rule/Block/Rule.php b/app/code/Magento/Rule/Block/Rule.php deleted file mode 100644 index 09babc242bf24..0000000000000 --- a/app/code/Magento/Rule/Block/Rule.php +++ /dev/null @@ -1,10 +0,0 @@ -" or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process. \ No newline at end of file diff --git a/app/code/Magento/Rule/LICENSE_AFL.txt b/app/code/Magento/Rule/LICENSE_AFL.txt deleted file mode 100644 index f39d641b18a19..0000000000000 --- a/app/code/Magento/Rule/LICENSE_AFL.txt +++ /dev/null @@ -1,48 +0,0 @@ - -Academic Free License ("AFL") v. 3.0 - -This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work: - -Licensed under the Academic Free License version 3.0 - - 1. Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following: - - 1. to reproduce the Original Work in copies, either alone or as part of a collective work; - - 2. to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work; - - 3. to distribute or communicate copies of the Original Work and Derivative Works to the public, under any license of your choice that does not contradict the terms and conditions, including Licensor's reserved rights and remedies, in this Academic Free License; - - 4. to perform the Original Work publicly; and - - 5. to display the Original Work publicly. - - 2. Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works. - - 3. Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work. - - 4. Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license. - - 5. External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c). - - 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. - - 7. Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer. - - 8. Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation. - - 9. Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including "fair use" or "fair dealing"). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c). - - 10. Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware. - - 11. Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License. - - 12. Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License. - - 13. Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. - - 14. Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - - 15. Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You. - - 16. Modification of This License. This License is Copyright © 2005 Lawrence Rosen. Permission is granted to copy, distribute, or communicate this License without modification. Nothing in this License permits You to modify this License as applied to the Original Work or to Derivative Works. However, You may modify the text of this License and copy, distribute or communicate your modified version (the "Modified License") and apply it to other original works of authorship subject to the following conditions: (i) You may not indicate in any way that your Modified License is the "Academic Free License" or "AFL" and you may not use those names in the name of your Modified License; (ii) You must replace the notice specified in the first paragraph above with the notice "Licensed under " or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process. diff --git a/app/code/Magento/Rule/Model/AbstractModel.php b/app/code/Magento/Rule/Model/AbstractModel.php deleted file mode 100644 index 58c18093c3bab..0000000000000 --- a/app/code/Magento/Rule/Model/AbstractModel.php +++ /dev/null @@ -1,509 +0,0 @@ -_formFactory = $formFactory; - $this->_localeDate = $localeDate; - $this->serializer = $serializer ?: \Magento\Framework\App\ObjectManager::getInstance()->get( - \Magento\Framework\Serialize\Serializer\Json::class - ); - parent::__construct( - $context, - $registry, - $extensionFactory ?: $this->getExtensionFactory(), - $customAttributeFactory ?: $this->getCustomAttributeFactory(), - $resource, - $resourceCollection, - $data - ); - } - - /** - * Prepare data before saving - * - * @return $this - * @throws \Magento\Framework\Exception\LocalizedException - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function beforeSave() - { - // Check if discount amount not negative - if ($this->hasDiscountAmount()) { - if ((int)$this->getDiscountAmount() < 0) { - throw new \Magento\Framework\Exception\LocalizedException(__('Please choose a valid discount amount.')); - } - } - - // Serialize conditions - if ($this->getConditions()) { - $this->setConditionsSerialized($this->serializer->serialize($this->getConditions()->asArray())); - $this->_conditions = null; - } - - // Serialize actions - if ($this->getActions()) { - $this->setActionsSerialized($this->serializer->serialize($this->getActions()->asArray())); - $this->_actions = null; - } - - /** - * Prepare website Ids if applicable and if they were set as string in comma separated format. - * Backwards compatibility. - */ - if ($this->hasWebsiteIds()) { - $websiteIds = $this->getWebsiteIds(); - if (is_string($websiteIds) && !empty($websiteIds)) { - $this->setWebsiteIds(explode(',', $websiteIds)); - } - } - - /** - * Prepare customer group Ids if applicable and if they were set as string in comma separated format. - * Backwards compatibility. - */ - if ($this->hasCustomerGroupIds()) { - $groupIds = $this->getCustomerGroupIds(); - if (is_string($groupIds) && !empty($groupIds)) { - $this->setCustomerGroupIds(explode(',', $groupIds)); - } - } - - parent::beforeSave(); - return $this; - } - - /** - * Set rule combine conditions model - * - * @param \Magento\Rule\Model\Condition\Combine $conditions - * @return $this - */ - public function setConditions($conditions) - { - $this->_conditions = $conditions; - return $this; - } - - /** - * Retrieve rule combine conditions model - * - * @return \Magento\Rule\Model\Condition\Combine - */ - public function getConditions() - { - if (empty($this->_conditions)) { - $this->_resetConditions(); - } - - // Load rule conditions if it is applicable - if ($this->hasConditionsSerialized()) { - $conditions = $this->getConditionsSerialized(); - if (!empty($conditions)) { - $conditions = $this->serializer->unserialize($conditions); - if (is_array($conditions) && !empty($conditions)) { - $this->_conditions->loadArray($conditions); - } - } - $this->unsConditionsSerialized(); - } - - return $this->_conditions; - } - - /** - * Set rule actions model - * - * @param \Magento\Rule\Model\Action\Collection $actions - * @return $this - */ - public function setActions($actions) - { - $this->_actions = $actions; - return $this; - } - - /** - * Retrieve rule actions model - * - * @return \Magento\Rule\Model\Action\Collection - */ - public function getActions() - { - if (!$this->_actions) { - $this->_resetActions(); - } - - // Load rule actions if it is applicable - if ($this->hasActionsSerialized()) { - $actions = $this->getActionsSerialized(); - if (!empty($actions)) { - $actions = $this->serializer->unserialize($actions); - if (is_array($actions) && !empty($actions)) { - $this->_actions->loadArray($actions); - } - } - $this->unsActionsSerialized(); - } - - return $this->_actions; - } - - /** - * Reset rule combine conditions - * - * @param null|\Magento\Rule\Model\Condition\Combine $conditions - * @return $this - */ - protected function _resetConditions($conditions = null) - { - if (null === $conditions) { - $conditions = $this->getConditionsInstance(); - } - $conditions->setRule($this)->setId('1')->setPrefix('conditions'); - $this->setConditions($conditions); - - return $this; - } - - /** - * Reset rule actions - * - * @param null|\Magento\Rule\Model\Action\Collection $actions - * @return $this - */ - protected function _resetActions($actions = null) - { - if (null === $actions) { - $actions = $this->getActionsInstance(); - } - $actions->setRule($this)->setId('1')->setPrefix('actions'); - $this->setActions($actions); - - return $this; - } - - /** - * Rule form getter - * - * @return \Magento\Framework\Data\Form - */ - public function getForm() - { - if (!$this->_form) { - $this->_form = $this->_formFactory->create(); - } - return $this->_form; - } - - /** - * Initialize rule model data from array - * - * @param array $data - * @return $this - */ - public function loadPost(array $data) - { - $arr = $this->_convertFlatToRecursive($data); - if (isset($arr['conditions'])) { - $this->getConditions()->setConditions([])->loadArray($arr['conditions'][1]); - } - if (isset($arr['actions'])) { - $this->getActions()->setActions([])->loadArray($arr['actions'][1], 'actions'); - } - - return $this; - } - - /** - * Set specified data to current rule. - * Set conditions and actions recursively. - * Convert dates into \DateTime. - * - * @param array $data - * @return array - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - protected function _convertFlatToRecursive(array $data) - { - $arr = []; - foreach ($data as $key => $value) { - if (($key === 'conditions' || $key === 'actions') && is_array($value)) { - foreach ($value as $id => $data) { - $path = explode('--', $id); - $node = & $arr; - for ($i = 0, $l = count($path); $i < $l; $i++) { - if (!isset($node[$key][$path[$i]])) { - $node[$key][$path[$i]] = []; - } - $node = & $node[$key][$path[$i]]; - } - foreach ($data as $k => $v) { - $node[$k] = $v; - } - } - } else { - /** - * Convert dates into \DateTime - */ - if (in_array($key, ['from_date', 'to_date'], true) && $value) { - $value = new \DateTime($value); - } - $this->setData($key, $value); - } - } - - return $arr; - } - - /** - * Validate rule conditions to determine if rule can run - * - * @param \Magento\Framework\DataObject $object - * @return bool - */ - public function validate(\Magento\Framework\DataObject $object) - { - return $this->getConditions()->validate($object); - } - - /** - * Validate rule data - * - * @param \Magento\Framework\DataObject $dataObject - * @return bool|string[] - return true if validation passed successfully. Array with errors description otherwise - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - public function validateData(\Magento\Framework\DataObject $dataObject) - { - $result = []; - $fromDate = $toDate = null; - - if ($dataObject->hasFromDate() && $dataObject->hasToDate()) { - $fromDate = $dataObject->getFromDate(); - $toDate = $dataObject->getToDate(); - } - - if ($fromDate && $toDate) { - $fromDate = new \DateTime($fromDate); - $toDate = new \DateTime($toDate); - - if ($fromDate > $toDate) { - $result[] = __('End Date must follow Start Date.'); - } - } - - if ($dataObject->hasWebsiteIds()) { - $websiteIds = $dataObject->getWebsiteIds(); - if (empty($websiteIds)) { - $result[] = __('Please specify a website.'); - } - } - if ($dataObject->hasCustomerGroupIds()) { - $customerGroupIds = $dataObject->getCustomerGroupIds(); - if (empty($customerGroupIds)) { - $result[] = __('Please specify Customer Groups.'); - } - } - - return !empty($result) ? $result : true; - } - - /** - * Check availability to delete rule - * - * @return bool - * @codeCoverageIgnore - */ - public function isDeleteable() - { - return $this->_isDeleteable; - } - - /** - * Set is rule can be deleted flag - * - * @param bool $value - * @return $this - * @codeCoverageIgnore - */ - public function setIsDeleteable($value) - { - $this->_isDeleteable = (bool)$value; - return $this; - } - - /** - * Check if rule is readonly - * - * @return bool - * @codeCoverageIgnore - */ - public function isReadonly() - { - return $this->_isReadonly; - } - - /** - * Set is readonly flag to rule - * - * @param bool $value - * @return $this - * @codeCoverageIgnore - */ - public function setIsReadonly($value) - { - $this->_isReadonly = (bool)$value; - return $this; - } - - /** - * Get rule associated website Ids - * - * @return array - */ - public function getWebsiteIds() - { - if (!$this->hasWebsiteIds()) { - $websiteIds = $this->_getResource()->getWebsiteIds($this->getId()); - $this->setData('website_ids', (array)$websiteIds); - } - return $this->_getData('website_ids'); - } - - /** - * Get extension factory - * - * @return \Magento\Framework\Api\ExtensionAttributesFactory - * @deprecated 100.1.0 - */ - private function getExtensionFactory() - { - return \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Framework\Api\ExtensionAttributesFactory::class); - } - - /** - * Get custom attribute factory - * - * @return \Magento\Framework\Api\AttributeValueFactory - * @deprecated 100.1.0 - */ - private function getCustomAttributeFactory() - { - return \Magento\Framework\App\ObjectManager::getInstance() - ->get(\Magento\Framework\Api\AttributeValueFactory::class); - } -} diff --git a/app/code/Magento/Rule/Model/Action/AbstractAction.php b/app/code/Magento/Rule/Model/Action/AbstractAction.php deleted file mode 100644 index 4d56f6cc56edc..0000000000000 --- a/app/code/Magento/Rule/Model/Action/AbstractAction.php +++ /dev/null @@ -1,371 +0,0 @@ -_assetRepo = $assetRepo; - $this->_layout = $layout; - - parent::__construct($data); - - $this->loadAttributeOptions()->loadOperatorOptions()->loadValueOptions(); - - $attributes = $this->getAttributeOption(); - if ($attributes) { - reset($attributes); - $this->setAttribute(key($attributes)); - } - - $operators = $this->getOperatorOption(); - if ($operators) { - reset($operators); - $this->setOperator(key($operators)); - } - } - - /** - * @return Form - */ - public function getForm() - { - return $this->getRule()->getForm(); - } - - /** - * @param array $arrAttributes - * @return array - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function asArray(array $arrAttributes = []) - { - $out = [ - 'type' => $this->getType(), - 'attribute' => $this->getAttribute(), - 'operator' => $this->getOperator(), - 'value' => $this->getValue(), - ]; - return $out; - } - - /** - * @return string - */ - public function asXml() - { - $xml = "" . - $this->getType() . - "" . - "" . - $this->getAttribute() . - "" . - "" . - $this->getOperator() . - "" . - "" . - $this->getValue() . - ""; - return $xml; - } - - /** - * @param array $arr - * @return $this - */ - public function loadArray(array $arr) - { - $this->addData( - [ - 'type' => $arr['type'], - 'attribute' => $arr['attribute'], - 'operator' => $arr['operator'], - 'value' => $arr['value'], - ] - ); - $this->loadAttributeOptions(); - $this->loadOperatorOptions(); - $this->loadValueOptions(); - return $this; - } - - /** - * @return $this - */ - public function loadAttributeOptions() - { - $this->setAttributeOption([]); - return $this; - } - - /** - * @return array - */ - public function getAttributeSelectOptions() - { - $opt = []; - foreach ($this->getAttributeOption() as $key => $value) { - $opt[] = ['value' => $key, 'label' => $value]; - } - return $opt; - } - - /** - * @return string - */ - public function getAttributeName() - { - return $this->getAttributeOption($this->getAttribute()); - } - - /** - * @return $this - */ - public function loadOperatorOptions() - { - $this->setOperatorOption(['=' => __('to'), '+=' => __('by')]); - return $this; - } - - /** - * @return array - */ - public function getOperatorSelectOptions() - { - $opt = []; - foreach ($this->getOperatorOption() as $k => $v) { - $opt[] = ['value' => $k, 'label' => $v]; - } - return $opt; - } - - /** - * @return string - */ - public function getOperatorName() - { - return $this->getOperatorOption($this->getOperator()); - } - - /** - * @return $this - */ - public function loadValueOptions() - { - $this->setValueOption([]); - return $this; - } - - /** - * @return array - */ - public function getValueSelectOptions() - { - $opt = []; - foreach ($this->getValueOption() as $key => $value) { - $opt[] = ['value' => $key, 'label' => $value]; - } - return $opt; - } - - /** - * @return string - */ - public function getValueName() - { - $value = $this->getValue(); - return !empty($value) || 0 === $value ? $value : '...'; - } - - /** - * @return array - */ - public function getNewChildSelectOptions() - { - return [['value' => '', 'label' => __('Please choose an action to add.')]]; - } - - /** - * @return string - */ - public function getNewChildName() - { - return $this->getAddLinkHtml(); - } - - /** - * @return string - */ - public function asHtml() - { - return ''; - } - - /** - * @return string - */ - public function asHtmlRecursive() - { - $str = $this->asHtml(); - return $str; - } - - /** - * @return AbstractElement - */ - public function getTypeElement() - { - return $this->getForm()->addField( - 'action:' . $this->getId() . ':type', - 'hidden', - [ - 'name' => $this->elementName . '[actions][' . $this->getId() . '][type]', - 'value' => $this->getType(), - 'no_span' => true - ] - ); - } - - /** - * @return $this - */ - public function getAttributeElement() - { - return $this->getForm()->addField( - 'action:' . $this->getId() . ':attribute', - 'select', - [ - 'name' => $this->elementName . '[actions][' . $this->getId() . '][attribute]', - 'values' => $this->getAttributeSelectOptions(), - 'value' => $this->getAttribute(), - 'value_name' => $this->getAttributeName() - ] - )->setRenderer( - $this->_layout->getBlockSingleton(\Magento\Rule\Block\Editable::class) - ); - } - - /** - * @return $this - */ - public function getOperatorElement() - { - return $this->getForm()->addField( - 'action:' . $this->getId() . ':operator', - 'select', - [ - 'name' => $this->elementName . '[actions][' . $this->getId() . '][operator]', - 'values' => $this->getOperatorSelectOptions(), - 'value' => $this->getOperator(), - 'value_name' => $this->getOperatorName() - ] - )->setRenderer( - $this->_layout->getBlockSingleton(\Magento\Rule\Block\Editable::class) - ); - } - - /** - * @return $this - */ - public function getValueElement() - { - return $this->getForm()->addField( - 'action:' . $this->getId() . ':value', - 'text', - [ - 'name' => $this->elementName . '[actions][' . $this->getId() . '][value]', - 'value' => $this->getValue(), - 'value_name' => $this->getValueName() - ] - )->setRenderer( - $this->_layout->getBlockSingleton(\Magento\Rule\Block\Editable::class) - ); - } - - /** - * @return string - */ - public function getAddLinkHtml() - { - $src = $this->_assetRepo->getUrl('images/rule_component_add.gif'); - $html = ''; - return $html; - } - - /** - * @return string - */ - public function getRemoveLinkHtml() - { - $src = $this->_assetRepo->getUrl('images/rule_component_remove.gif'); - $html = ''; - return $html; - } - - /** - * @param string $format - * @return string - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function asString($format = '') - { - return ""; - } - - /** - * @param int $level - * @return string - */ - public function asStringRecursive($level = 0) - { - $str = str_pad('', $level * 3, ' ', STR_PAD_LEFT) . $this->asString(); - return $str; - } - - /** - * @return $this - */ - public function process() - { - return $this; - } -} diff --git a/app/code/Magento/Rule/Model/Action/ActionInterface.php b/app/code/Magento/Rule/Model/Action/ActionInterface.php deleted file mode 100644 index de3246f064780..0000000000000 --- a/app/code/Magento/Rule/Model/Action/ActionInterface.php +++ /dev/null @@ -1,14 +0,0 @@ -_actionFactory = $actionFactory; - $this->_layout = $layout; - - parent::__construct($assetRepo, $layout, $data); - - $this->setActions([]); - $this->setType(\Magento\Rule\Model\Action\Collection::class); - } - - /** - * Returns array containing actions in the collection - * - * Output example: - * array( - * {action::asArray}, - * {action::asArray} - * ) - * - * @param array $arrAttributes - * @return array - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function asArray(array $arrAttributes = []) - { - $out = parent::asArray(); - - foreach ($this->getActions() as $item) { - $out['actions'][] = $item->asArray(); - } - return $out; - } - - /** - * Load array - * - * @param array $arr - * @return $this - */ - public function loadArray(array $arr) - { - if (!empty($arr['actions']) && is_array($arr['actions'])) { - foreach ($arr['actions'] as $actArr) { - if (empty($actArr['type'])) { - continue; - } - $action = $this->_actionFactory->create($actArr['type']); - $action->loadArray($actArr); - $this->addAction($action); - } - } - return $this; - } - - /** - * Add actions - * - * @param ActionInterface $action - * @return $this - */ - public function addAction(ActionInterface $action) - { - $actions = $this->getActions(); - - $action->setRule($this->getRule()); - - $actions[] = $action; - if (!$action->getId()) { - $action->setId($this->getId() . '.' . count($actions)); - } - - $this->setActions($actions); - return $this; - } - - /** - * As html - * - * @return string - */ - public function asHtml() - { - $html = $this->getTypeElement()->toHtml() . 'Perform following actions: '; - if ($this->getId() != '1') { - $html .= $this->getRemoveLinkHtml(); - } - return $html; - } - - /** - * Return new child element - * - * @return $this - */ - public function getNewChildElement() - { - return $this->getForm()->addField( - 'action:' . $this->getId() . ':new_child', - 'select', - [ - 'name' => $this->elementName . '[actions][' . $this->getId() . '][new_child]', - 'values' => $this->getNewChildSelectOptions(), - 'value_name' => $this->getNewChildName() - ] - )->setRenderer( - $this->_layout->getBlockSingleton(\Magento\Rule\Block\Newchild::class) - ); - } - - /** - * Return as html recursive - * - * @return string - */ - public function asHtmlRecursive() - { - $html = $this->asHtml() . ''; - return $html; - } - - /** - * Add string - * - * @param string $format - * @return string - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function asString($format = '') - { - $str = __("Perform following actions"); - return $str; - } - - /** - * Return string as recursive - * - * @param int $level - * @return string - */ - public function asStringRecursive($level = 0) - { - $str = $this->asString(); - foreach ($this->getActions() as $action) { - $str .= "\n" . $action->asStringRecursive($level + 1); - } - return $str; - } - - /** - * Process - * - * @return $this - */ - public function process() - { - foreach ($this->getActions() as $action) { - $action->process(); - } - return $this; - } -} diff --git a/app/code/Magento/Rule/Model/ActionFactory.php b/app/code/Magento/Rule/Model/ActionFactory.php deleted file mode 100644 index 0f07c9e227893..0000000000000 --- a/app/code/Magento/Rule/Model/ActionFactory.php +++ /dev/null @@ -1,39 +0,0 @@ -_objectManager = $objectManager; - } - - /** - * Create new action object - * - * @param string $type - * @param array $data - * @return \Magento\Rule\Model\Action\ActionInterface - */ - public function create($type, array $data = []) - { - return $this->_objectManager->create($type, $data); - } -} diff --git a/app/code/Magento/Rule/Model/Condition/AbstractCondition.php b/app/code/Magento/Rule/Model/Condition/AbstractCondition.php deleted file mode 100644 index d5d3b80755360..0000000000000 --- a/app/code/Magento/Rule/Model/Condition/AbstractCondition.php +++ /dev/null @@ -1,925 +0,0 @@ -_assetRepo = $context->getAssetRepository(); - $this->_localeDate = $context->getLocaleDate(); - $this->_layout = $context->getLayout(); - - parent::__construct($data); - - $this->loadAttributeOptions()->loadOperatorOptions()->loadValueOptions(); - - $options = $this->getAttributeOptions(); - if ($options) { - reset($options); - $this->setAttribute(key($options)); - } - $options = $this->getOperatorOptions(); - if ($options) { - reset($options); - $this->setOperator(key($options)); - } - } - - /** - * Default operator input by type map getter - * - * @return array - */ - public function getDefaultOperatorInputByType() - { - if (null === $this->_defaultOperatorInputByType) { - $this->_defaultOperatorInputByType = [ - 'string' => ['==', '!=', '>=', '>', '<=', '<', '{}', '!{}', '()', '!()'], - 'numeric' => ['==', '!=', '>=', '>', '<=', '<', '()', '!()'], - 'date' => ['==', '>=', '<='], - 'select' => ['==', '!=', '<=>'], - 'boolean' => ['==', '!=', '<=>'], - 'multiselect' => ['{}', '!{}', '()', '!()'], - 'grid' => ['()', '!()'], - ]; - $this->_arrayInputTypes = ['multiselect', 'grid']; - } - return $this->_defaultOperatorInputByType; - } - - /** - * Default operator options getter. - * - * Provides all possible operator options. - * - * @return array - */ - public function getDefaultOperatorOptions() - { - if (null === $this->_defaultOperatorOptions) { - $this->_defaultOperatorOptions = [ - '==' => __('is'), - '!=' => __('is not'), - '>=' => __('equals or greater than'), - '<=' => __('equals or less than'), - '>' => __('greater than'), - '<' => __('less than'), - '{}' => __('contains'), - '!{}' => __('does not contain'), - '()' => __('is one of'), - '!()' => __('is not one of'), - '<=>' => __('is undefined'), - ]; - } - return $this->_defaultOperatorOptions; - } - - /** - * Get rule form. - * - * @return Form - */ - public function getForm() - { - return $this->getRule()->getForm(); - } - - /** - * Get condition as array. - * - * @param array $arrAttributes - * @return array - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function asArray(array $arrAttributes = []) - { - return [ - 'type' => $this->getType(), - 'attribute' => $this->getAttribute(), - 'operator' => $this->getOperator(), - 'value' => $this->getValue(), - 'is_value_processed' => $this->getIsValueParsed(), - ]; - } - - /** - * Get tables to join - * - * @return array - */ - public function getTablesToJoin() - { - return []; - } - - /** - * Get value to bind - * - * @return array|float|int|mixed|string - */ - public function getBindArgumentValue() - { - return $this->getValueParsed(); - } - - /** - * Get field by attribute - * - * @return string - */ - public function getMappedSqlField() - { - return $this->getAttribute(); - } - - /** - * Get condition as xml. - * - * @return string - */ - public function asXml() - { - return "" . - $this->getType() . - "" . - "" . - $this->getAttribute() . - "" . - "" . - $this->getOperator() . - "" . - "" . - $this->getValue() . - ""; - } - - /** - * Load condition from array. - * - * @param array $arr - * @return $this - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - public function loadArray($arr) - { - $this->setType($arr['type']); - $this->setAttribute(isset($arr['attribute']) ? $arr['attribute'] : false); - $this->setOperator(isset($arr['operator']) ? $arr['operator'] : false); - $this->setValue(isset($arr['value']) ? $arr['value'] : false); - $this->setIsValueParsed(isset($arr['is_value_parsed']) ? $arr['is_value_parsed'] : false); - return $this; - } - - /** - * Load condition from xml. - * - * @param string|array $xml - * @return $this - */ - public function loadXml($xml) - { - if (is_string($xml)) { - $xml = simplexml_load_string($xml); - } - $this->loadArray((array)$xml); - return $this; - } - - /** - * Load attribute options. - * - * @return $this - */ - public function loadAttributeOptions() - { - return $this; - } - - /** - * Get attribute options. - * - * @return array - */ - public function getAttributeOptions() - { - return []; - } - - /** - * Get attribute select options. - * - * @return array - */ - public function getAttributeSelectOptions() - { - $opt = []; - foreach ($this->getAttributeOption() as $key => $value) { - $opt[] = ['value' => $key, 'label' => $value]; - } - return $opt; - } - - /** - * Get attribute name. - * - * @return string - */ - public function getAttributeName() - { - return $this->getAttributeOption($this->getAttribute()); - } - - /** - * Load operator options. - * - * @return $this - */ - public function loadOperatorOptions() - { - $this->setOperatorOption($this->getDefaultOperatorOptions()); - $this->setOperatorByInputType($this->getDefaultOperatorInputByType()); - return $this; - } - - /** - * This value will define which operators will be available for this condition. - * - * Possible values are: string, numeric, date, select, multiselect, grid, boolean - * - * @return string - */ - public function getInputType() - { - return null === $this->_inputType ? 'string' : $this->_inputType; - } - - /** - * Get operator select options. - * - * @return array - */ - public function getOperatorSelectOptions() - { - $type = $this->getInputType(); - $opt = []; - $operatorByType = $this->getOperatorByInputType(); - foreach ($this->getOperatorOption() as $key => $value) { - if (!$operatorByType || in_array($key, $operatorByType[$type])) { - $opt[] = ['value' => $key, 'label' => $value]; - } - } - return $opt; - } - - /** - * Get operator name. - * - * @return array - */ - public function getOperatorName() - { - return $this->getOperatorOption($this->getOperator()); - } - - /** - * Load value options. - * - * @return $this - */ - public function loadValueOptions() - { - $this->setValueOption([]); - return $this; - } - - /** - * Get value select options. - * - * @return array - */ - public function getValueSelectOptions() - { - $opt = []; - if ($this->hasValueOption()) { - foreach ((array)$this->getValueOption() as $key => $value) { - $opt[] = ['value' => $key, 'label' => $value]; - } - } - return $opt; - } - - /** - * Retrieve parsed value - * - * @return array|string|int|float - */ - public function getValueParsed() - { - if (!$this->hasValueParsed()) { - $value = $this->getValue(); - if (is_array($value) && count($value) === 1) { - $value = reset($value); - } - if (!is_array($value) && $this->isArrayOperatorType() && $value) { - $value = preg_split('#\s*[,;]\s*#', (string) $value, -1, PREG_SPLIT_NO_EMPTY); - } - $this->setValueParsed($value); - } - return $this->getData('value_parsed'); - } - - /** - * Check if value should be array - * - * Depends on operator input type - * - * @return bool - */ - public function isArrayOperatorType() - { - $operator = $this->getOperator(); - return $operator === '()' || $operator === '!()' || in_array($this->getInputType(), $this->_arrayInputTypes); - } - - /** - * Get value. - * - * @return mixed - */ - public function getValue() - { - if ($this->getInputType() == 'date' && !$this->getIsValueParsed()) { - // date format intentionally hard-coded - $date = $this->getData('value'); - $date = (\is_numeric($date) ? '@' : '') . $date; - $this->setValue( - (new \DateTime($date, new \DateTimeZone((string) $this->_localeDate->getConfigTimezone()))) - ->format('Y-m-d H:i:s') - ); - $this->setIsValueParsed(true); - } - return $this->getData('value'); - } - - /** - * Get value name. - * - * @return array|string - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * phpcs:disable Generic.Metrics.NestingLevel - */ - public function getValueName() - { - $value = $this->getValue(); - if ($value === null || '' === $value) { - return '...'; - } - - $options = $this->getValueSelectOptions(); - $valueArr = []; - if (!empty($options)) { - foreach ($options as $option) { - if (is_array($value)) { - if (in_array($option['value'], $value)) { - $valueArr[] = $option['label']; - } - } elseif (isset($option['value'])) { - if (is_array($option['value'])) { - foreach ($option['value'] as $optionValue) { - if ($optionValue['value'] == $value) { - return $optionValue['label']; - } - } - } - if ($option['value'] == $value) { - return $option['label']; - } - } - } - } - if (!empty($valueArr)) { - $value = implode(', ', $valueArr); - } elseif (is_array($value)) { - $value = implode(', ', $value); - } - return $value; - } - //phpcs:enable Generic.Metrics.NestingLevel - - /** - * Get inherited conditions selectors - * - * @return array - */ - public function getNewChildSelectOptions() - { - return [['value' => '', 'label' => __('Please choose a condition to add.')]]; - } - - /** - * Get new child name. - * - * @return string - */ - public function getNewChildName() - { - return $this->getAddLinkHtml(); - } - - /** - * Get this condition as html. - * - * @return string - */ - public function asHtml() - { - return $this->getTypeElementHtml() . - $this->getAttributeElementHtml() . - $this->getOperatorElementHtml() . - $this->getValueElementHtml() . - $this->getRemoveLinkHtml() . - $this->getChooserContainerHtml(); - } - - /** - * Get this condition with subconditions as html. - * - * @return string - */ - public function asHtmlRecursive() - { - return $this->asHtml(); - } - - /** - * Get type element. - * - * @return AbstractElement - */ - public function getTypeElement() - { - return $this->getForm()->addField( - $this->getPrefix() . '__' . $this->getId() . '__type', - 'hidden', - [ - 'name' => $this->elementName . '[' . $this->getPrefix() . '][' . $this->getId() . '][type]', - 'value' => $this->getType(), - 'no_span' => true, - 'class' => 'hidden', - 'data-form-part' => $this->getFormName() - ] - ); - } - - /** - * Get type element html. - * - * @return string - */ - public function getTypeElementHtml() - { - return $this->getTypeElement()->getHtml(); - } - - /** - * Get attribute element. - * - * @return $this - */ - public function getAttributeElement() - { - if (null === $this->getAttribute()) { - $options = $this->getAttributeOption(); - if ($options) { - reset($options); - $this->setAttribute(key($options)); - } - } - return $this->getForm()->addField( - $this->getPrefix() . '__' . $this->getId() . '__attribute', - 'select', - [ - 'name' => $this->elementName . '[' . $this->getPrefix() . '][' . $this->getId() . '][attribute]', - 'values' => $this->getAttributeSelectOptions(), - 'value' => $this->getAttribute(), - 'value_name' => $this->getAttributeName(), - 'data-form-part' => $this->getFormName() - ] - )->setRenderer( - $this->_layout->getBlockSingleton(\Magento\Rule\Block\Editable::class) - ); - } - - /** - * Get attribute element html. - * - * @return string - */ - public function getAttributeElementHtml() - { - return $this->getAttributeElement()->getHtml(); - } - - /** - * Retrieve Condition Operator element Instance. - * - * If the operator value is empty - define first available operator value as default. - * - * @return \Magento\Framework\Data\Form\Element\Select - */ - public function getOperatorElement() - { - $options = $this->getOperatorSelectOptions(); - if ($this->getOperator() === null) { - $option = reset($options); - $this->setOperator($option['value']); - } - - $elementId = sprintf('%s__%s__operator', $this->getPrefix(), $this->getId()); - $elementName = sprintf($this->elementName . '[%s][%s][operator]', $this->getPrefix(), $this->getId()); - $element = $this->getForm()->addField( - $elementId, - 'select', - [ - 'name' => $elementName, - 'values' => $options, - 'value' => $this->getOperator(), - 'value_name' => $this->getOperatorName(), - 'data-form-part' => $this->getFormName() - ] - ); - $element->setRenderer($this->_layout->getBlockSingleton(\Magento\Rule\Block\Editable::class)); - - return $element; - } - - /** - * Get operator element html. - * - * @return string - */ - public function getOperatorElementHtml() - { - return $this->getOperatorElement()->getHtml(); - } - - /** - * Value element type will define renderer for condition value element - * - * @see \Magento\Framework\Data\Form\Element - * @return string - */ - public function getValueElementType() - { - return 'text'; - } - - /** - * Get value element renderer. - * - * @return \Magento\Rule\Block\Editable - */ - public function getValueElementRenderer() - { - if (strpos($this->getValueElementType(), '/') !== false) { - return $this->_layout->getBlockSingleton($this->getValueElementType()); - } - return $this->_layout->getBlockSingleton(\Magento\Rule\Block\Editable::class); - } - - /** - * Get value element. - * - * @return $this - */ - public function getValueElement() - { - $elementParams = [ - 'name' => $this->elementName . '[' . $this->getPrefix() . '][' . $this->getId() . '][value]', - 'value' => $this->getValue(), - 'values' => $this->getValueSelectOptions(), - 'value_name' => $this->getValueName(), - 'after_element_html' => $this->getValueAfterElementHtml(), - 'explicit_apply' => $this->getExplicitApply(), - 'data-form-part' => $this->getFormName() - ]; - if ($this->getInputType() == 'date') { - // date format intentionally hard-coded - $elementParams['input_format'] = \Magento\Framework\Stdlib\DateTime::DATE_INTERNAL_FORMAT; - $elementParams['date_format'] = \Magento\Framework\Stdlib\DateTime::DATE_INTERNAL_FORMAT; - $elementParams['placeholder'] = \Magento\Framework\Stdlib\DateTime::DATE_INTERNAL_FORMAT; - $elementParams['autocomplete'] = 'off'; - $elementParams['readonly'] = 'true'; - $elementParams['value_name'] = - (new \DateTime($elementParams['value'], new \DateTimeZone($this->_localeDate->getConfigTimezone()))) - ->format('Y-m-d'); - } - return $this->getForm()->addField( - $this->getPrefix() . '__' . $this->getId() . '__value', - $this->getValueElementType(), - $elementParams - )->setRenderer( - $this->getValueElementRenderer() - ); - } - - /** - * Get value element html. - * - * @return string - */ - public function getValueElementHtml() - { - return $this->getValueElement()->getHtml(); - } - - /** - * Get add link html. - * - * @return string - */ - public function getAddLinkHtml() - { - $src = $this->_assetRepo->getUrl('images/rule_component_add.gif'); - return ''; - } - - /** - * Get remove link html. - * - * @return string - */ - public function getRemoveLinkHtml() - { - $src = $this->_assetRepo->getUrl('images/rule_component_remove.gif'); - $html = ' '; - return $html; - } - - /** - * Get chooser container html. - * - * @return string - */ - public function getChooserContainerHtml() - { - $url = $this->getValueElementChooserUrl(); - return $url ? '
' : ''; - } - - /** - * Get this condition as string. - * - * @param string $format - * @return string - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function asString($format = '') - { - return $this->getAttributeName() . ' ' . $this->getOperatorName() . ' ' . $this->getValueName(); - } - - /** - * Get this condition with subconditions as string. - * - * @param int $level - * @return string - */ - public function asStringRecursive($level = 0) - { - return str_pad('', $level * 3, ' ', STR_PAD_LEFT) . $this->asString(); - } - - /** - * Validate product attribute value for condition - * - * @param object|array|int|string|float|bool|null $validatedValue product attribute value - * @return bool - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - public function validateAttribute($validatedValue) - { - if (is_object($validatedValue)) { - return false; - } - - /** - * Condition attribute value - */ - $value = $this->getValueParsed(); - - /** - * Comparison operator - */ - $option = $this->getOperatorForValidate(); - - // if operator requires array and it is not, or on opposite, return false - if ($this->isArrayOperatorType() xor is_array($value)) { - return false; - } - - $result = false; - - switch ($option) { - case '==': - case '!=': - if (is_array($value)) { - if (!is_array($validatedValue)) { - return false; - } - $result = !empty(array_intersect($value, $validatedValue)); - } else { - if (is_array($validatedValue)) { - $result = count($validatedValue) == 1 && array_shift($validatedValue) == $value; - } else { - $result = $this->_compareValues($validatedValue, $value); - } - } - break; - - case '<=': - case '>': - if (!is_scalar($validatedValue)) { - return false; - } - $result = $validatedValue <= $value; - break; - - case '>=': - case '<': - if (!is_scalar($validatedValue)) { - return false; - } - $result = $validatedValue >= $value; - break; - - case '{}': - case '!{}': - if (is_scalar($validatedValue) && is_array($value)) { - $validatedValue = (string)$validatedValue; - foreach ($value as $item) { - if (stripos($validatedValue, (string)$item) !== false) { - $result = true; - break; - } - } - } elseif (is_array($value)) { - if (!is_array($validatedValue) || empty($validatedValue)) { - return false; - } - $result = array_intersect($value, $validatedValue); - $result = !empty($result); - } else { - if (is_array($validatedValue)) { - $result = in_array($value, $validatedValue); - } else { - $result = $this->_compareValues($value, $validatedValue, false); - } - } - break; - - case '()': - case '!()': - if (is_array($validatedValue)) { - $result = count(array_intersect($validatedValue, (array)$value)) > 0; - } else { - $value = (array)$value; - foreach ($value as $item) { - if ($this->_compareValues($validatedValue, $item)) { - $result = true; - break; - } - } - } - break; - } - - if ('!=' == $option || '>' == $option || '<' == $option || '!{}' == $option || '!()' == $option) { - $result = !$result; - } - - return $result; - } - - /** - * Case and type insensitive comparison of values - * - * @param string|int|float|null $validatedValue - * @param string|int|float|null $value - * @param bool $strict - * @return bool - */ - protected function _compareValues($validatedValue, $value, $strict = true) - { - if (null === $value || null === $validatedValue || - $strict && is_numeric($validatedValue) && is_numeric($value)) { - return $validatedValue == $value; - } - - $validatePattern = preg_quote((string) $validatedValue, '~'); - if ($strict) { - $validatePattern = '^' . $validatePattern . '$'; - } - return (bool)preg_match('~' . $validatePattern . '~iu', $value); - } - - /** - * Validate model. - * - * @param \Magento\Framework\Model\AbstractModel $model - * @return bool - */ - public function validate(\Magento\Framework\Model\AbstractModel $model) - { - if (!$model->hasData($this->getAttribute())) { - $model->load($model->getId()); - } - $attributeValue = $model->getData($this->getAttribute()); - - return $this->validateAttribute($attributeValue); - } - - /** - * Retrieve operator for php validation - * - * @return string - */ - public function getOperatorForValidate() - { - return $this->getOperator(); - } -} diff --git a/app/code/Magento/Rule/Model/Condition/Combine.php b/app/code/Magento/Rule/Model/Condition/Combine.php deleted file mode 100644 index a8a8e5fb0f843..0000000000000 --- a/app/code/Magento/Rule/Model/Condition/Combine.php +++ /dev/null @@ -1,459 +0,0 @@ -_conditionFactory = $context->getConditionFactory(); - $this->_logger = $context->getLogger(); - - parent::__construct($context, $data); - $this->setType( - \Magento\Rule\Model\Condition\Combine::class - )->setAggregator( - 'all' - )->setValue( - true - )->setConditions( - [] - )->setActions( - [] - ); - - $this->loadAggregatorOptions(); - $options = $this->getAggregatorOptions(); - if ($options) { - reset($options); - $this->setAggregator(key($options)); - } - } - - /* start aggregator methods */ - - /** - * Load aggregation options - * - * @return $this - */ - public function loadAggregatorOptions() - { - $this->setAggregatorOption(['all' => __('ALL'), 'any' => __('ANY')]); - return $this; - } - - /** - * Return agregator selected options - * - * @return array - */ - public function getAggregatorSelectOptions() - { - $opt = []; - foreach ($this->getAggregatorOption() as $key => $value) { - $opt[] = ['value' => $key, 'label' => $value]; - } - return $opt; - } - - /** - * Get Agregator name - * - * @return string - */ - public function getAggregatorName() - { - return $this->getAggregatorOption($this->getAggregator()); - } - - /** - * Return agregator element - * - * @return object - */ - public function getAggregatorElement() - { - if ($this->getAggregator() === null) { - $options = $this->getAggregatorOption(); - if ($options) { - reset($options); - $this->setAggregator(key($options)); - } - } - return $this->getForm()->addField( - $this->getPrefix() . '__' . $this->getId() . '__aggregator', - 'select', - [ - 'name' => $this->elementName . '[' . $this->getPrefix() . '][' . $this->getId() . '][aggregator]', - 'values' => $this->getAggregatorSelectOptions(), - 'value' => $this->getAggregator(), - 'value_name' => $this->getAggregatorName(), - 'data-form-part' => $this->getFormName() - ] - )->setRenderer( - $this->_layout->getBlockSingleton(\Magento\Rule\Block\Editable::class) - ); - } - - /* end aggregator methods */ - - /** - * Load value options - * - * @return $this - */ - public function loadValueOptions() - { - $this->setValueOption([1 => __('TRUE'), 0 => __('FALSE')]); - return $this; - } - - /** - * Adds condition - * - * @param object $condition - * @return $this - */ - public function addCondition($condition) - { - $condition->setRule($this->getRule()); - $condition->setObject($this->getObject()); - $condition->setPrefix($this->getPrefix()); - - $conditions = $this->getConditions(); - $conditions[] = $condition; - - if (!$condition->getId()) { - $condition->setId($this->getId() . '--' . count($conditions)); - } - - $this->setData($this->getPrefix(), $conditions); - return $this; - } - - /** - * Return value element type - * - * @return string - */ - public function getValueElementType() - { - return 'select'; - } - - /** - * Returns array containing conditions in the collection - * - * Output example: - * array( - * 'type'=>'combine', - * 'operator'=>'ALL', - * 'value'=>'TRUE', - * 'conditions'=>array( - * {condition::asArray}, - * {combine::asArray}, - * {quote_item_combine::asArray} - * ) - * ) - * - * @param array $arrAttributes - * @return array - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function asArray(array $arrAttributes = []) - { - $out = parent::asArray(); - $out['aggregator'] = $this->getAggregator(); - - foreach ($this->getConditions() as $condition) { - $out['conditions'][] = $condition->asArray(); - } - - return $out; - } - - /** - * As xml - * - * @param string $containerKey - * @param string $itemKey - * @return string - */ - public function asXml($containerKey = 'conditions', $itemKey = 'condition') - { - $xml = "" . - $this->getAggregator() . - "" . - "" . - $this->getValue() . - "" . - "<{$containerKey}>"; - foreach ($this->getConditions() as $condition) { - $xml .= "<{$itemKey}>" . $condition->asXml() . ""; - } - $xml .= ""; - return $xml; - } - - /** - * Load array - * - * @param array $arr - * @param string $key - * @return $this - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - public function loadArray($arr, $key = 'conditions') - { - $this->setAggregator( - isset($arr['aggregator']) ? $arr['aggregator'] : (isset($arr['attribute']) ? $arr['attribute'] : null) - )->setValue( - isset($arr['value']) ? $arr['value'] : (isset($arr['operator']) ? $arr['operator'] : null) - ); - - if (!empty($arr[$key]) && is_array($arr[$key])) { - foreach ($arr[$key] as $conditionArr) { - try { - $condition = $this->_conditionFactory->create($conditionArr['type']); - $this->addCondition($condition); - $condition->loadArray($conditionArr, $key); - } catch (\Exception $e) { - $this->_logger->critical($e); - } - } - } - return $this; - } - - /** - * Load xml - * - * @param array|string $xml - * @return $this - */ - public function loadXml($xml) - { - if (is_string($xml)) { - $xml = simplexml_load_string($xml); - } - $arr = parent::loadXml($xml); - foreach ($xml->conditions->children() as $condition) { - $arr['conditions'] = parent::loadXml($condition); - } - $this->loadArray($arr); - return $this; - } - - /** - * As html - * - * @return string - */ - public function asHtml() - { - $html = $this->getTypeElement()->getHtml() . __( - 'If %1 of these conditions are %2:', - $this->getAggregatorElement()->getHtml(), - $this->getValueElement()->getHtml() - ); - if ($this->getId() != '1') { - $html .= $this->getRemoveLinkHtml(); - } - return $html; - } - - /** - * Get new child element - * - * @return $this - */ - public function getNewChildElement() - { - return $this->getForm()->addField( - $this->getPrefix() . '__' . $this->getId() . '__new_child', - 'select', - [ - 'name' => $this->elementName . '[' . $this->getPrefix() . '][' . $this->getId() . '][new_child]', - 'values' => $this->getNewChildSelectOptions(), - 'value_name' => $this->getNewChildName(), - 'data-form-part' => $this->getFormName() - ] - )->setRenderer( - $this->_layout->getBlockSingleton(\Magento\Rule\Block\Newchild::class) - ); - } - - /** - * As html recursive - * - * @return string - */ - public function asHtmlRecursive() - { - $html = $this->asHtml() . - ''; - return $html; - } - - /** - * As string - * - * @param string $format - * @return string - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function asString($format = '') - { - $str = __("If %1 of these conditions are %2:", $this->getAggregatorName(), $this->getValueName()); - return $str; - } - - /** - * As string recursive - * - * @param int $level - * @return string - */ - public function asStringRecursive($level = 0) - { - $str = parent::asStringRecursive($level); - foreach ($this->getConditions() as $cond) { - $str .= "\n" . $cond->asStringRecursive($level + 1); - } - return $str; - } - - /** - * Validate - * - * @param \Magento\Framework\Model\AbstractModel $model - * @return bool - */ - public function validate(\Magento\Framework\Model\AbstractModel $model) - { - return $this->_isValid($model); - } - - /** - * Validate by entity ID - * - * @param int $entityId - * @return mixed - */ - public function validateByEntityId($entityId) - { - return $this->_isValid($entityId); - } - - /** - * Is entity valid - * - * @param int|\Magento\Framework\Model\AbstractModel $entity - * @return bool - */ - protected function _isValid($entity) - { - if (!$this->getConditions()) { - return true; - } - - $all = $this->getAggregator() === 'all'; - $true = (bool)$this->getValue(); - - foreach ($this->getConditions() as $cond) { - if ($entity instanceof \Magento\Framework\Model\AbstractModel) { - $validated = $cond->validate($entity); - } else { - $validated = $cond->validateByEntityId($entity); - } - if ($all && $validated !== $true) { - return false; - } elseif (!$all && $validated === $true) { - return true; - } - } - return $all ? true : false; - } - - /** - * Set js From object - * - * @param \Magento\Framework\Data\Form $form - * @return $this - */ - public function setJsFormObject($form) - { - $this->setData('js_form_object', $form); - foreach ($this->getConditions() as $condition) { - $condition->setJsFormObject($form); - } - return $this; - } - - /** - * Get conditions, if current prefix is undefined use 'conditions' key - * - * @return array - */ - public function getConditions() - { - $key = $this->getPrefix() ? $this->getPrefix() : 'conditions'; - return $this->getData($key); - } - - /** - * Set conditions, if current prefix is undefined use 'conditions' key - * - * @param array $conditions - * @return $this - */ - public function setConditions($conditions) - { - $key = $this->getPrefix() ? $this->getPrefix() : 'conditions'; - return $this->setData($key, $conditions); - } - - /** - * Getter for "Conditions Combination" select option for recursive combines - * - * @return array - */ - protected function _getRecursiveChildSelectOption() - { - return ['value' => $this->getType(), 'label' => __('Conditions Combination')]; - } -} diff --git a/app/code/Magento/Rule/Model/Condition/ConditionInterface.php b/app/code/Magento/Rule/Model/Condition/ConditionInterface.php deleted file mode 100644 index 58f7bd0dfad6d..0000000000000 --- a/app/code/Magento/Rule/Model/Condition/ConditionInterface.php +++ /dev/null @@ -1,34 +0,0 @@ -_assetRepo = $assetRepo; - $this->_localeDate = $localeDate; - $this->_layout = $layout; - $this->_conditionFactory = $conditionFactory; - $this->_logger = $logger; - } - - /** - * @return \Magento\Framework\View\Asset\Repository - */ - public function getAssetRepository() - { - return $this->_assetRepo; - } - - /** - * @return \Magento\Framework\Stdlib\DateTime\TimezoneInterface - */ - public function getLocaleDate() - { - return $this->_localeDate; - } - - /** - * @return \Magento\Framework\View\LayoutInterface - */ - public function getLayout() - { - return $this->_layout; - } - - /** - * @return \Magento\Rule\Model\ConditionFactory - */ - public function getConditionFactory() - { - return $this->_conditionFactory; - } - - /** - * @return \Psr\Log\LoggerInterface - */ - public function getLogger() - { - return $this->_logger; - } -} diff --git a/app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php b/app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php deleted file mode 100644 index 10b32d393083c..0000000000000 --- a/app/code/Magento/Rule/Model/Condition/Product/AbstractProduct.php +++ /dev/null @@ -1,734 +0,0 @@ - array( - * [store_id_1] => store_value_1, - * [store_id_2] => store_value_2, - * ... - * [store_id_n] => store_value_n - * ), - * ... - * ) - * - * Will be set only for not global scope attribute - * - * @var array - */ - protected $_entityAttributeValues = null; - - /** - * Attribute data key that indicates whether it should be used for rules - * - * @var string - */ - protected $_isUsedForRuleProperty = 'is_used_for_promo_rules'; - - /** - * Adminhtml data - * - * @var \Magento\Backend\Helper\Data - */ - protected $_backendData; - - /** - * @var \Magento\Eav\Model\Config - */ - protected $_config; - - /** - * @var \Magento\Catalog\Model\ProductFactory - */ - protected $_productFactory; - - /** - * @var \Magento\Catalog\Api\ProductRepositoryInterface - */ - protected $productRepository; - - /** - * @var \Magento\Catalog\Model\ResourceModel\Product - */ - protected $_productResource; - - /** - * @var \Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\Collection - */ - protected $_attrSetCollection; - - /** - * @var \Magento\Framework\Locale\FormatInterface - */ - protected $_localeFormat; - - /** - * @var ProductCategoryList - */ - private $productCategoryList; - - /** - * @param \Magento\Rule\Model\Condition\Context $context - * @param \Magento\Backend\Helper\Data $backendData - * @param \Magento\Eav\Model\Config $config - * @param \Magento\Catalog\Model\ProductFactory $productFactory - * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository - * @param \Magento\Catalog\Model\ResourceModel\Product $productResource - * @param \Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\Collection $attrSetCollection - * @param \Magento\Framework\Locale\FormatInterface $localeFormat - * @param array $data - * @param ProductCategoryList|null $categoryList - * - * @SuppressWarnings(PHPMD.ExcessiveParameterList) - */ - public function __construct( - \Magento\Rule\Model\Condition\Context $context, - \Magento\Backend\Helper\Data $backendData, - \Magento\Eav\Model\Config $config, - \Magento\Catalog\Model\ProductFactory $productFactory, - \Magento\Catalog\Api\ProductRepositoryInterface $productRepository, - \Magento\Catalog\Model\ResourceModel\Product $productResource, - \Magento\Eav\Model\ResourceModel\Entity\Attribute\Set\Collection $attrSetCollection, - \Magento\Framework\Locale\FormatInterface $localeFormat, - array $data = [], - ProductCategoryList $categoryList = null - ) { - $this->_backendData = $backendData; - $this->_config = $config; - $this->_productFactory = $productFactory; - $this->productRepository = $productRepository; - $this->_productResource = $productResource; - $this->_attrSetCollection = $attrSetCollection; - $this->_localeFormat = $localeFormat; - $this->productCategoryList = $categoryList ?: ObjectManager::getInstance()->get(ProductCategoryList::class); - parent::__construct($context, $data); - } - - /** - * Customize default operator input by type mapper for some types - * - * @return array - */ - public function getDefaultOperatorInputByType() - { - if (null === $this->_defaultOperatorInputByType) { - parent::getDefaultOperatorInputByType(); - /* - * '{}' and '!{}' are left for back-compatibility and equal to '==' and '!=' - */ - $this->_defaultOperatorInputByType['category'] = ['==', '!=', '{}', '!{}', '()', '!()']; - $this->_arrayInputTypes[] = 'category'; - } - return $this->_defaultOperatorInputByType; - } - - /** - * Retrieve attribute object - * - * @return \Magento\Catalog\Model\ResourceModel\Eav\Attribute - */ - public function getAttributeObject() - { - try { - $obj = $this->_config->getAttribute(\Magento\Catalog\Model\Product::ENTITY, $this->getAttribute()); - } catch (\Exception $e) { - $obj = new \Magento\Framework\DataObject(); - $obj->setEntity($this->_productFactory->create())->setFrontendInput('text'); - } - return $obj; - } - - /** - * Add special attributes - * - * @param array &$attributes - * @return void - */ - protected function _addSpecialAttributes(array &$attributes) - { - $attributes['attribute_set_id'] = __('Attribute Set'); - $attributes['category_ids'] = __('Category'); - } - - /** - * Load attribute options - * - * @return $this - */ - public function loadAttributeOptions() - { - $productAttributes = $this->_productResource->loadAllAttributes()->getAttributesByCode(); - - $attributes = []; - foreach ($productAttributes as $attribute) { - /* @var $attribute \Magento\Catalog\Model\ResourceModel\Eav\Attribute */ - if (!$attribute->isAllowedForRuleCondition() || !$attribute->getDataUsingMethod( - $this->_isUsedForRuleProperty - ) - ) { - continue; - } - $attributes[$attribute->getAttributeCode()] = $attribute->getFrontendLabel(); - } - - $this->_addSpecialAttributes($attributes); - - asort($attributes); - $this->setAttributeOption($attributes); - - return $this; - } - - /** - * Prepares values options to be used as select options or hashed array - * Result is stored in following keys: - * 'value_select_options' - normal select array: array(array('value' => $value, 'label' => $label), ...) - * 'value_option' - hashed array: array($value => $label, ...), - * - * @return $this - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - protected function _prepareValueOptions() - { - // Check that both keys exist. Maybe somehow only one was set not in this routine, but externally. - $selectReady = $this->getData('value_select_options'); - $hashedReady = $this->getData('value_option'); - if ($selectReady && $hashedReady) { - return $this; - } - - // Get array of select options. It will be used as source for hashed options - $selectOptions = null; - if ($this->getAttribute() === 'attribute_set_id') { - $entityTypeId = $this->_config->getEntityType(\Magento\Catalog\Model\Product::ENTITY)->getId(); - $selectOptions = $this->_attrSetCollection - ->setEntityTypeFilter($entityTypeId) - ->load() - ->toOptionArray(); - } elseif ($this->getAttribute() === 'type_id') { - foreach ($selectReady as $value => $label) { - if (is_array($label) && isset($label['value'])) { - $selectOptions[] = $label; - } else { - $selectOptions[] = ['value' => $value, 'label' => $label]; - } - } - $selectReady = null; - } elseif (is_object($this->getAttributeObject())) { - $attributeObject = $this->getAttributeObject(); - if ($attributeObject->usesSource()) { - if ($attributeObject->getFrontendInput() == 'multiselect') { - $addEmptyOption = false; - } else { - $addEmptyOption = true; - } - $selectOptions = $attributeObject->getSource()->getAllOptions($addEmptyOption); - } - } - - $this->_setSelectOptions($selectOptions, $selectReady, $hashedReady); - - return $this; - } - - /** - * Set new values only if we really got them - * - * @param array $selectOptions - * @param array $selectReady - * @param array $hashedReady - * @return $this - */ - protected function _setSelectOptions($selectOptions, $selectReady, $hashedReady) - { - if ($selectOptions !== null) { - // Overwrite only not already existing values - if (!$selectReady) { - $this->setData('value_select_options', $selectOptions); - } - if (!$hashedReady) { - $hashedOptions = []; - foreach ($selectOptions as $option) { - if (is_array($option['value'])) { - continue; // We cannot use array as index - } - $hashedOptions[$option['value']] = $option['label']; - } - $this->setData('value_option', $hashedOptions); - } - } - return $this; - } - - /** - * Retrieve value by option - * - * @param string|null $option - * @return string - */ - public function getValueOption($option = null) - { - $this->_prepareValueOptions(); - return $this->getData('value_option' . ($option !== null ? '/' . $option : '')); - } - - /** - * Retrieve select option values - * - * @return array - */ - public function getValueSelectOptions() - { - $this->_prepareValueOptions(); - return $this->getData('value_select_options'); - } - - /** - * Retrieve after element HTML - * - * @return string - */ - public function getValueAfterElementHtml() - { - $html = ''; - - switch ($this->getAttribute()) { - case 'sku': - case 'category_ids': - $image = $this->_assetRepo->getUrl('images/rule_chooser_trigger.gif'); - break; - } - - if (!empty($image)) { - $html = ''; - } - return $html; - } - - /** - * Retrieve attribute element - * - * @return \Magento\Framework\Data\Form\Element\AbstractElement - */ - public function getAttributeElement() - { - $element = parent::getAttributeElement(); - $element->setShowAsText(true); - return $element; - } - - /** - * Collect validated attributes - * - * @param \Magento\Catalog\Model\ResourceModel\Product\Collection $productCollection - * @return $this - */ - public function collectValidatedAttributes($productCollection) - { - $attribute = $this->getAttribute(); - if ('category_ids' != $attribute) { - $productCollection->addAttributeToSelect($attribute, 'left'); - if ($this->getAttributeObject()->isScopeGlobal()) { - $attributes = $this->getRule()->getCollectedAttributes(); - $attributes[$attribute] = true; - $this->getRule()->setCollectedAttributes($attributes); - } else { - $this->_entityAttributeValues = $productCollection->getAllAttributeValues($attribute); - } - } - - return $this; - } - - /** - * Retrieve input type - * - * @return string - */ - public function getInputType() - { - if ($this->getAttribute() === 'attribute_set_id') { - return 'select'; - } - if (!is_object($this->getAttributeObject())) { - return 'string'; - } - if ($this->getAttributeObject()->getAttributeCode() == 'category_ids') { - return 'category'; - } - switch ($this->getAttributeObject()->getFrontendInput()) { - case 'select': - return 'select'; - - case 'multiselect': - return 'multiselect'; - - case 'date': - return 'date'; - - case 'boolean': - return 'boolean'; - - default: - return 'string'; - } - } - - /** - * Retrieve value element type - * - * @return string - */ - public function getValueElementType() - { - if ($this->getAttribute() === 'attribute_set_id') { - return 'select'; - } - if (!is_object($this->getAttributeObject())) { - return 'text'; - } - switch ($this->getAttributeObject()->getFrontendInput()) { - case 'select': - case 'boolean': - return 'select'; - - case 'multiselect': - return 'multiselect'; - - case 'date': - return 'date'; - - default: - return 'text'; - } - } - - /** - * Retrieve value element chooser URL - * - * @return string - */ - public function getValueElementChooserUrl() - { - $url = false; - switch ($this->getAttribute()) { - case 'sku': - case 'category_ids': - $url = 'catalog_rule/promo_widget/chooser/attribute/' . $this->getAttribute(); - if ($this->getJsFormObject()) { - $url .= '/form/' . $this->getJsFormObject(); - } - break; - default: - break; - } - return $url !== false ? $this->_backendData->getUrl($url) : ''; - } - - /** - * Retrieve Explicit Apply - * - * @return bool - * @SuppressWarnings(PHPMD.BooleanGetMethodName) - */ - public function getExplicitApply() - { - switch ($this->getAttribute()) { - case 'sku': - case 'category_ids': - return true; - default: - break; - } - if (is_object($this->getAttributeObject())) { - switch ($this->getAttributeObject()->getFrontendInput()) { - case 'date': - return true; - default: - break; - } - } - return false; - } - - /** - * Load array - * - * @param array $arr - * @return $this - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function loadArray($arr) - { - $this->setAttribute(isset($arr['attribute']) ? $arr['attribute'] : false); - $attribute = $this->getAttributeObject(); - - $isContainsOperator = !empty($arr['operator']) && in_array($arr['operator'], ['{}', '!{}']); - if ($attribute && $attribute->getBackendType() == 'decimal' && !$isContainsOperator) { - if (isset($arr['value'])) { - if (!empty($arr['operator']) && in_array( - $arr['operator'], - ['!()', '()'] - ) && false !== strpos( - $arr['value'], - ',' - ) - ) { - $tmp = []; - foreach (explode(',', $arr['value']) as $value) { - $tmp[] = $this->_localeFormat->getNumber($value); - } - $arr['value'] = implode(',', $tmp); - } else { - $arr['value'] = $this->_localeFormat->getNumber($arr['value']); - } - } else { - $arr['value'] = false; - } - $arr['is_value_parsed'] = isset( - $arr['is_value_parsed'] - ) ? $this->_localeFormat->getNumber( - $arr['is_value_parsed'] - ) : false; - } elseif (!empty($arr['operator']) && $arr['operator'] == '()') { - if (isset($arr['value'])) { - $arr['value'] = preg_replace('/\s*,\s*/', ',', $arr['value']); - } - } - - return parent::loadArray($arr); - } - - /** - * Validate product attribute value for condition - * - * @param \Magento\Framework\Model\AbstractModel $model - * @return bool - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - public function validate(\Magento\Framework\Model\AbstractModel $model) - { - $attrCode = $this->getAttribute(); - - if ('category_ids' == $attrCode) { - $productId = (int)$model->getEntityId(); - return $this->validateAttribute($this->productCategoryList->getCategoryIds($productId)); - } elseif (!isset($this->_entityAttributeValues[$model->getId()])) { - if (!$model->getResource()) { - return false; - } - $attr = $model->getResource()->getAttribute($attrCode); - - if ($attr && $attr->getBackendType() == 'datetime' && !is_int($this->getValue())) { - $this->setValue(strtotime((string) $this->getValue())); - $value = strtotime($model->getData($attrCode)); - return $this->validateAttribute($value); - } - - if ($attr && $attr->getFrontendInput() == 'multiselect') { - $value = $model->getData($attrCode); - $value = ($value && strlen($value)) ? explode(',', $value) : []; - return $this->validateAttribute($value); - } - - return parent::validate($model); - } else { - $result = false; - // any valid value will set it to TRUE - // remember old attribute state - $oldAttrValue = $model->hasData($attrCode) ? $model->getData($attrCode) : null; - - foreach ($this->_entityAttributeValues[$model->getId()] as $value) { - $attr = $model->getResource()->getAttribute($attrCode); - if ($attr && $attr->getBackendType() == 'datetime') { - $value = strtotime($value); - } elseif ($attr && $attr->getFrontendInput() == 'multiselect') { - $value = ($value && strlen($value)) ? explode(',', $value) : []; - } - - $model->setData($attrCode, $value); - $result |= parent::validate($model); - - if ($result) { - break; - } - } - - if ($oldAttrValue === null) { - $model->unsetData($attrCode); - } else { - $model->setData($attrCode, $oldAttrValue); - } - - return (bool)$result; - } - } - - /** - * Get argument value to bind - * - * @return array|float|int|mixed|string|\Zend_Db_Expr - */ - public function getBindArgumentValue() - { - if ($this->getAttribute() == 'category_ids') { - return new \Zend_Db_Expr( - $this->_productResource->getConnection() - ->select() - ->from( - $this->_productResource->getTable('catalog_category_product'), - ['product_id'] - )->where( - 'category_id IN (?)', - $this->getValueParsed() - )->__toString() - ); - } - return parent::getBindArgumentValue(); - } - - /** - * Get mapped sql field - * - * @return string - */ - public function getMappedSqlField() - { - if ($this->getAttribute() == 'sku') { - $mappedSqlField = 'e.sku'; - } elseif (!$this->isAttributeSetOrCategory()) { - $mappedSqlField = $this->getEavAttributeTableAlias() . '.value'; - } elseif ($this->getAttribute() == 'category_ids') { - $mappedSqlField = 'e.entity_id'; - } elseif ($this->getAttribute() == 'attribute_set_id') { - $mappedSqlField = 'e.attribute_set_id'; - } else { - $mappedSqlField = parent::getMappedSqlField(); - } - return $mappedSqlField; - } - - /** - * Validate product by entity ID - * - * @param int $productId - * @return bool - */ - public function validateByEntityId($productId) - { - if ('category_ids' == $this->getAttribute()) { - $result = $this->validateAttribute($this->_getAvailableInCategories($productId)); - } elseif ('attribute_set_id' == $this->getAttribute()) { - $result = $this->validateAttribute($this->_getAttributeSetId($productId)); - } else { - $product = $this->productRepository->getById($productId); - $result = $this->validate($product); - unset($product); - } - return $result; - } - - /** - * Retrieve category ids where product is available - * - * @param int $productId - * @return array - */ - protected function _getAvailableInCategories($productId) - { - return $this->productCategoryList->getCategoryIds($productId); - } - - /** - * Get attribute set id for product - * - * @param int $productId - * @return string - */ - protected function _getAttributeSetId($productId) - { - return $this->_productResource->getConnection() - ->fetchOne( - $this->_productResource->getConnection() - ->select() - ->distinct() - ->from( - $this->_productResource->getTable('catalog_product_entity'), - ['attribute_set_id'] - )->where( - 'entity_id = ?', - $productId - ) - ); - } - - /** - * Correct '==' and '!=' operators - * - * Categories can't be equal because product is included categories selected by administrator and in their parents - * - * @return string - */ - public function getOperatorForValidate() - { - $operator = $this->getOperator(); - if ($this->getInputType() == 'category') { - if ($operator == '==') { - $operator = '{}'; - } elseif ($operator == '!=') { - $operator = '!{}'; - } - } - - return $operator; - } - - /** - * Check is attribute set or category - * - * @return bool - */ - protected function isAttributeSetOrCategory() - { - return in_array($this->getAttribute(), ['attribute_set_id', 'category_ids']); - } - - /** - * Get eav attribute alias - * - * @return string - */ - protected function getEavAttributeTableAlias() - { - $attribute = $this->getAttributeObject(); - - return 'at_' . $attribute->getAttributeCode(); - } -} diff --git a/app/code/Magento/Rule/Model/Condition/Sql/Builder.php b/app/code/Magento/Rule/Model/Condition/Sql/Builder.php deleted file mode 100644 index cb4cb9a12bd5b..0000000000000 --- a/app/code/Magento/Rule/Model/Condition/Sql/Builder.php +++ /dev/null @@ -1,300 +0,0 @@ - ':field = ?', - '!=' => ':field <> ?', - '>=' => ':field >= ?', - '>=' => ':field >= ?', - '>' => ':field > ?', - '>' => ':field > ?', - '<=' => ':field <= ?', - '<=' => ':field <= ?', - '<' => ':field < ?', - '<' => ':field < ?', - '{}' => ':field IN (?)', - '!{}' => ':field NOT IN (?)', - '()' => ':field IN (?)', - '!()' => ':field NOT IN (?)', - ]; - - /** - * @var array - */ - private $stringConditionOperatorMap = [ - '{}' => ':field LIKE ?', - '!{}' => ':field NOT LIKE ?', - ]; - - /** - * @var \Magento\Rule\Model\Condition\Sql\ExpressionFactory - */ - protected $_expressionFactory; - - /** - * @var AttributeRepositoryInterface - */ - private $attributeRepository; - - /** - * @param ExpressionFactory $expressionFactory - * @param AttributeRepositoryInterface|null $attributeRepository - */ - public function __construct( - ExpressionFactory $expressionFactory, - AttributeRepositoryInterface $attributeRepository = null - ) { - $this->_expressionFactory = $expressionFactory; - $this->attributeRepository = $attributeRepository ?: - ObjectManager::getInstance()->get(AttributeRepositoryInterface::class); - } - - /** - * Get tables to join for given conditions combination - * - * @param Combine $combine - * @return array - */ - protected function _getCombineTablesToJoin(Combine $combine) - { - $tables = $this->_getChildCombineTablesToJoin($combine); - return $tables; - } - - /** - * Get child for given conditions combination - * - * @param Combine $combine - * @param array $tables - * @return array - */ - protected function _getChildCombineTablesToJoin(Combine $combine, $tables = []) - { - foreach ($combine->getConditions() as $condition) { - if ($condition->getConditions()) { - $tables = $this->_getChildCombineTablesToJoin($condition); - } else { - /** @var $condition AbstractCondition */ - foreach ($condition->getTablesToJoin() as $alias => $table) { - if (!isset($tables[$alias])) { - $tables[$alias] = $table; - } - } - } - } - return $tables; - } - - /** - * Join tables from conditions combination to collection - * - * @param AbstractCollection $collection - * @param Combine $combine - * @return $this - */ - protected function _joinTablesToCollection( - AbstractCollection $collection, - Combine $combine - ): Builder { - foreach ($this->_getCombineTablesToJoin($combine) as $alias => $joinTable) { - /** @var $condition AbstractCondition */ - $collection->getSelect()->joinLeft( - [$alias => $collection->getResource()->getTable($joinTable['name'])], - $joinTable['condition'], - isset($joinTable['columns']) ? $joinTable['columns'] : '*' - ); - } - - return $this; - } - - /** - * Returns sql expression based on rule condition. - * - * @param AbstractCondition $condition - * @param string $value - * @param bool $isDefaultStoreUsed no longer used because caused an issue about not existing table alias - * @return string - * @throws \Magento\Framework\Exception\LocalizedException - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - protected function _getMappedSqlCondition( - AbstractCondition $condition, - string $value = '', - bool $isDefaultStoreUsed = true - ): string { - $argument = $condition->getMappedSqlField(); - - // If rule hasn't valid argument - prevent incorrect rule behavior. - if (empty($argument)) { - return $this->_expressionFactory->create(['expression' => '1 = -1']); - } elseif (preg_match('/[^a-z0-9\-_\.\`]/i', $argument) > 0) { - throw new \Magento\Framework\Exception\LocalizedException(__('Invalid field')); - } - - $conditionOperator = $condition->getOperatorForValidate(); - - if (!isset($this->_conditionOperatorMap[$conditionOperator])) { - throw new \Magento\Framework\Exception\LocalizedException(__('Unknown condition operator')); - } - - $defaultValue = 0; - //operator 'contains {}' is mapped to 'IN()' query that cannot work with substrings - // adding mapping to 'LIKE %%' - if ($condition->getInputType() === 'string' - && in_array($conditionOperator, array_keys($this->stringConditionOperatorMap), true) - ) { - $sql = str_replace( - ':field', - (string) $this->_connection->getIfNullSql( - $this->_connection->quoteIdentifier($argument), - $defaultValue - ), - $this->stringConditionOperatorMap[$conditionOperator] - ); - $bindValue = $condition->getBindArgumentValue(); - $expression = $value . $this->_connection->quoteInto($sql, "%$bindValue%"); - } else { - $sql = str_replace( - ':field', - (string) $this->_connection->getIfNullSql( - $this->_connection->quoteIdentifier($argument), - $defaultValue - ), - $this->_conditionOperatorMap[$conditionOperator] - ); - $bindValue = $condition->getBindArgumentValue(); - $expression = $value . $this->_connection->quoteInto($sql, $bindValue); - } - // values for multiselect attributes can be saved in comma-separated format - // below is a solution for matching such conditions with selected values - if (is_array($bindValue) && \in_array($conditionOperator, ['()', '{}'], true)) { - foreach ($bindValue as $item) { - $expression .= $this->_connection->quoteInto( - " OR (FIND_IN_SET (?, {$this->_connection->quoteIdentifier($argument)}) > 0)", - $item - ); - } - } - return $this->_expressionFactory->create( - ['expression' => $expression] - ); - } - - /** - * Get mapped sql combination. - * - * @param Combine $combine - * @param string $value - * @param bool $isDefaultStoreUsed - * @return string - * @SuppressWarnings(PHPMD.NPathComplexity) - * @throws \Magento\Framework\Exception\LocalizedException - */ - protected function _getMappedSqlCombination( - Combine $combine, - string $value = '', - bool $isDefaultStoreUsed = true - ): string { - $out = (!empty($value) ? $value : ''); - $value = ($combine->getValue() ? '' : ' NOT '); - $getAggregator = $combine->getAggregator(); - $conditions = $combine->getConditions(); - foreach ($conditions as $key => $condition) { - /** @var $condition AbstractCondition|Combine */ - $con = ($getAggregator == 'any' ? Select::SQL_OR : Select::SQL_AND); - $con = (isset($conditions[$key+1]) ? $con : ''); - if ($condition instanceof Combine) { - $out .= $this->_getMappedSqlCombination($condition, $value, $isDefaultStoreUsed); - } else { - $out .= $this->_getMappedSqlCondition($condition, $value, $isDefaultStoreUsed); - } - $out .= $out ? (' ' . $con) : ''; - } - - return $this->_expressionFactory->create(['expression' => $out]); - } - - /** - * Attach conditions filter to collection - * - * @param AbstractCollection $collection - * @param Combine $combine - * @return void - * @throws \Magento\Framework\Exception\LocalizedException - */ - public function attachConditionToCollection( - AbstractCollection $collection, - Combine $combine - ): void { - $this->_connection = $collection->getResource()->getConnection(); - $this->_joinTablesToCollection($collection, $combine); - $whereExpression = (string)$this->_getMappedSqlCombination($combine); - if (!empty($whereExpression)) { - $collection->getSelect()->where($whereExpression); - $this->buildConditions($collection, $combine); - } - } - - /** - * Build sql conditions from combination. - * - * @param AbstractCollection $collection - * @param Combine $combine - * @return void - */ - private function buildConditions(AbstractCollection $collection, Combine $combine) : void - { - if (!empty($combine->getConditions())) { - $conditions = ''; - $attributeField = ''; - foreach ($combine->getConditions() as $condition) { - if ($condition->getData('attribute') === \Magento\Catalog\Api\Data\ProductInterface::SKU - && $condition->getData('operator') === '()' - ) { - $conditions = $condition->getData('value'); - $attributeField = $this->_connection->quoteIdentifier($condition->getMappedSqlField()); - } - } - - if (!empty($conditions) && !empty($attributeField)) { - $conditions = $this->_connection->quote( - array_map('trim', explode(',', $conditions)) - ); - $collection->getSelect()->reset(Select::ORDER); - $collection->getSelect()->order( - $this->_expressionFactory->create( - ['expression' => "FIELD($attributeField, $conditions)"] - ) - ); - } - } - } -} diff --git a/app/code/Magento/Rule/Model/Condition/Sql/Expression.php b/app/code/Magento/Rule/Model/Condition/Sql/Expression.php deleted file mode 100644 index 0896a65652681..0000000000000 --- a/app/code/Magento/Rule/Model/Condition/Sql/Expression.php +++ /dev/null @@ -1,23 +0,0 @@ -_expression) ? '' : '(' . $this->_expression . ')'; - } -} diff --git a/app/code/Magento/Rule/Model/ConditionFactory.php b/app/code/Magento/Rule/Model/ConditionFactory.php deleted file mode 100644 index 2a47e3ca015d8..0000000000000 --- a/app/code/Magento/Rule/Model/ConditionFactory.php +++ /dev/null @@ -1,60 +0,0 @@ -objectManager = $objectManager; - } - - /** - * Create new object for each requested model. - * If model is requested first time, store it at array. - * It's made by performance reasons to avoid initialization of same models each time when rules are being processed. - * - * @param string $type - * - * @return \Magento\Rule\Model\Condition\ConditionInterface - * - * @throws \LogicException - * @throws \BadMethodCallException - * @throws \InvalidArgumentException - */ - public function create($type) - { - if (!array_key_exists($type, $this->conditionModels)) { - if (!class_exists($type)) { - throw new \InvalidArgumentException('Class does not exist'); - } - if (!in_array(ConditionInterface::class, class_implements($type))) { - throw new \InvalidArgumentException('Class does not implement condition interface'); - } - $this->conditionModels[$type] = $this->objectManager->create($type); - } - - return clone $this->conditionModels[$type]; - } -} diff --git a/app/code/Magento/Rule/Model/Renderer/Actions.php b/app/code/Magento/Rule/Model/Renderer/Actions.php deleted file mode 100644 index 21f539d19c671..0000000000000 --- a/app/code/Magento/Rule/Model/Renderer/Actions.php +++ /dev/null @@ -1,23 +0,0 @@ -getRule() && $element->getRule()->getActions()) { - return $element->getRule()->getActions()->asHtmlRecursive(); - } - return ''; - } -} diff --git a/app/code/Magento/Rule/Model/Renderer/Conditions.php b/app/code/Magento/Rule/Model/Renderer/Conditions.php deleted file mode 100644 index 7e1e17877968b..0000000000000 --- a/app/code/Magento/Rule/Model/Renderer/Conditions.php +++ /dev/null @@ -1,23 +0,0 @@ -getRule() && $element->getRule()->getConditions()) { - return $element->getRule()->getConditions()->asHtmlRecursive(); - } - return ''; - } -} diff --git a/app/code/Magento/Rule/Model/ResourceModel/AbstractResource.php b/app/code/Magento/Rule/Model/ResourceModel/AbstractResource.php deleted file mode 100644 index 6e685a9a9b978..0000000000000 --- a/app/code/Magento/Rule/Model/ResourceModel/AbstractResource.php +++ /dev/null @@ -1,248 +0,0 @@ - array( - * 'associations_table' => 'table_name', - * 'rule_id_field' => 'rule_id', - * 'entity_id_field' => 'entity_id' - * ), - * 'entity_type2' => array( - * 'associations_table' => 'table_name', - * 'rule_id_field' => 'rule_id', - * 'entity_id_field' => 'entity_id' - * ) - * .... - * ) - * - * @var array - */ - protected $_associatedEntitiesMap = []; - - /** - * Prepare rule's active "from" and "to" dates - * - * @param \Magento\Framework\Model\AbstractModel $object - * @return $this - */ - public function _beforeSave(\Magento\Framework\Model\AbstractModel $object) - { - $this->resolveDate($object, 'from_date'); - $this->resolveDate($object, 'to_date'); - parent::_beforeSave($object); - return $this; - } - - /** - * @param \Magento\Framework\Model\AbstractModel $object - * @param string $dateIdentifier - * @return void - */ - private function resolveDate(\Magento\Framework\Model\AbstractModel $object, $dateIdentifier) - { - $date = $object->getData($dateIdentifier); - if ($date instanceof \DateTimeInterface) { - $object->setData($dateIdentifier, $date->format('Y-m-d H:i:s')); - } elseif (!is_string($date) || empty($date)) { - $object->setData($dateIdentifier, null); - } - } - - /** - * Bind specified rules to entities - * - * @param int[]|int|string $ruleIds - * @param int[]|int|string $entityIds - * @param string $entityType - * @return $this - * @throws \Exception - */ - public function bindRuleToEntity($ruleIds, $entityIds, $entityType) - { - $this->getConnection()->beginTransaction(); - - try { - $this->_multiplyBunchInsert($ruleIds, $entityIds, $entityType); - } catch (\Exception $e) { - $this->getConnection()->rollBack(); - throw $e; - } - - $this->getConnection()->commit(); - - return $this; - } - - /** - * Multiply rule ids by entity ids and insert - * - * @param int|[] $ruleIds - * @param int|[] $entityIds - * @param string $entityType - * @return $this - */ - protected function _multiplyBunchInsert($ruleIds, $entityIds, $entityType) - { - if (empty($ruleIds) || empty($entityIds)) { - return $this; - } - if (!is_array($ruleIds)) { - $ruleIds = [(int)$ruleIds]; - } - if (!is_array($entityIds)) { - $entityIds = [(int)$entityIds]; - } - $data = []; - $count = 0; - $entityInfo = $this->_getAssociatedEntityInfo($entityType); - foreach ($ruleIds as $ruleId) { - foreach ($entityIds as $entityId) { - $data[] = [ - $entityInfo['entity_id_field'] => $entityId, - $entityInfo['rule_id_field'] => $ruleId, - ]; - $count++; - if ($count % 1000 == 0) { - $this->getConnection()->insertOnDuplicate( - $this->getTable($entityInfo['associations_table']), - $data, - [$entityInfo['rule_id_field']] - ); - $data = []; - } - } - } - if (!empty($data)) { - $this->getConnection()->insertOnDuplicate( - $this->getTable($entityInfo['associations_table']), - $data, - [$entityInfo['rule_id_field']] - ); - } - - $this->getConnection()->delete( - $this->getTable($entityInfo['associations_table']), - $this->getConnection()->quoteInto( - $entityInfo['rule_id_field'] . ' IN (?) AND ', - $ruleIds - ) . $this->getConnection()->quoteInto( - $entityInfo['entity_id_field'] . ' NOT IN (?)', - $entityIds - ) - ); - return $this; - } - - /** - * Unbind specified rules from entities - * - * @param int[]|int|string $ruleIds - * @param int[]|int|string $entityIds - * @param string $entityType - * @return $this - */ - public function unbindRuleFromEntity($ruleIds, $entityIds, $entityType) - { - $connection = $this->getConnection(); - $entityInfo = $this->_getAssociatedEntityInfo($entityType); - - if (!is_array($entityIds)) { - $entityIds = [(int)$entityIds]; - } - if (!is_array($ruleIds)) { - $ruleIds = [(int)$ruleIds]; - } - - $where = []; - if (!empty($ruleIds)) { - $where[] = $connection->quoteInto($entityInfo['rule_id_field'] . ' IN (?)', $ruleIds); - } - if (!empty($entityIds)) { - $where[] = $connection->quoteInto($entityInfo['entity_id_field'] . ' IN (?)', $entityIds); - } - - $connection->delete($this->getTable($entityInfo['associations_table']), implode(' AND ', $where)); - - return $this; - } - - /** - * Retrieve rule's associated entity Ids by entity type - * - * @param int $ruleId - * @param string $entityType - * @return array - */ - public function getAssociatedEntityIds($ruleId, $entityType) - { - $entityInfo = $this->_getAssociatedEntityInfo($entityType); - - $select = $this->getConnection()->select()->from( - $this->getTable($entityInfo['associations_table']), - [$entityInfo['entity_id_field']] - )->where( - $entityInfo['rule_id_field'] . ' = ?', - $ruleId - ); - - return $this->getConnection()->fetchCol($select); - } - - /** - * Retrieve website ids of specified rule - * - * @param int $ruleId - * @return array - */ - public function getWebsiteIds($ruleId) - { - return $this->getAssociatedEntityIds($ruleId, 'website'); - } - - /** - * Retrieve customer group ids of specified rule - * - * @param int $ruleId - * @return array - */ - public function getCustomerGroupIds($ruleId) - { - return $this->getAssociatedEntityIds($ruleId, 'customer_group'); - } - - /** - * Retrieve correspondent entity information (associations table name, columns names) - * of rule's associated entity by specified entity type - * - * @param string $entityType - * @return array - * @throws \Magento\Framework\Exception\LocalizedException - */ - protected function _getAssociatedEntityInfo($entityType) - { - if (isset($this->_associatedEntitiesMap[$entityType])) { - return $this->_associatedEntitiesMap[$entityType]; - } - - throw new \Magento\Framework\Exception\LocalizedException( - __('There is no information about associated entity type "%1".', $entityType) - ); - } -} diff --git a/app/code/Magento/Rule/Model/ResourceModel/Rule/Collection/AbstractCollection.php b/app/code/Magento/Rule/Model/ResourceModel/Rule/Collection/AbstractCollection.php deleted file mode 100644 index 83006fe65061e..0000000000000 --- a/app/code/Magento/Rule/Model/ResourceModel/Rule/Collection/AbstractCollection.php +++ /dev/null @@ -1,159 +0,0 @@ - array( - * 'associations_table' => 'table_name', - * 'rule_id_field' => 'rule_id', - * 'entity_id_field' => 'entity_id' - * ), - * 'entity_type2' => array( - * 'associations_table' => 'table_name', - * 'rule_id_field' => 'rule_id', - * 'entity_id_field' => 'entity_id' - * ) - * .... - * ) - * - * @var array - */ - protected $_associatedEntitiesMap = []; - - /** - * Add website ids to rules data - * - * @return $this - */ - protected function _afterLoad() - { - parent::_afterLoad(); - if ($this->getFlag('add_websites_to_result') && $this->_items) { - /** @var \Magento\Rule\Model\AbstractModel $item */ - foreach ($this->_items as $item) { - $item->afterLoad(); - } - } - - return $this; - } - - /** - * Init flag for adding rule website ids to collection result - * - * @param bool|null $flag - * @return $this - */ - public function addWebsitesToResult($flag = null) - { - $flag = $flag === null ? true : $flag; - $this->setFlag('add_websites_to_result', $flag); - return $this; - } - - /** - * Limit rules collection by specific websites - * - * @param int|int[]|\Magento\Store\Model\Website $websiteId - * @return $this - */ - public function addWebsiteFilter($websiteId) - { - if (!$this->getFlag('is_website_table_joined')) { - $websiteIds = is_array($websiteId) ? $websiteId : [$websiteId]; - $entityInfo = $this->_getAssociatedEntityInfo('website'); - $this->setFlag('is_website_table_joined', true); - foreach ($websiteIds as $index => $website) { - if ($website instanceof \Magento\Store\Model\Website) { - $websiteIds[$index] = $website->getId(); - } - $websiteIds[$index] = (int) $websiteIds[$index]; - } - - $websiteSelect = $this->getConnection()->select(); - $websiteSelect->from( - $this->getTable($entityInfo['associations_table']), - [$entityInfo['rule_id_field']] - )->distinct( - true - )->where( - $this->getConnection()->quoteInto($entityInfo['entity_id_field'] . ' IN (?)', $websiteIds) - ); - $this->getSelect()->join( - ['website' => $websiteSelect], - 'main_table.' . $entityInfo['rule_id_field'] . ' = website.' . $entityInfo['rule_id_field'], - [] - ); - } - return $this; - } - - /** - * Provide support for website id filter - * - * @param string $field - * @param null|string|array $condition - * @return $this - */ - public function addFieldToFilter($field, $condition = null) - { - if ($field == 'website_ids') { - return $this->addWebsiteFilter($condition); - } - - parent::addFieldToFilter($field, $condition); - return $this; - } - - /** - * Filter collection to only active or inactive rules - * - * @param int $isActive - * @return $this - */ - public function addIsActiveFilter($isActive = 1) - { - if (!$this->getFlag('is_active_filter')) { - $this->addFieldToFilter('is_active', (int)$isActive ? 1 : 0); - $this->setFlag('is_active_filter', true); - } - return $this; - } - - /** - * Retrieve correspondent entity information of rule's associated entity by specified entity type - * - * (associations table name, columns names) - * - * @param string $entityType - * @throws \Magento\Framework\Exception\LocalizedException - * @return array - */ - protected function _getAssociatedEntityInfo($entityType) - { - if (isset($this->_associatedEntitiesMap[$entityType])) { - return $this->_associatedEntitiesMap[$entityType]; - } - - throw new \Magento\Framework\Exception\LocalizedException( - __('There is no information about associated entity type "%1".', $entityType) - ); - } -} diff --git a/app/code/Magento/Rule/README.md b/app/code/Magento/Rule/README.md deleted file mode 100644 index 8da892f2cb768..0000000000000 --- a/app/code/Magento/Rule/README.md +++ /dev/null @@ -1 +0,0 @@ -Magento_Rule module provides abstract implementation of rules and rule conditions that are extended by other modules, in particular by: Magento_SalesRule, Magento_CatalogRule, etc... diff --git a/app/code/Magento/Rule/Test/Mftf/Helper/RuleHelper.php b/app/code/Magento/Rule/Test/Mftf/Helper/RuleHelper.php deleted file mode 100644 index 502f2ec0822f2..0000000000000 --- a/app/code/Magento/Rule/Test/Mftf/Helper/RuleHelper.php +++ /dev/null @@ -1,62 +0,0 @@ -getModule('\Magento\FunctionalTestingFramework\Module\MagentoWebDriver'); - /** @var FacebookWebDriver $webDriver */ - $webDriver = $magentoWebDriver->webDriver; - $rows = $webDriver->findElements(WebDriverBy::cssSelector($firstNotEmptyRow)); - while (!empty($rows)) { - $rows[0]->click(); - $magentoWebDriver->waitForPageLoad(30); - $magentoWebDriver->click($deleteButton); - $magentoWebDriver->waitForPageLoad(30); - $magentoWebDriver->waitForElementVisible($modalAcceptButton, 10); - $magentoWebDriver->waitForPageLoad(60); - $magentoWebDriver->click($modalAcceptButton); - $magentoWebDriver->waitForPageLoad(60); - $magentoWebDriver->waitForLoadingMaskToDisappear(); - $magentoWebDriver->waitForElementVisible($successMessageContainer, 10); - $magentoWebDriver->see($successMessage, $successMessageContainer); - $rows = $webDriver->findElements(WebDriverBy::cssSelector($firstNotEmptyRow)); - } - } catch (\Exception $e) { - $this->fail($e->getMessage()); - } - } -} diff --git a/app/code/Magento/Rule/Test/Mftf/LICENSE.txt b/app/code/Magento/Rule/Test/Mftf/LICENSE.txt deleted file mode 100644 index 49525fd99da9c..0000000000000 --- a/app/code/Magento/Rule/Test/Mftf/LICENSE.txt +++ /dev/null @@ -1,48 +0,0 @@ - -Open Software License ("OSL") v. 3.0 - -This Open Software License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work: - -Licensed under the Open Software License version 3.0 - - 1. Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following: - - 1. to reproduce the Original Work in copies, either alone or as part of a collective work; - - 2. to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work; - - 3. to distribute or communicate copies of the Original Work and Derivative Works to the public, with the proviso that copies of Original Work or Derivative Works that You distribute or communicate shall be licensed under this Open Software License; - - 4. to perform the Original Work publicly; and - - 5. to display the Original Work publicly. - - 2. Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works. - - 3. Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work. - - 4. Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license. - - 5. External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c). - - 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. - - 7. Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer. - - 8. Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation. - - 9. Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including 'fair use' or 'fair dealing'). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c). - - 10. Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware. - - 11. Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License. - - 12. Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License. - - 13. Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. - - 14. Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - - 15. Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You. - - 16. Modification of This License. This License is Copyright (C) 2005 Lawrence Rosen. Permission is granted to copy, distribute, or communicate this License without modification. Nothing in this License permits You to modify this License as applied to the Original Work or to Derivative Works. However, You may modify the text of this License and copy, distribute or communicate your modified version (the "Modified License") and apply it to other original works of authorship subject to the following conditions: (i) You may not indicate in any way that your Modified License is the "Open Software License" or "OSL" and you may not use those names in the name of your Modified License; (ii) You must replace the notice specified in the first paragraph above with the notice "Licensed under " or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process. \ No newline at end of file diff --git a/app/code/Magento/Rule/Test/Mftf/LICENSE_AFL.txt b/app/code/Magento/Rule/Test/Mftf/LICENSE_AFL.txt deleted file mode 100644 index f39d641b18a19..0000000000000 --- a/app/code/Magento/Rule/Test/Mftf/LICENSE_AFL.txt +++ /dev/null @@ -1,48 +0,0 @@ - -Academic Free License ("AFL") v. 3.0 - -This Academic Free License (the "License") applies to any original work of authorship (the "Original Work") whose owner (the "Licensor") has placed the following licensing notice adjacent to the copyright notice for the Original Work: - -Licensed under the Academic Free License version 3.0 - - 1. Grant of Copyright License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, for the duration of the copyright, to do the following: - - 1. to reproduce the Original Work in copies, either alone or as part of a collective work; - - 2. to translate, adapt, alter, transform, modify, or arrange the Original Work, thereby creating derivative works ("Derivative Works") based upon the Original Work; - - 3. to distribute or communicate copies of the Original Work and Derivative Works to the public, under any license of your choice that does not contradict the terms and conditions, including Licensor's reserved rights and remedies, in this Academic Free License; - - 4. to perform the Original Work publicly; and - - 5. to display the Original Work publicly. - - 2. Grant of Patent License. Licensor grants You a worldwide, royalty-free, non-exclusive, sublicensable license, under patent claims owned or controlled by the Licensor that are embodied in the Original Work as furnished by the Licensor, for the duration of the patents, to make, use, sell, offer for sale, have made, and import the Original Work and Derivative Works. - - 3. Grant of Source Code License. The term "Source Code" means the preferred form of the Original Work for making modifications to it and all available documentation describing how to modify the Original Work. Licensor agrees to provide a machine-readable copy of the Source Code of the Original Work along with each copy of the Original Work that Licensor distributes. Licensor reserves the right to satisfy this obligation by placing a machine-readable copy of the Source Code in an information repository reasonably calculated to permit inexpensive and convenient access by You for as long as Licensor continues to distribute the Original Work. - - 4. Exclusions From License Grant. Neither the names of Licensor, nor the names of any contributors to the Original Work, nor any of their trademarks or service marks, may be used to endorse or promote products derived from this Original Work without express prior permission of the Licensor. Except as expressly stated herein, nothing in this License grants any license to Licensor's trademarks, copyrights, patents, trade secrets or any other intellectual property. No patent license is granted to make, use, sell, offer for sale, have made, or import embodiments of any patent claims other than the licensed claims defined in Section 2. No license is granted to the trademarks of Licensor even if such marks are included in the Original Work. Nothing in this License shall be interpreted to prohibit Licensor from licensing under terms different from this License any Original Work that Licensor otherwise would have a right to license. - - 5. External Deployment. The term "External Deployment" means the use, distribution, or communication of the Original Work or Derivative Works in any way such that the Original Work or Derivative Works may be used by anyone other than You, whether those works are distributed or communicated to those persons or made available as an application intended for use over a network. As an express condition for the grants of license hereunder, You must treat any External Deployment by You of the Original Work or a Derivative Work as a distribution under section 1(c). - - 6. Attribution Rights. You must retain, in the Source Code of any Derivative Works that You create, all copyright, patent, or trademark notices from the Source Code of the Original Work, as well as any notices of licensing and any descriptive text identified therein as an "Attribution Notice." You must cause the Source Code for any Derivative Works that You create to carry a prominent Attribution Notice reasonably calculated to inform recipients that You have modified the Original Work. - - 7. Warranty of Provenance and Disclaimer of Warranty. Licensor warrants that the copyright in and to the Original Work and the patent rights granted herein by Licensor are owned by the Licensor or are sublicensed to You under the terms of this License with the permission of the contributor(s) of those copyrights and patent rights. Except as expressly stated in the immediately preceding sentence, the Original Work is provided under this License on an "AS IS" BASIS and WITHOUT WARRANTY, either express or implied, including, without limitation, the warranties of non-infringement, merchantability or fitness for a particular purpose. THE ENTIRE RISK AS TO THE QUALITY OF THE ORIGINAL WORK IS WITH YOU. This DISCLAIMER OF WARRANTY constitutes an essential part of this License. No license to the Original Work is granted by this License except under this disclaimer. - - 8. Limitation of Liability. Under no circumstances and under no legal theory, whether in tort (including negligence), contract, or otherwise, shall the Licensor be liable to anyone for any indirect, special, incidental, or consequential damages of any character arising as a result of this License or the use of the Original Work including, without limitation, damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses. This limitation of liability shall not apply to the extent applicable law prohibits such limitation. - - 9. Acceptance and Termination. If, at any time, You expressly assented to this License, that assent indicates your clear and irrevocable acceptance of this License and all of its terms and conditions. If You distribute or communicate copies of the Original Work or a Derivative Work, You must make a reasonable effort under the circumstances to obtain the express assent of recipients to the terms of this License. This License conditions your rights to undertake the activities listed in Section 1, including your right to create Derivative Works based upon the Original Work, and doing so without honoring these terms and conditions is prohibited by copyright law and international treaty. Nothing in this License is intended to affect copyright exceptions and limitations (including "fair use" or "fair dealing"). This License shall terminate immediately and You may no longer exercise any of the rights granted to You by this License upon your failure to honor the conditions in Section 1(c). - - 10. Termination for Patent Action. This License shall terminate automatically and You may no longer exercise any of the rights granted to You by this License as of the date You commence an action, including a cross-claim or counterclaim, against Licensor or any licensee alleging that the Original Work infringes a patent. This termination provision shall not apply for an action alleging patent infringement by combinations of the Original Work with other software or hardware. - - 11. Jurisdiction, Venue and Governing Law. Any action or suit relating to this License may be brought only in the courts of a jurisdiction wherein the Licensor resides or in which Licensor conducts its primary business, and under the laws of that jurisdiction excluding its conflict-of-law provisions. The application of the United Nations Convention on Contracts for the International Sale of Goods is expressly excluded. Any use of the Original Work outside the scope of this License or after its termination shall be subject to the requirements and penalties of copyright or patent law in the appropriate jurisdiction. This section shall survive the termination of this License. - - 12. Attorneys' Fees. In any action to enforce the terms of this License or seeking damages relating thereto, the prevailing party shall be entitled to recover its costs and expenses, including, without limitation, reasonable attorneys' fees and costs incurred in connection with such action, including any appeal of such action. This section shall survive the termination of this License. - - 13. Miscellaneous. If any provision of this License is held to be unenforceable, such provision shall be reformed only to the extent necessary to make it enforceable. - - 14. Definition of "You" in This License. "You" throughout this License, whether in upper or lower case, means an individual or a legal entity exercising rights under, and complying with all of the terms of, this License. For legal entities, "You" includes any entity that controls, is controlled by, or is under common control with you. For purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. - - 15. Right to Use. You may use the Original Work in all ways not otherwise restricted or conditioned by this License or by law, and Licensor promises not to interfere with or be responsible for such uses by You. - - 16. Modification of This License. This License is Copyright © 2005 Lawrence Rosen. Permission is granted to copy, distribute, or communicate this License without modification. Nothing in this License permits You to modify this License as applied to the Original Work or to Derivative Works. However, You may modify the text of this License and copy, distribute or communicate your modified version (the "Modified License") and apply it to other original works of authorship subject to the following conditions: (i) You may not indicate in any way that your Modified License is the "Academic Free License" or "AFL" and you may not use those names in the name of your Modified License; (ii) You must replace the notice specified in the first paragraph above with the notice "Licensed under " or with a notice of your own that is not confusingly similar to the notice in this License; and (iii) You may not claim that your original works are open source software unless your Modified License has been approved by Open Source Initiative (OSI) and You comply with its license review and certification process. diff --git a/app/code/Magento/Rule/Test/Mftf/README.md b/app/code/Magento/Rule/Test/Mftf/README.md deleted file mode 100644 index 46d592f4ab950..0000000000000 --- a/app/code/Magento/Rule/Test/Mftf/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Rule Functional Tests - -The Functional Test Module for **Magento Rule** module. diff --git a/app/code/Magento/Rule/Test/Unit/Model/AbstractModelTest.php b/app/code/Magento/Rule/Test/Unit/Model/AbstractModelTest.php deleted file mode 100644 index 3e9fdcb753dc5..0000000000000 --- a/app/code/Magento/Rule/Test/Unit/Model/AbstractModelTest.php +++ /dev/null @@ -1,220 +0,0 @@ -localeDateMock = $this->getMockBuilder(TimezoneInterface::class) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - - $this->formFactoryMock = $this->getMockBuilder(FormFactory::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->registryMock = $this->getMockBuilder(Registry::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->contextMock = $this->getMockBuilder(Context::class) - ->disableOriginalConstructor() - ->setMethods(['getEventDispatcher']) - ->getMock(); - - $this->eventManagerMock = $this->getMockBuilder(ManagerInterface::class) - ->disableOriginalConstructor() - ->setMethods(['dispatch']) - ->getMockForAbstractClass(); - $this->contextMock->expects($this->any()) - ->method('getEventDispatcher') - ->willReturn($this->eventManagerMock); - - $resourceMock = $this->getMockBuilder(AbstractResource::class) - ->disableOriginalConstructor() - ->getMock(); - $resourceCollectionMock = $this->getMockBuilder(AbstractDb::class) - ->disableOriginalConstructor() - ->getMock(); - $extensionFactory = $this->getMockBuilder(ExtensionAttributesFactory::class) - ->disableOriginalConstructor() - ->getMock(); - $customAttributeFactory = $this->getMockBuilder(AttributeValueFactory::class) - ->disableOriginalConstructor() - ->getMock(); - - $this->model = $this->getMockForAbstractClass( - AbstractModel::class, - [ - 'context' => $this->contextMock, - 'registry' => $this->registryMock, - 'formFactory' => $this->formFactoryMock, - 'localeDate' => $this->localeDateMock, - 'resource' => $resourceMock, - 'resourceCollection' => $resourceCollectionMock, - 'data' => [], - 'extensionFactory' => $extensionFactory, - 'customAttributeFactory' => $customAttributeFactory, - 'serializer' => $this->getSerializerMock(), - ] - ); - } - - /** - * Get mock for serializer - * - * @return Json|MockObject - */ - private function getSerializerMock() - { - $serializerMock = $this->getMockBuilder(Json::class) - ->disableOriginalConstructor() - ->setMethods(['serialize', 'unserialize']) - ->getMock(); - - $serializerMock->expects($this->any()) - ->method('serialize') - ->willReturnCallback( - function ($value) { - return json_encode($value); - } - ); - - $serializerMock->expects($this->any()) - ->method('unserialize') - ->willReturnCallback( - function ($value) { - return json_decode($value, true); - } - ); - - return $serializerMock; - } - - public function testGetConditions() - { - $conditionsArray = ['conditions' => 'serialized']; - $serializedConditions = json_encode($conditionsArray); - $conditions = $this->getMockBuilder(Combine::class) - ->setMethods(['setRule', 'setId', 'setPrefix', 'loadArray']) - ->disableOriginalConstructor() - ->getMock(); - - $conditions->expects($this->once())->method('setRule')->willReturnSelf(); - $conditions->expects($this->once())->method('setId')->willReturnSelf(); - $conditions->expects($this->once())->method('setPrefix')->willReturnSelf(); - - $this->model->expects($this->once())->method('getConditionsInstance')->willReturn($conditions); - - $this->model->setConditionsSerialized($serializedConditions); - - $conditions->expects($this->once())->method('loadArray')->with($conditionsArray); - - $this->assertEquals($conditions, $this->model->getConditions()); - } - - public function testGetActions() - { - $actionsArray = ['actions' => 'some_actions']; - $actionsSerialized = json_encode($actionsArray); - $actions = $this->getMockBuilder(Collection::class) - ->setMethods(['setRule', 'setId', 'setPrefix', 'loadArray']) - ->disableOriginalConstructor() - ->getMock(); - - $actions->expects($this->once())->method('setRule')->willReturnSelf(); - $actions->expects($this->once())->method('setId')->willReturnSelf(); - $actions->expects($this->once())->method('setPrefix')->willReturnSelf(); - - $this->model->expects($this->once())->method('getActionsInstance')->willReturn($actions); - - $this->model->setActionsSerialized($actionsSerialized); - - $actions->expects($this->once())->method('loadArray')->with($actionsArray); - - $this->assertEquals($actions, $this->model->getActions()); - } - - public function testBeforeSave() - { - $conditions = $this->getMockBuilder(Combine::class) - ->setMethods(['asArray']) - ->disableOriginalConstructor() - ->getMock(); - - $actions = $this->getMockBuilder(Collection::class) - ->setMethods(['asArray']) - ->disableOriginalConstructor() - ->getMock(); - - $this->model->setConditions($conditions); - $this->model->setActions($actions); - - $conditions->expects($this->any())->method('asArray')->willReturn(['conditions' => 'array']); - $actions->expects($this->any())->method('asArray')->willReturn(['actions' => 'array']); - - $this->eventManagerMock->expects($this->exactly(2))->method('dispatch'); - - $this->assertEquals($this->model, $this->model->beforeSave()); - $this->assertEquals(json_encode(['conditions' => 'array']), $this->model->getConditionsSerialized()); - $this->assertEquals(json_encode(['actions' => 'array']), $this->model->getActionsSerialized()); - } -} diff --git a/app/code/Magento/Rule/Test/Unit/Model/ActionFactoryTest.php b/app/code/Magento/Rule/Test/Unit/Model/ActionFactoryTest.php deleted file mode 100644 index ff4ae03af6009..0000000000000 --- a/app/code/Magento/Rule/Test/Unit/Model/ActionFactoryTest.php +++ /dev/null @@ -1,53 +0,0 @@ -objectManagerMock = $this->getMockForAbstractClass(ObjectManagerInterface::class); - - $this->objectManagerHelper = new ObjectManagerHelper($this); - $this->actionFactory = $this->objectManagerHelper->getObject( - ActionFactory::class, - [ - 'objectManager' => $this->objectManagerMock - ] - ); - } - - public function testCreate() - { - $type = '1'; - $data = ['data2', 'data3']; - $this->objectManagerMock->expects($this->once())->method('create')->with($type, $data); - $this->actionFactory->create($type, $data); - } -} diff --git a/app/code/Magento/Rule/Test/Unit/Model/Condition/AbstractConditionTest.php b/app/code/Magento/Rule/Test/Unit/Model/Condition/AbstractConditionTest.php deleted file mode 100644 index 91f1c4b942f75..0000000000000 --- a/app/code/Magento/Rule/Test/Unit/Model/Condition/AbstractConditionTest.php +++ /dev/null @@ -1,242 +0,0 @@ -_condition = $this->getMockForAbstractClass( - AbstractCondition::class, - [], - '', - false, - false, - true, - ['getInputType'] - ); - } - - public function testGetjointTables() - { - $this->_condition->setAttribute('category_ids'); - $this->assertEquals([], $this->_condition->getTablesToJoin()); - $this->_condition->setAttribute('gdsjkfghksldjfg'); - $this->assertEmpty($this->_condition->getTablesToJoin()); - } - - public function testGetMappedSqlField() - { - $this->_condition->setAttribute('category_ids'); - $this->assertEquals('category_ids', $this->_condition->getMappedSqlField()); - } - - /** - * @return array - */ - public function validateAttributeDataProvider() - { - return [ - // value, operator, valueForValidate, expectedResult - [1, '==', new \stdClass(), false], - [new \stdClass(), '==', new \stdClass(), false], - - [1, '==', 1, true], - [0, '==', 1, false], - ['0', '==', 1, false], - ['1', '==', 1, true], - ['x', '==', 'x', true], - ['x', '==', 0, false], - - [1, '!=', 1, false], - [0, '!=', 1, true], - ['0', '!=', 1, true], - ['1', '!=', 1, false], - ['x', '!=', 'x', false], - ['x', '!=', 0, true], - - [1, '==', [1], true], - [1, '!=', [1], false], - [1, '==', [3, 1, 5], false], - [1, '!=', [1, 5], true], - - [[1,2,3], '==', '1,2,3', false], - [[1], '==', 1, false], - - // Note: validated value is on the right, so read expression in the array from right to left - // e.g.: 1, <=, 0 actually is 0 <= 1. - [1, '>', 1, false], - [1, '<=', 1, true], - [1, '<=', '1', true], - [1, '<=', 0, true], - [0, '>', [1], false], - - [1, '<', 1, false], - [1, '>=', 1, true], - [1, '>=', '1', true], - [1, '>=', 0, false], - [0, '<', [1], false], - - [[1], '!{}', [], false], - [[1], '!{}', [1], false], - [[1], '!{}', [0], false], - ]; - } - - /** - * @param $existingValue - * @param $operator - * @param $valueForValidate - * @param $expectedResult - * - * @dataProvider validateAttributeDataProvider - */ - public function testValidateAttribute($existingValue, $operator, $valueForValidate, $expectedResult) - { - $this->_condition->setOperator($operator); - $this->_condition->setData('value_parsed', $existingValue); - $this->assertEquals( - $expectedResult, - $this->_condition->validateAttribute($valueForValidate), - "Failed asserting that " - . var_export($existingValue, true) - . $operator - . var_export($valueForValidate, true) - ); - } - - /** - * @param $existingValue - * @param $operator - * @param $valueForValidate - * @param $expectedResult - * - * @dataProvider validateAttributeDataProvider - */ - public function testValidate($existingValue, $operator, $valueForValidate, $expectedResult) - { - $objectMock = $this->createPartialMock( - AbstractModel::class, - ['hasData', 'load', 'getId', 'getData'] - ); - $objectMock->expects($this->once()) - ->method('hasData') - ->willReturn(false); - $objectMock->expects($this->once()) - ->method('getId') - ->willReturn(7); - $objectMock->expects($this->once()) - ->method('load') - ->with(7); - $objectMock->expects($this->once()) - ->method('getData') - ->willReturn($valueForValidate); - - $this->_condition->setOperator($operator); - $this->_condition->setData('value_parsed', $existingValue); - $this->assertEquals( - $expectedResult, - $this->_condition->validate($objectMock), - "Failed asserting that " - . var_export($existingValue, true) - . $operator - . var_export($valueForValidate, true) - ); - } - - /** - * @return array - */ - public function validateAttributeArrayInputTypeDataProvider() - { - return [ - // value, operator, valueForValidate, expectedResult, inputType - [[1, 2, 3], '==', [2, 1, 3], true, 'multiselect'], - [[1, 2], '==', [2, 3], true, 'multiselect'], - [[1, 1, 3], '==', [2, 4], false, 'multiselect'], - [[1, 2], '!=', [2, 3], false, 'multiselect'], - [[1, 2], '!=', 1, false, 'multiselect'], - - [[1, 2, 3], '{}', '1', true, 'grid'], - [[1, 2, 3], '{}', '8', false, 'grid'], - [[1, 2, 3], '{}', 5, false, 'grid'], - [[1, 2, 3], '{}', [2, 3, 4], true, 'grid'], - [[1, 2, 3], '{}', [4], false, 'grid'], - [[3], '{}', [], false, 'grid'], - [1, '{}', 1, false, 'grid'], - [1, '!{}', [1, 2, 3], false, 'grid'], - [1, '!{}', [], false, 'grid'], - [[1], '!{}', [], false, 'grid'], - [[1], '{}', null, false, 'grid'], - [null, '{}', null, true, 'input'], - [null, '!{}', null, false, 'input'], - [null, '{}', [1], false, 'input'], - - [[1, 2, 3], '()', 1, true, 'select'], - [[1, 2, 3], '!()', 1, false, 'select'], - [[1], '()', 3, false, 'select'], - [[1], '!()', 3, true, 'select'], - [3, '()', 3, false, 'select'], - [[3], '()', [3], true, 'select'], - [3, '()', [3], false, 'select'], - - ]; - } - - /** - * @param $existingValue - * @param $operator - * @param $valueForValidate - * @param $expectedResult - * @param $inputType - * - * @dataProvider validateAttributeArrayInputTypeDataProvider - */ - public function testValidateArrayOperatorType( - $existingValue, - $operator, - $valueForValidate, - $expectedResult, - $inputType - ) { - $this->_condition->setOperator($operator); - $this->_condition->setData('value_parsed', $existingValue); - $this->_condition->getDefaultOperatorInputByType(); - $this->_condition - ->expects($this->any()) - ->method('getInputType') - ->willReturn($inputType); - - $this->assertEquals( - $expectedResult, - $this->_condition->validateAttribute($valueForValidate), - "Failed asserting that " - . var_export($existingValue, true) - . $operator - . var_export($valueForValidate, true) - ); - } - - public function testGetValueParsed() - { - $value = [1, 2, 3, 4, 5, 6, 7, 8, 9]; - $this->_condition->setValue(['1,2,3,4,5,6,7,8,9']); - $this->_condition->setOperator('()'); - $this->assertEquals($value, $this->_condition->getValueParsed()); - } -} diff --git a/app/code/Magento/Rule/Test/Unit/Model/Condition/CombineTest.php b/app/code/Magento/Rule/Test/Unit/Model/Condition/CombineTest.php deleted file mode 100644 index aeb385cb5219c..0000000000000 --- a/app/code/Magento/Rule/Test/Unit/Model/Condition/CombineTest.php +++ /dev/null @@ -1,156 +0,0 @@ -conditionFactoryMock = $this->getMockBuilder(ConditionFactory::class) - ->disableOriginalConstructor() - ->setMethods([]) - ->getMock(); - - $this->loggerMock = $this->getMockBuilder(LoggerInterface::class) - ->disableOriginalConstructor() - ->setMethods([]) - ->getMockForAbstractClass(); - - $this->conditionObjectMock = $this->getMockBuilder(Product::class) - ->disableOriginalConstructor() - ->setMethods([]) - ->getMock(); - - $this->combine = (new ObjectManagerHelper($this))->getObject( - Combine::class, - [ - "conditionFactory" => $this->conditionFactoryMock, - "logger" => $this->loggerMock, - ] - ); - } - - /** - * - * @covers \Magento\Rule\Model\Condition\AbstractCondition::getValueName - * - * @dataProvider optionValuesData - * - * @param string|array $value - * @param string $expectingData - */ - public function testGetValueName($value, $expectingData) - { - $this->combine - ->setValueOption(['option_key' => 'option_value']) - ->setValue($value); - - $this->assertEquals($expectingData, $this->combine->getValueName()); - } - - /** - * @return array - */ - public function optionValuesData() - { - return [ - ['option_key', 'option_value'], - ['option_value', 'option_value'], - [['option_key'], 'option_value'], - ['', '...'], - ]; - } - - public function testLoadArray() - { - $array['conditions'] = [ - [ - 'type' => 'test', - 'attribute' => '', - 'operator' => '', - 'value' => '', - ], - ]; - - $this->conditionObjectMock->expects($this->once()) - ->method('loadArray') - ->with($array['conditions'][0], 'conditions'); - - $this->conditionFactoryMock->expects($this->once()) - ->method('create') - ->with($array['conditions'][0]['type']) - ->willReturn($this->conditionObjectMock); - - $this->loggerMock->expects($this->never()) - ->method('critical'); - - $result = $this->combine->loadArray($array); - - $this->assertInstanceOf(Combine::class, $result); - } - - public function testLoadArrayLoggerCatchException() - { - $array['conditions'] = [ - [ - 'type' => '', - 'attribute' => '', - 'operator' => '', - 'value' => '', - ], - ]; - - $this->conditionObjectMock->expects($this->never()) - ->method('loadArray'); - - $this->conditionFactoryMock->expects($this->once()) - ->method('create') - ->with($array['conditions'][0]['type']) - ->willThrowException(new \Exception('everything is fine, it is test')); - - $this->loggerMock->expects($this->once()) - ->method('critical') - ->with(); - - $result = $this->combine->loadArray($array); - - $this->assertInstanceOf(Combine::class, $result); - } -} diff --git a/app/code/Magento/Rule/Test/Unit/Model/Condition/Product/AbstractProductTest.php b/app/code/Magento/Rule/Test/Unit/Model/Condition/Product/AbstractProductTest.php deleted file mode 100644 index e19d56dd46f57..0000000000000 --- a/app/code/Magento/Rule/Test/Unit/Model/Condition/Product/AbstractProductTest.php +++ /dev/null @@ -1,566 +0,0 @@ -_condition = $this->getMockForAbstractClass( - AbstractProduct::class, - [], - '', - false - ); - - $this->productCategoryListProperty = new \ReflectionProperty( - AbstractProduct::class, - 'productCategoryList' - ); - $this->productCategoryListProperty->setAccessible(true); - - $this->_entityAttributeValuesProperty = new \ReflectionProperty( - AbstractProduct::class, - '_entityAttributeValues' - ); - $this->_entityAttributeValuesProperty->setAccessible(true); - - $this->_configProperty = new \ReflectionProperty( - AbstractProduct::class, - '_config' - ); - $this->_configProperty->setAccessible(true); - } - - /** - * Test to validate equal category id condition - */ - public function testValidateAttributeEqualCategoryId() - { - $product = $this->getMockBuilder(AbstractModel::class) - ->addMethods(["getAttribute"]) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - $this->_condition->setAttribute('category_ids'); - $this->_condition->setValueParsed('1'); - $this->_condition->setOperator('{}'); - - $productCategoryList = $this->getMockBuilder(ProductCategoryList::class) - ->disableOriginalConstructor() - ->getMock(); - $productCategoryList->method('getCategoryIds')->willReturn([1, 2]); - $this->productCategoryListProperty->setValue( - $this->_condition, - $productCategoryList - ); - $this->_configProperty->setValue( - $this->_condition, - $this->getMockBuilder(Config::class) - ->disableOriginalConstructor() - ->getMock() - ); - - $this->assertTrue($this->_condition->validate($product)); - } - - /** - * Test to validate empty attribute condition - */ - public function testValidateEmptyEntityAttributeValues() - { - $product = $this->getMockBuilder(AbstractModel::class) - ->addMethods(["getAttribute"]) - ->onlyMethods(['getResource']) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - $product->expects($this->once()) - ->method('getResource') - ->willReturn(null); - $product->setId(1); - $configProperty = new \ReflectionProperty( - AbstractProduct::class, - '_entityAttributeValues' - ); - $configProperty->setAccessible(true); - $configProperty->setValue($this->_condition, []); - $this->assertFalse($this->_condition->validate($product)); - } - - /** - * Test to validate empty attribute value condition - */ - public function testValidateEmptyEntityAttributeValuesWithResource() - { - $product = $this->getMockBuilder(AbstractModel::class) - ->addMethods(["getAttribute"]) - ->onlyMethods(['getResource']) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - $product->setId(1); - $time = '04/19/2012 11:59 am'; - $product->setData('someAttribute', $time); - $this->_condition->setAttribute('someAttribute'); - $this->_entityAttributeValuesProperty->setValue($this->_condition, []); - - $this->_configProperty->setValue( - $this->_condition, - $this->createMock(Config::class) - ); - - $attribute = new DataObject(); - $attribute->setBackendType('datetime'); - - $newResource = $this->createPartialMock(Product::class, ['getAttribute']); - $newResource->expects($this->any()) - ->method('getAttribute') - ->with('someAttribute') - ->willReturn($attribute); - $newResource->_config = $this->createMock(Config::class); - $product->expects($this->atLeastOnce()) - ->method('getResource') - ->willReturn($newResource); - - $this->assertFalse($this->_condition->validate($product)); - - $product->setData('someAttribute', 'option1,option2,option3'); - $attribute->setBackendType('null'); - $attribute->setFrontendInput('multiselect'); - - $newResource = $this->createPartialMock(Product::class, ['getAttribute']); - $newResource->expects($this->any()) - ->method('getAttribute') - ->with('someAttribute') - ->willReturn($attribute); - $newResource->_config = $this->createMock(Config::class); - - $product->setResource($newResource); - $this->assertFalse($this->_condition->validate($product)); - } - - /** - * Test to validate set entity attribute value with resource condition - */ - public function testValidateSetEntityAttributeValuesWithResource() - { - $this->_condition->setAttribute('someAttribute'); - $product = $this->getMockBuilder(AbstractModel::class) - ->addMethods(['getAttribute']) - ->onlyMethods(['getResource']) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - $product->setAtribute('attribute'); - $product->setData('someAttribute', ''); - $product->setId(12); - - $this->_configProperty->setValue( - $this->_condition, - $this->createMock(Config::class) - ); - $this->_entityAttributeValuesProperty->setValue( - $this->_condition, - $this->createMock(Config::class) - ); - - $attribute = new DataObject(); - $attribute->setBackendType('datetime'); - - $newResource = $this->createPartialMock(Product::class, ['getAttribute']); - $newResource->expects($this->any()) - ->method('getAttribute') - ->with('someAttribute') - ->willReturn($attribute); - $newResource->_config = $this->createMock(Config::class); - - $product->expects($this->atLeastOnce()) - ->method('getResource') - ->willReturn($newResource); - - $this->_entityAttributeValuesProperty->setValue( - $this->_condition, - [ - 1 => ['Dec. 1979 17:30'], - 2 => ['Dec. 1979 17:30'], - 3 => ['Dec. 1979 17:30'] - ] - ); - $this->assertFalse($this->_condition->validate($product)); - } - - /** - * Test to validate set entity attribute value without resource condition - */ - public function testValidateSetEntityAttributeValuesWithoutResource() - { - $product = $this->getMockBuilder(AbstractModel::class) - ->addMethods(['someMethod']) - ->onlyMethods(['getResource', 'load']) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - $this->_condition->setAttribute('someAttribute'); - $product->setAtribute('attribute'); - $product->setId(12); - - $this->_configProperty->setValue( - $this->_condition, - $this->createMock(Config::class) - ); - - $this->_entityAttributeValuesProperty->setValue( - $this->_condition, - $this->createMock(Config::class) - ); - - $attribute = new DataObject(); - $attribute->setBackendType('multiselect'); - - $newResource = $this->createPartialMock(Product::class, ['getAttribute']); - $newResource->expects($this->any()) - ->method('getAttribute') - ->with('someAttribute') - ->willReturn($attribute); - $newResource->_config = $this->createMock(Config::class); - - $product->expects($this->atLeastOnce()) - ->method('getResource') - ->willReturn($newResource); - - $this->_entityAttributeValuesProperty->setValue( - $this->_condition, - [ - 1 => [''], - 2 => ['option1,option2,option3'], - 3 => ['option1,option2,option3'] - ] - ); - - $this->assertFalse($this->_condition->validate($product)); - - $attribute = new DataObject(); - $attribute->setBackendType(null); - $attribute->setFrontendInput('multiselect'); - - $newResource = $this->createPartialMock(Product::class, ['getAttribute']); - $newResource->expects($this->any()) - ->method('getAttribute') - ->with('someAttribute') - ->willReturn($attribute); - $newResource->_config = $this->createMock(Config::class); - - $product->setResource($newResource); - $product->setId(1); - $product->setData('someAttribute', 'value'); - - $this->assertFalse($this->_condition->validate($product)); - } - - /** - * Test to get tables to join - */ - public function testGetjointTables() - { - $this->_condition->setAttribute('category_ids'); - $this->assertEquals([], $this->_condition->getTablesToJoin()); - } - - /** - * Test to get mapped sql field - */ - public function testGetMappedSqlField() - { - $this->_condition->setAttribute('category_ids'); - $this->assertEquals('e.entity_id', $this->_condition->getMappedSqlField()); - $this->_condition->setAttribute('attribute_set_id'); - $this->assertEquals('e.attribute_set_id', $this->_condition->getMappedSqlField()); - } - - /** - * Test to prepare value options - * - * @param array $setData - * @param string $attributeObjectFrontendInput - * @param array $attrObjectSourceAllOptionsValue - * @param array $attrSetCollectionOptionsArray - * @param bool $expectedAttrObjSourceAllOptionsParam - * @param array $expectedValueSelectOptions - * @param array $expectedValueOption - * @dataProvider prepareValueOptionsDataProvider - * @SuppressWarnings(PHPMD.NPathComplexity) - */ - public function testPrepareValueOptions( - $setData, - $attributeObjectFrontendInput, - $attrObjectSourceAllOptionsValue, - $attrSetCollectionOptionsArray, - $expectedAttrObjSourceAllOptionsParam, - $expectedValueSelectOptions, - $expectedValueOption - ) { - foreach ($setData as $key => $value) { - $this->_condition->setData($key, $value); - } - - $attrObjectSourceMock = $this->getMockBuilder(AbstractSource::class) - ->setMethods(['getAllOptions']) - ->disableOriginalConstructor() - ->getMock(); - $attrObjectSourceMock - ->expects((null === $expectedAttrObjSourceAllOptionsParam) ? $this->never() : $this->once()) - ->method('getAllOptions') - ->with($expectedAttrObjSourceAllOptionsParam) - ->willReturn($attrObjectSourceAllOptionsValue); - - $attributeObjectMock = $this->getMockBuilder(Attribute::class) - ->setMethods(['usesSource', 'getFrontendInput', 'getSource', 'getAllOptions']) - ->disableOriginalConstructor() - ->getMock(); - $attributeObjectMock->method('usesSource')->willReturn(true); - $attributeObjectMock - ->expects((null === $attributeObjectFrontendInput) ? $this->never() : $this->once()) - ->method('getFrontendInput') - ->willReturn($attributeObjectFrontendInput); - $attributeObjectMock->method('getSource')->willReturn($attrObjectSourceMock); - - $entityTypeMock = $this->getMockBuilder(Type::class) - ->setMethods(['getId']) - ->disableOriginalConstructor() - ->getMock(); - $entityTypeMock->method('getId')->willReturn('SomeEntityType'); - - $configValueMock = $this->createPartialMock( - Config::class, - ['getAttribute', 'getEntityType'] - ); - $configValueMock->method('getAttribute')->willReturn($attributeObjectMock); - $configValueMock->method('getEntityType')->willReturn($entityTypeMock); - - $configProperty = new \ReflectionProperty( - AbstractProduct::class, - '_config' - ); - $configProperty->setAccessible(true); - $configProperty->setValue($this->_condition, $configValueMock); - - $attrSetCollectionValueMock = $this - ->getMockBuilder(Collection::class) - ->setMethods(['setEntityTypeFilter', 'load', 'toOptionArray']) - ->disableOriginalConstructor() - ->getMock(); - - $attrSetCollectionValueMock->method('setEntityTypeFilter')->willReturnSelf(); - $attrSetCollectionValueMock->method('load')->willReturnSelf(); - $attrSetCollectionValueMock - ->expects((null === $attrSetCollectionOptionsArray) ? $this->never() : $this->once()) - ->method('toOptionArray') - ->willReturn($attrSetCollectionOptionsArray); - - $attrSetCollectionProperty = new \ReflectionProperty( - AbstractProduct::class, - '_attrSetCollection' - ); - $attrSetCollectionProperty->setAccessible(true); - $attrSetCollectionProperty->setValue($this->_condition, $attrSetCollectionValueMock); - - $testedMethod = new \ReflectionMethod( - AbstractProduct::class, - '_prepareValueOptions' - ); - $testedMethod->setAccessible(true); - $testedMethod->invoke($this->_condition); - - $this->assertEquals($expectedValueSelectOptions, $this->_condition->getData('value_select_options')); - $this->assertEquals($expectedValueOption, $this->_condition->getData('value_option')); - } - - /** - * Data provider for prepare value options - * - * @return array - * @SuppressWarnings(PHPMD.ExcessiveMethodLength) - */ - public function prepareValueOptionsDataProvider() - { - return [ - [ - [ - 'value_select_options' => ['key' => 'value'], - 'value_option' => ['k' => 'v'], - ], null, null, null, null, ['key' => 'value'], ['k' => 'v'], - ], - [ - ['attribute' => 'attribute_set_id'], - null, - null, - [ - ['value' => 'value1', 'label' => 'Label for value 1'], - ['value' => 'value2', 'label' => 'Label for value 2'], - ], - null, - [ - ['value' => 'value1', 'label' => 'Label for value 1'], - ['value' => 'value2', 'label' => 'Label for value 2'], - ], - [ - 'value1' => 'Label for value 1', - 'value2' => 'Label for value 2' - ] - ], - [ - [ - 'value_select_options' => [ - ['value' => 'value3', 'label' => 'Label for value 3'], - ['value' => 'value4', 'label' => 'Label for value 4'], - ], - 'attribute' => 'type_id', - ], - null, - null, - null, - null, - [ - ['value' => 'value3', 'label' => 'Label for value 3'], - ['value' => 'value4', 'label' => 'Label for value 4'], - ], - [ - 'value3' => 'Label for value 3', - 'value4' => 'Label for value 4' - ] - ], - [ - [ - 'value_select_options' => [ - 'value5' => 'Label for value 5', - 'value6' => 'Label for value 6', - ], - 'attribute' => 'type_id', - ], - null, - null, - null, - null, - [ - ['value' => 'value5', 'label' => 'Label for value 5'], - ['value' => 'value6', 'label' => 'Label for value 6'], - ], - [ - 'value5' => 'Label for value 5', - 'value6' => 'Label for value 6' - ] - ], - [ - [], - 'multiselect', - [ - ['value' => 'value7', 'label' => 'Label for value 7'], - ['value' => 'value8', 'label' => 'Label for value 8'], - ], - null, - false, - [ - ['value' => 'value7', 'label' => 'Label for value 7'], - ['value' => 'value8', 'label' => 'Label for value 8'], - ], - [ - 'value7' => 'Label for value 7', - 'value8' => 'Label for value 8', - ], - ], - [ - [], - 'multiselect', - [ - ['value' => 'valueA', 'label' => 'Label for value A'], - ['value' => ['array value'], 'label' => 'Label for value B'], - ], - null, - false, - [ - ['value' => 'valueA', 'label' => 'Label for value A'], - ['value' => ['array value'], 'label' => 'Label for value B'], - ], - [ - 'valueA' => 'Label for value A', - ], - ], - [ - [], - 'select', - [ - ['value' => 'value7', 'label' => 'Label for value 7'], - ['value' => 'value8', 'label' => 'Label for value 8'], - ['value' => 'default', 'label' => 'Default Option'] - ], - null, - true, - [ - ['value' => 'value7', 'label' => 'Label for value 7'], - ['value' => 'value8', 'label' => 'Label for value 8'], - ['value' => 'default', 'label' => 'Default Option'] - ], - [ - 'value7' => 'Label for value 7', - 'value8' => 'Label for value 8', - 'default' => 'Default Option' - ], - ] - ]; - } -} diff --git a/app/code/Magento/Rule/Test/Unit/Model/Condition/Sql/BuilderTest.php b/app/code/Magento/Rule/Test/Unit/Model/Condition/Sql/BuilderTest.php deleted file mode 100644 index d2e19b4032d04..0000000000000 --- a/app/code/Magento/Rule/Test/Unit/Model/Condition/Sql/BuilderTest.php +++ /dev/null @@ -1,150 +0,0 @@ -createMock(Expression::class); - $expressionFactory = $this->createPartialMock( - ExpressionFactory::class, - ['create'] - ); - $expressionFactory->expects($this->any()) - ->method('create') - ->willReturn($expressionMock); - $this->builder = (new ObjectManagerHelper($this))->getObject( - Builder::class, - ['expressionFactory' => $expressionFactory] - ); - } - - /** - * @return void - */ - public function testAttachConditionToCollection(): void - { - $collection = $this->getMockBuilder(AbstractCollection::class) - ->addMethods(['getStoreId', 'getDefaultStoreId']) - ->onlyMethods(['getResource', 'getSelect']) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - $combine = $this->createPartialMock(Combine::class, ['getConditions']); - $resource = $this->createPartialMock(Mysql::class, ['getConnection']); - $select = $this->createPartialMock(Select::class, ['where']); - $select->expects($this->never()) - ->method('where'); - - $connection = $this->getMockForAbstractClass( - AdapterInterface::class, - [], - '', - false - ); - - $collection->expects($this->once()) - ->method('getResource') - ->willReturn($resource); - $collection->expects($this->any()) - ->method('getSelect') - ->willReturn($select); - - $resource->expects($this->once()) - ->method('getConnection') - ->willReturn($connection); - - $combine->expects($this->any()) - ->method('getConditions') - ->willReturn([]); - - $this->builder->attachConditionToCollection($collection, $combine); - } - - /** - * Test for attach condition to collection with operator in html format - * - * @return void - */ - public function testAttachConditionAsHtmlToCollection(): void - { - $abstractCondition = $this->getMockForAbstractClass( - AbstractCondition::class, - [], - '', - false, - false, - true, - ['getOperatorForValidate', 'getMappedSqlField', 'getAttribute', 'getBindArgumentValue'] - ); - - $abstractCondition->expects($this->once())->method('getMappedSqlField')->willReturn('argument'); - $abstractCondition->expects($this->once())->method('getOperatorForValidate')->willReturn('>'); - $abstractCondition - ->method('getAttribute') - ->willReturnOnConsecutiveCalls('attribute', 'attribute'); - $abstractCondition->expects($this->once())->method('getBindArgumentValue')->willReturn(10); - - $conditions = [$abstractCondition]; - $collection = $this->createPartialMock( - AbstractCollection::class, - [ - 'getResource', - 'getSelect' - ] - ); - $combine = $this->getMockBuilder(Combine::class) - ->addMethods(['getAggregator']) - ->onlyMethods(['getConditions', 'getValue']) - ->disableOriginalConstructor() - ->getMock(); - - $resource = $this->createPartialMock(Mysql::class, ['getConnection']); - $select = $this->createPartialMock(Select::class, ['where']); - $select->expects($this->never())->method('where'); - - $connection = $this->getMockForAbstractClass( - AdapterInterface::class, - ['quoteInto'], - '', - false - ); - - $connection->expects($this->once())->method('quoteInto')->with(' > ?', 10)->willReturn(' > 10'); - $collection->expects($this->once())->method('getResource')->willReturn($resource); - $resource->expects($this->once())->method('getConnection')->willReturn($connection); - $combine->expects($this->once())->method('getValue')->willReturn('attribute'); - $combine->expects($this->once())->method('getAggregator')->willReturn(' AND '); - $combine - ->method('getConditions') - ->willReturnOnConsecutiveCalls($conditions, $conditions, $conditions, $conditions); - - $this->builder->attachConditionToCollection($collection, $combine); - } -} diff --git a/app/code/Magento/Rule/Test/Unit/Model/Condition/Sql/ExpressionTest.php b/app/code/Magento/Rule/Test/Unit/Model/Condition/Sql/ExpressionTest.php deleted file mode 100644 index c93940acab682..0000000000000 --- a/app/code/Magento/Rule/Test/Unit/Model/Condition/Sql/ExpressionTest.php +++ /dev/null @@ -1,24 +0,0 @@ -getObject( - Expression::class, - ['expression' => 'SQL_EXPRESSION'] - ); - $this->assertEquals('(SQL_EXPRESSION)', (string)$expression); - } -} diff --git a/app/code/Magento/Rule/Test/Unit/Model/ConditionFactoryTest.php b/app/code/Magento/Rule/Test/Unit/Model/ConditionFactoryTest.php deleted file mode 100644 index 8396ee9cb7b3e..0000000000000 --- a/app/code/Magento/Rule/Test/Unit/Model/ConditionFactoryTest.php +++ /dev/null @@ -1,106 +0,0 @@ -objectManagerMock = $this->getMockForAbstractClass(ObjectManagerInterface::class); - - $this->objectManagerHelper = new ObjectManagerHelper($this); - $this->conditionFactory = $this->objectManagerHelper->getObject( - ConditionFactory::class, - [ - 'objectManager' => $this->objectManagerMock - ] - ); - } - - public function testExceptingToCallMethodCreateInObjectManager() - { - $type = Combine::class; - $origin = $this->getMockBuilder($type) - ->disableOriginalConstructor() - ->getMock(); - - $this->objectManagerMock - ->expects($this->once()) - ->method('create') - ->with($type) - ->willReturn($origin); - - $this->conditionFactory->create($type); - } - - public function testExceptingClonedObject() - { - $type = Combine::class; - $origin = $this->getMockBuilder($type) - ->disableOriginalConstructor() - ->getMock(); - - $this->objectManagerMock->expects($this->once()) - ->method('create') - ->with($type) - ->willReturn($origin); - - $cloned = $this->conditionFactory->create($type); - - $this->assertNotSame($cloned, $origin); - } - - public function testCreateExceptionClass() - { - $type = 'type'; - $this->objectManagerMock - ->expects($this->never()) - ->method('create'); - - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('Class does not exist'); - - $this->conditionFactory->create($type); - } - - public function testCreateExceptionType() - { - $type = ConditionFactory::class; - - $this->objectManagerMock - ->expects($this->never()) - ->method('create') - ->with($type) - ->willReturn(new \stdClass()); - $this->expectException(\InvalidArgumentException::class); - $this->expectExceptionMessage('Class does not implement condition interface'); - $this->conditionFactory->create($type); - } -} diff --git a/app/code/Magento/Rule/Test/Unit/Model/Renderer/ActionsTest.php b/app/code/Magento/Rule/Test/Unit/Model/Renderer/ActionsTest.php deleted file mode 100644 index 279723ebd35e8..0000000000000 --- a/app/code/Magento/Rule/Test/Unit/Model/Renderer/ActionsTest.php +++ /dev/null @@ -1,67 +0,0 @@ -objectManagerHelper = new ObjectManagerHelper($this); - $this->actions = $this->objectManagerHelper->getObject(Actions::class); - $this->_element = $this->getMockBuilder(AbstractElement::class) - ->addMethods(['getRule']) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - } - - public function testRender() - { - $rule = $this->getMockBuilder(AbstractModel::class) - ->setMethods(['getActions', '__sleep', '__wakeup']) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - $actions = $this->createPartialMock(Collection::class, ['asHtmlRecursive']); - - $this->_element->expects($this->any()) - ->method('getRule') - ->willReturn($rule); - - $rule->expects($this->any()) - ->method('getActions') - ->willReturn($actions); - - $actions->expects($this->once()) - ->method('asHtmlRecursive') - ->willReturn('action html'); - - $this->assertEquals('action html', $this->actions->render($this->_element)); - } -} diff --git a/app/code/Magento/Rule/Test/Unit/Model/Renderer/ConditionsTest.php b/app/code/Magento/Rule/Test/Unit/Model/Renderer/ConditionsTest.php deleted file mode 100644 index 790c27cb11d59..0000000000000 --- a/app/code/Magento/Rule/Test/Unit/Model/Renderer/ConditionsTest.php +++ /dev/null @@ -1,67 +0,0 @@ -objectManagerHelper = new ObjectManagerHelper($this); - $this->conditions = $this->objectManagerHelper->getObject(Conditions::class); - $this->_element = $this->getMockBuilder(AbstractElement::class) - ->addMethods(['getRule']) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - } - - public function testRender() - { - $rule = $this->getMockBuilder(AbstractModel::class) - ->setMethods(['getConditions', '__sleep', '__wakeup']) - ->disableOriginalConstructor() - ->getMockForAbstractClass(); - $conditions = $this->createPartialMock(Combine::class, ['asHtmlRecursive']); - - $this->_element->expects($this->any()) - ->method('getRule') - ->willReturn($rule); - - $rule->expects($this->any()) - ->method('getConditions') - ->willReturn($conditions); - - $conditions->expects($this->once()) - ->method('asHtmlRecursive') - ->willReturn('conditions html'); - - $this->assertEquals('conditions html', $this->conditions->render($this->_element)); - } -} diff --git a/app/code/Magento/Rule/composer.json b/app/code/Magento/Rule/composer.json deleted file mode 100644 index a1b60b7e57eeb..0000000000000 --- a/app/code/Magento/Rule/composer.json +++ /dev/null @@ -1,29 +0,0 @@ -{ - "name": "magento/module-rule", - "description": "N/A", - "config": { - "sort-packages": true - }, - "require": { - "php": "~7.4.0||~8.1.0", - "lib-libxml": "*", - "magento/framework": "*", - "magento/module-backend": "*", - "magento/module-catalog": "*", - "magento/module-eav": "*", - "magento/module-store": "*" - }, - "type": "magento2-module", - "license": [ - "OSL-3.0", - "AFL-3.0" - ], - "autoload": { - "files": [ - "registration.php" - ], - "psr-4": { - "Magento\\Rule\\": "" - } - } -} diff --git a/app/code/Magento/Rule/etc/module.xml b/app/code/Magento/Rule/etc/module.xml deleted file mode 100644 index ee1bd4605c85e..0000000000000 --- a/app/code/Magento/Rule/etc/module.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - diff --git a/app/code/Magento/Rule/i18n/en_US.csv b/app/code/Magento/Rule/i18n/en_US.csv deleted file mode 100644 index d21b4cd956295..0000000000000 --- a/app/code/Magento/Rule/i18n/en_US.csv +++ /dev/null @@ -1,34 +0,0 @@ -Apply,Apply -"Please choose a valid discount amount.","Please choose a valid discount amount." -"End Date must follow Start Date.","End Date must follow Start Date." -"Please specify a website.","Please specify a website." -"Please specify Customer Groups.","Please specify Customer Groups." -to,to -by,by -"Please choose an action to add.","Please choose an action to add." -"Perform following actions","Perform following actions" -is,is -"is not","is not" -"equals or greater than","equals or greater than" -"equals or less than","equals or less than" -"greater than","greater than" -"less than","less than" -contains,contains -"does not contain","does not contain" -"is one of","is one of" -"is not one of","is not one of" -"Please choose a condition to add.","Please choose a condition to add." -Add,Add -Remove,Remove -ALL,ALL -ANY,ANY -TRUE,TRUE -FALSE,FALSE -"If %1 of these conditions are %2:","If %1 of these conditions are %2:" -"Conditions Combination","Conditions Combination" -"Attribute Set","Attribute Set" -Category,Category -"Open Chooser","Open Chooser" -"Unknown condition operator","Unknown condition operator" -"There is no information about associated entity type ""%1"".","There is no information about associated entity type ""%1""." -"This won't take long . . .","This won't take long . . ." diff --git a/app/code/Magento/Rule/registration.php b/app/code/Magento/Rule/registration.php deleted file mode 100644 index 21bce7ba05833..0000000000000 --- a/app/code/Magento/Rule/registration.php +++ /dev/null @@ -1,9 +0,0 @@ - 30) { - str = str.substr(0, 30) + '...'; - } - label.innerHTML = str.escapeHTML(); - } - } else { - elem = container.down('.element-value-changer'); - - if (elem.value) { - this.addRuleNewChild(elem); - } - elem.value = ''; - } - - if (elem && elem.id && elem.id.match(/__value$/)) { - this.hideChooser(container, event); - this.updateElement = null; - } - - this.shownElement = null; - }, - - changeVisibilityForValueRuleParam: function(elem) { - var parsedElementId = elem.id.split('__'); - if (parsedElementId[2] !== 'operator') { - return false; - } - - var valueElement = jQuery('#' + parsedElementId[0] + '__' + parsedElementId[1] + '__value'); - - if(elem.value === '<=>') { - valueElement.closest('.rule-param').hide(); - } else { - valueElement.closest('.rule-param').show(); - } - - return true; - }, - - addRuleNewChild: function (elem) { - var parent_id = elem.id.replace(/^.*__(.*)__.*$/, '$1'); - var children_ul_id = elem.id.replace(/__/g, ':').replace(/[^:]*$/, 'children').replace(/:/g, '__'); - var children_ul = $(this.parent).select('#' + children_ul_id)[0]; - var max_id = 0, - i; - var children_inputs = Selector.findChildElements(children_ul, $A(['input.hidden'])); - - if (children_inputs.length) { - children_inputs.each(function (el) { - if (el.id.match(/__type$/)) { - i = 1 * el.id.replace(/^.*__.*?([0-9]+)__.*$/, '$1'); - max_id = i > max_id ? i : max_id; - } - }); - } - var new_id = parent_id + '--' + (max_id + 1); - var new_type = elem.value; - var new_elem = document.createElement('LI'); - - new_elem.className = 'rule-param-wait'; - new_elem.innerHTML = jQuery.mage.__('This won\'t take long . . .'); - children_ul.insertBefore(new_elem, $(elem).up('li')); - - new Ajax.Request(this.newChildUrl, { - evalScripts: true, - parameters: { - form_key: FORM_KEY, type: new_type.replace('/', '-'), id: new_id - }, - onComplete: this.onAddNewChildComplete.bind(this, new_elem), - onSuccess: function (transport) { - if (this._processSuccess(transport)) { - $(new_elem).update(transport.responseText); - } - }.bind(this), - onFailure: this._processFailure.bind(this) - }); - }, - - _processSuccess: function (transport) { - if (transport.responseText.isJSON()) { - var response = transport.responseText.evalJSON(); - - if (response.error) { - alert(response.message); - } - - if (response.ajaxExpired && response.ajaxRedirect) { - setLocation(response.ajaxRedirect); - } - - return false; - } - - return true; - }, - - _processFailure: function (transport) { - location.href = BASE_URL; - }, - - onAddNewChildComplete: function (new_elem) { - if (this.readOnly) { - return false; - } - - $(new_elem).removeClassName('rule-param-wait'); - var elems = new_elem.getElementsByClassName('rule-param'); - - for (var i = 0; i < elems.length; i++) { - this.initParam(elems[i]); - } - }, - - removeRuleEntry: function (container, event) { - var li = Element.up(container, 'li'); - - li.parentNode.removeChild(li); - }, - - chooserGridInit: function (grid) { - //grid.reloadParams = {'selected[]':this.chooserSelectedItems.keys()}; - }, - - chooserGridRowInit: function (grid, row) { - if (!grid.reloadParams) { - grid.reloadParams = { - 'selected[]': this.chooserSelectedItems.keys() - }; - } - }, - - chooserGridRowClick: function (grid, event) { - var trElement = Event.findElement(event, 'tr'); - var isInput = Event.element(event).tagName == 'INPUT'; - - if (trElement) { - var checkbox = Element.select(trElement, 'input'); - - if (checkbox[0]) { - var checked = isInput ? checkbox[0].checked : !checkbox[0].checked; - - grid.setCheckboxChecked(checkbox[0], checked); - - } - } - }, - - chooserGridCheckboxCheck: function (grid, element, checked) { - if (checked) { - if (!element.up('th')) { - this.chooserSelectedItems.set(element.value, 1); - } - } else { - this.chooserSelectedItems.unset(element.value); - } - grid.reloadParams = { - 'selected[]': this.chooserSelectedItems.keys() - }; - this.updateElement.value = this.chooserSelectedItems.keys().join(', '); - } - }; - - return VarienRulesForm; -}); diff --git a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote.php b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote.php index 55e1d319cc776..7116779c4c917 100644 --- a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote.php +++ b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote.php @@ -5,7 +5,15 @@ */ namespace Magento\SalesRule\Controller\Adminhtml\Promo; -abstract class Quote extends \Magento\Backend\App\Action +use Magento\Backend\App\Action; +use Magento\Backend\App\Action\Context; +use Magento\Framework\App\Response\Http\FileFactory; +use Magento\Framework\Registry; +use Magento\Framework\Stdlib\DateTime\Filter\Date; +use Magento\SalesRule\Model\RegistryConstants; +use Magento\SalesRule\Model\Rule; + +abstract class Quote extends Action { /** * Authorization level of a basic admin session @@ -17,31 +25,31 @@ abstract class Quote extends \Magento\Backend\App\Action /** * Core registry * - * @var \Magento\Framework\Registry + * @var Registry */ protected $_coreRegistry = null; /** - * @var \Magento\Framework\App\Response\Http\FileFactory + * @var FileFactory */ protected $_fileFactory; /** - * @var \Magento\Framework\Stdlib\DateTime\Filter\Date + * @var Date */ protected $_dateFilter; /** - * @param \Magento\Backend\App\Action\Context $context - * @param \Magento\Framework\Registry $coreRegistry - * @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory - * @param \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter + * @param Context $context + * @param Registry $coreRegistry + * @param FileFactory $fileFactory + * @param Date $dateFilter */ public function __construct( - \Magento\Backend\App\Action\Context $context, - \Magento\Framework\Registry $coreRegistry, - \Magento\Framework\App\Response\Http\FileFactory $fileFactory, - \Magento\Framework\Stdlib\DateTime\Filter\Date $dateFilter + Context $context, + Registry $coreRegistry, + FileFactory $fileFactory, + Date $dateFilter ) { parent::__construct($context); $this->_coreRegistry = $coreRegistry; @@ -57,8 +65,8 @@ public function __construct( protected function _initRule() { $this->_coreRegistry->register( - \Magento\SalesRule\Model\RegistryConstants::CURRENT_SALES_RULE, - $this->_objectManager->create(\Magento\SalesRule\Model\Rule::class) + RegistryConstants::CURRENT_SALES_RULE, + $this->_objectManager->create(Rule::class) ); $id = (int)$this->getRequest()->getParam('id'); @@ -67,7 +75,7 @@ protected function _initRule() } if ($id) { - $this->_coreRegistry->registry(\Magento\SalesRule\Model\RegistryConstants::CURRENT_SALES_RULE)->load($id); + $this->_coreRegistry->registry(RegistryConstants::CURRENT_SALES_RULE)->load($id); } } diff --git a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/NewActionHtml.php b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/NewActionHtml.php index 47c9f41453b74..87c0c992283f8 100644 --- a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/NewActionHtml.php +++ b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/NewActionHtml.php @@ -3,18 +3,23 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + +declare(strict_types=1); namespace Magento\SalesRule\Controller\Adminhtml\Promo\Quote; -use Magento\Framework\App\Action\HttpPostActionInterface; -use Magento\Rule\Model\Condition\AbstractCondition; -use Magento\SalesRule\Controller\Adminhtml\Promo\Quote; use Magento\SalesRule\Model\Rule; +use Magento\Rule\Model\Condition\AbstractCondition; /** * New action html action */ -class NewActionHtml extends Quote implements HttpPostActionInterface +class NewActionHtml extends NewHtml { + /** + * @var string + */ + protected string $typeChecked = 'Magento\Rule\Model\Condition\AbstractCondition'; + /** * New action html action * @@ -30,31 +35,24 @@ public function execute() ); $type = $typeArr[0]; - $model = $this->_objectManager->create( - $type - )->setId( - $id - )->setType( - $type - )->setRule( - $this->_objectManager->create(Rule::class) - )->setPrefix( - 'actions' - ); - if (!empty($typeArr[1])) { - $model->setAttribute($typeArr[1]); - } + $model = $this->_objectManager->create($type); + if ($this->verifyClassName($model)) { + $model->setId($id) + ->setType($type) + ->setRule($this->_objectManager->create(Rule::class)) + ->setPrefix('actions'); + if (!empty($typeArr[1])) { + $model->setAttribute($typeArr[1]); + } - if ($model instanceof AbstractCondition) { $model->setJsFormObject($formName); $model->setFormName($formName); $this->setJsFormObject($model); $html = $model->asHtmlRecursive(); } else { - $html = ''; + $html = $this->getErrorJson(); } - $this->getResponse() - ->setBody($html); + $this->getResponse()->setBody($html); } /** diff --git a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/NewConditionHtml.php b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/NewConditionHtml.php index 959e3cf192f6d..97429df722e65 100644 --- a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/NewConditionHtml.php +++ b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/NewConditionHtml.php @@ -3,17 +3,24 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + +declare(strict_types=1); + namespace Magento\SalesRule\Controller\Adminhtml\Promo\Quote; -use Magento\Framework\App\Action\HttpPostActionInterface; +use Magento\SalesRule\Model\Rule; use Magento\Rule\Model\Condition\AbstractCondition; -use Magento\SalesRule\Controller\Adminhtml\Promo\Quote; /** * Controller class NewConditionHtml. Returns condition html */ -class NewConditionHtml extends Quote implements HttpPostActionInterface +class NewConditionHtml extends NewHtml { + /** + * @var string + */ + protected string $typeChecked = 'Magento\Rule\Model\Condition\AbstractCondition'; + /** * New condition html action * @@ -29,29 +36,24 @@ public function execute() ); $type = $typeArr[0]; - $model = $this->_objectManager->create( - $type - )->setId( - $id - )->setType( - $type - )->setRule( - $this->_objectManager->create(\Magento\SalesRule\Model\Rule::class) - )->setPrefix( - 'conditions' - ); - if (!empty($typeArr[1])) { - $model->setAttribute($typeArr[1]); - } + $model = $this->_objectManager->create($type); + if ($this->verifyClassName($model)) { + $model->setId($id) + ->setType($type) + ->setRule($this->_objectManager->create(Rule::class)) + ->setPrefix('conditions'); + if (!empty($typeArr[1])) { + $model->setAttribute($typeArr[1]); + } - if ($model instanceof AbstractCondition) { $model->setJsFormObject($this->getRequest()->getParam('form')); $model->setFormName($formName); $this->setJsFormObject($model); $html = $model->asHtmlRecursive(); - } else { - $html = ''; + }else { + $html = $this->getErrorJson(); } + $this->getResponse()->setBody($html); } diff --git a/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/NewHtml.php b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/NewHtml.php new file mode 100644 index 0000000000000..6f695af8c495d --- /dev/null +++ b/app/code/Magento/SalesRule/Controller/Adminhtml/Promo/Quote/NewHtml.php @@ -0,0 +1,79 @@ +serializer = $serializer; + } + + /** + * Verify class instance + * + * @param mixed $verifyClass + * @return bool + */ + public function verifyClassName($verifyClass): bool + { + if ($verifyClass instanceof $this->typeChecked) { + return true; + } + + return false; + } + + /** + * Get Error json + * + * @return bool|string + */ + protected function getErrorJson() + { + return $this->serializer->serialize( + [ + 'error' => true, + 'message' => __('Selected type is not inherited from type %1', $this->typeChecked) + ] + ); + } +} \ No newline at end of file