diff --git a/app/code/Magento/Bundle/Api/Data/LinkInterface.php b/app/code/Magento/Bundle/Api/Data/LinkInterface.php index 4e2268eae8f9a..694e6227ef25d 100644 --- a/app/code/Magento/Bundle/Api/Data/LinkInterface.php +++ b/app/code/Magento/Bundle/Api/Data/LinkInterface.php @@ -7,6 +7,10 @@ namespace Magento\Bundle\Api\Data; +/** + * Interface LinkInterface + * @api + */ interface LinkInterface extends \Magento\Framework\Api\ExtensibleDataInterface { const PRICE_TYPE_FIXED = 0; diff --git a/app/code/Magento/Bundle/Api/Data/OptionInterface.php b/app/code/Magento/Bundle/Api/Data/OptionInterface.php index 47d52ba713c64..52de4e8d65cf7 100644 --- a/app/code/Magento/Bundle/Api/Data/OptionInterface.php +++ b/app/code/Magento/Bundle/Api/Data/OptionInterface.php @@ -7,6 +7,10 @@ namespace Magento\Bundle\Api\Data; +/** + * Interface OptionInterface + * @api + */ interface OptionInterface extends \Magento\Framework\Api\ExtensibleDataInterface { /** diff --git a/app/code/Magento/Bundle/Api/Data/OptionTypeInterface.php b/app/code/Magento/Bundle/Api/Data/OptionTypeInterface.php index 9883c8535da83..b86735497f4bf 100644 --- a/app/code/Magento/Bundle/Api/Data/OptionTypeInterface.php +++ b/app/code/Magento/Bundle/Api/Data/OptionTypeInterface.php @@ -6,6 +6,10 @@ */ namespace Magento\Bundle\Api\Data; +/** + * Interface OptionTypeInterface + * @api + */ interface OptionTypeInterface extends \Magento\Framework\Api\ExtensibleDataInterface { /** diff --git a/app/code/Magento/Bundle/Api/ProductLinkManagementInterface.php b/app/code/Magento/Bundle/Api/ProductLinkManagementInterface.php index 0529831f4094f..309084b8137bc 100644 --- a/app/code/Magento/Bundle/Api/ProductLinkManagementInterface.php +++ b/app/code/Magento/Bundle/Api/ProductLinkManagementInterface.php @@ -6,6 +6,10 @@ */ namespace Magento\Bundle\Api; +/** + * Interface for Management of ProductLink + * @api + */ interface ProductLinkManagementInterface { /** diff --git a/app/code/Magento/Bundle/Api/ProductOptionRepositoryInterface.php b/app/code/Magento/Bundle/Api/ProductOptionRepositoryInterface.php index 26857e69449cd..b0b8375650150 100644 --- a/app/code/Magento/Bundle/Api/ProductOptionRepositoryInterface.php +++ b/app/code/Magento/Bundle/Api/ProductOptionRepositoryInterface.php @@ -6,6 +6,10 @@ */ namespace Magento\Bundle\Api; +/** + * Interface ProductOptionRepositoryInterface + * @api + */ interface ProductOptionRepositoryInterface { /** diff --git a/app/code/Magento/Bundle/Api/ProductOptionTypeListInterface.php b/app/code/Magento/Bundle/Api/ProductOptionTypeListInterface.php index 6df2f3341b6fb..998293c9b937b 100644 --- a/app/code/Magento/Bundle/Api/ProductOptionTypeListInterface.php +++ b/app/code/Magento/Bundle/Api/ProductOptionTypeListInterface.php @@ -6,6 +6,10 @@ */ namespace Magento\Bundle\Api; +/** + * Interface ProductOptionTypeListInterface + * @api + */ interface ProductOptionTypeListInterface { /** diff --git a/app/code/Magento/Bundle/Block/Adminhtml/Catalog/Product/Edit/Tab/Attributes/Extend.php b/app/code/Magento/Bundle/Block/Adminhtml/Catalog/Product/Edit/Tab/Attributes/Extend.php index ecf2459e85fc6..ed3f39d7ce77e 100644 --- a/app/code/Magento/Bundle/Block/Adminhtml/Catalog/Product/Edit/Tab/Attributes/Extend.php +++ b/app/code/Magento/Bundle/Block/Adminhtml/Catalog/Product/Edit/Tab/Attributes/Extend.php @@ -110,9 +110,12 @@ public function getOptions() */ public function isDisabledField() { - return $this->getProduct()->getId() && - $this->getAttribute()->getAttributeCode() === 'price' || - $this->getElement()->getReadonly(); + return $this->_getData('is_disabled_field') + || ($this->getProduct()->getId() + && $this->getAttribute()->getAttributeCode() === 'price' + ) + || $this->getElement()->getReadonly(); + } /** @@ -142,7 +145,9 @@ public function getExtendedElement($switchAttributeCode) 'values' => $this->getOptions(), 'value' => $switchAttributeCode, 'class' => 'required-entry next-toinput', - 'disabled' => $this->isDisabledField() + 'no_span' => true, + 'disabled' => $this->isDisabledField(), + 'value' => $this->getProduct()->getData($switchAttributeCode), ] ); } diff --git a/app/code/Magento/Bundle/Pricing/Price/BundleOptionPriceInterface.php b/app/code/Magento/Bundle/Pricing/Price/BundleOptionPriceInterface.php index 8239ee0aad8b1..c33b171db6b98 100644 --- a/app/code/Magento/Bundle/Pricing/Price/BundleOptionPriceInterface.php +++ b/app/code/Magento/Bundle/Pricing/Price/BundleOptionPriceInterface.php @@ -7,6 +7,7 @@ /** * Option price interface + * @api */ interface BundleOptionPriceInterface { diff --git a/app/code/Magento/Bundle/Pricing/Price/DiscountProviderInterface.php b/app/code/Magento/Bundle/Pricing/Price/DiscountProviderInterface.php index 1df557f3a81dc..f17f06e31532a 100644 --- a/app/code/Magento/Bundle/Pricing/Price/DiscountProviderInterface.php +++ b/app/code/Magento/Bundle/Pricing/Price/DiscountProviderInterface.php @@ -8,6 +8,7 @@ /** * Interface DiscountProviderInterface + * @api */ interface DiscountProviderInterface { diff --git a/app/code/Magento/Bundle/Pricing/Price/FinalPriceInterface.php b/app/code/Magento/Bundle/Pricing/Price/FinalPriceInterface.php index a593809e3da3d..6788132201593 100644 --- a/app/code/Magento/Bundle/Pricing/Price/FinalPriceInterface.php +++ b/app/code/Magento/Bundle/Pricing/Price/FinalPriceInterface.php @@ -8,6 +8,7 @@ /** * Interface FinalPriceInterface + * @api */ interface FinalPriceInterface extends \Magento\Catalog\Pricing\Price\FinalPriceInterface { diff --git a/app/code/Magento/Bundle/Pricing/Price/RegularPriceInterface.php b/app/code/Magento/Bundle/Pricing/Price/RegularPriceInterface.php index 836144879741e..052f2f4c7ceac 100644 --- a/app/code/Magento/Bundle/Pricing/Price/RegularPriceInterface.php +++ b/app/code/Magento/Bundle/Pricing/Price/RegularPriceInterface.php @@ -8,6 +8,7 @@ /** * Regular price interface + * @api */ interface RegularPriceInterface extends \Magento\Framework\Pricing\Price\BasePriceProviderInterface { diff --git a/app/code/Magento/Bundle/Test/Unit/Block/Adminhtml/Catalog/Product/Edit/Tab/Attributes/ExtendTest.php b/app/code/Magento/Bundle/Test/Unit/Block/Adminhtml/Catalog/Product/Edit/Tab/Attributes/ExtendTest.php new file mode 100644 index 0000000000000..03a3963184b20 --- /dev/null +++ b/app/code/Magento/Bundle/Test/Unit/Block/Adminhtml/Catalog/Product/Edit/Tab/Attributes/ExtendTest.php @@ -0,0 +1,76 @@ +registry = $this->getMockBuilder('Magento\\Framework\\Registry')->disableOriginalConstructor()->getMock( + ); + $this->formFactory = $this->getMockBuilder('Magento\\Framework\\Data\\FormFactory')->disableOriginalConstructor( + )->getMock(); + $this->objectManagerHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->object = $this->objectManagerHelper->getObject( + 'Magento\\Bundle\\Block\\Adminhtml\\Catalog\\Product\\Edit\\Tab\\Attributes\\Extend', + ['registry' => $this->registry, 'formFactory' => $this->formFactory] + ); + } + + /** + * @return \PHPUnit_Framework_MockObject_MockObject + */ + public function getProduct() + { + $product = $this->getMockBuilder(Product::class)->disableOriginalConstructor()->getMock(); + $this->registry->expects($this->once()) + ->method('registry') + ->with('product') + ->will( + $this->returnValue($product) + ); + return $product; + } + + public function testGetExtendedElement() + { + $switchAttributeCode = 'test_code'; + $form = $this->getMockBuilder(\Magento\Framework\Data\Form::class)->disableOriginalConstructor()->getMock(); + $and = new \PHPUnit_Framework_Constraint_And(); + $and->setConstraints( + [ + new \PHPUnit_Framework_Constraint_ArrayHasKey('value') + ] + ); + $form->expects($this->once())->method('addField')->with( + $switchAttributeCode, + 'select', + $and + ); + + $this->formFactory->expects($this->once())->method('create')->with()->will($this->returnValue($form)); + $product = $this->getProduct(); + $product->expects($this->once())->method('getData')->with($switchAttributeCode)->will( + $this->returnValue(123) + ); + $this->object->setIsDisabledField(true); + $this->object->getExtendedElement($switchAttributeCode); + } +} diff --git a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php index 168fa5363ab0a..ae190c3b07266 100644 --- a/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php +++ b/app/code/Magento/Bundle/Test/Unit/Model/Product/TypeTest.php @@ -16,6 +16,14 @@ */ class TypeTest extends \PHPUnit_Framework_TestCase { + /** + * @var \Magento\Bundle\Model\Resource\BundleFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $bundleFactory; + /** + * @var \Magento\Bundle\Model\SelectionFactory|\PHPUnit_Framework_MockObject_MockObject + */ + private $bundleModelSelection; /** * @var \Magento\Bundle\Model\Product\Type */ @@ -96,19 +104,18 @@ protected function setUp() ->setMethods(['convert']) ->disableOriginalConstructor() ->getMockForAbstractClass(); - $bundleModelSelection = $this->getMockBuilder('\Magento\Bundle\Model\SelectionFactory') + $this->bundleModelSelection = $this->getMockBuilder('Magento\Bundle\Model\SelectionFactory') ->disableOriginalConstructor() ->getMock(); - $bundleFactory = $this->getMockBuilder('\Magento\Bundle\Model\Resource\BundleFactory') + $this->bundleFactory = $this->getMockBuilder('\Magento\Bundle\Model\Resource\BundleFactory') ->disableOriginalConstructor() ->getMock(); - $objectHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->model = $objectHelper->getObject( 'Magento\Bundle\Model\Product\Type', [ - 'bundleModelSelection' => $bundleModelSelection, - 'bundleFactory' => $bundleFactory, + 'bundleModelSelection' => $this->bundleModelSelection, + 'bundleFactory' => $this->bundleFactory, 'bundleCollection' => $this->bundleCollection, 'bundleOption' => $this->bundleOptionFactory, 'catalogData' => $this->catalogData, @@ -2427,4 +2434,72 @@ protected function parentClass($group, $option, $buyRequest, $product) ->method('getSkipSaleableCheck') ->willReturn(false); } + + public function testSave() + { + $options = [ + 'some_option' => ['option_id' => '', 'delete' => false], + ]; + $selections = [ + 'some_option' => [ + 123 => ['selection_id' => '', 'delete' => false], + ] + ]; + + $resource = $this->getMockBuilder('Magento\Bundle\Model\Resource\Bundle') + ->disableOriginalConstructor() + ->getMock(); + $this->bundleFactory->expects($this->once()) + ->method('create') + ->willReturn($resource); + + $product = $this->getMockBuilder('Magento\Catalog\Model\Product') + ->setMethods( + [ + 'getStoreId', + 'getOrigData', + 'getData', + 'getBundleOptionsData', + 'getBundleSelectionsData' + ] + ) + ->disableOriginalConstructor() + ->getMock(); + $product->expects($this->once()) + ->method('getBundleOptionsData') + ->willReturn($options); + $product->expects($this->once()) + ->method('getBundleSelectionsData') + ->willReturn($selections); + $option = $this->getMockBuilder('Magento\Bundle\Model\Resource\Option\Collection') + ->setMethods(['setData', 'setParentId', 'setStoreId', 'isDeleted', 'save', 'getOptionId']) + ->disableOriginalConstructor() + ->getMock(); + $option->expects($this->once())->method('setData')->willReturnSelf(); + $option->expects($this->once())->method('setParentId')->willReturnSelf(); + $option->expects($this->once())->method('setStoreId')->willReturnSelf(); + $this->bundleOptionFactory->expects($this->once())->method('create')->will($this->returnValue($option)); + + $selection = $this->getMockBuilder('Magento\Bundle\Model\Selection') + ->setMethods(['setData', 'setOptionId', 'setParentProductId', 'setWebsiteId', 'save']) + ->disableOriginalConstructor() + ->getMock(); + $selection->expects($this->once())->method('setData')->willReturnSelf(); + $selection->expects($this->once())->method('setOptionId')->willReturnSelf(); + $selection->expects($this->once())->method('setParentProductId')->willReturnSelf(); + $selection->expects($this->once())->method('setWebsiteId')->willReturnSelf(); + $selection->expects($this->once())->method('setParentProductId')->willReturnSelf(); + $this->bundleModelSelection->expects($this->once())->method('create')->willReturn($selection); + $store = $this->getMockBuilder('Magento\Store\Model\Store') + ->setMethods(['getWebsiteId', '__wakeup']) + ->disableOriginalConstructor() + ->getMock(); + $this->storeManager->expects($this->once()) + ->method('getStore') + ->will($this->returnValue($store)); + $store->expects($this->once()) + ->method('getWebsiteId') + ->will($this->returnValue(10)); + $this->model->save($product); + } } diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Front.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Front.php index 1f146dcbe254a..837e2ac4f8107 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Front.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Front.php @@ -11,10 +11,14 @@ */ namespace Magento\Catalog\Block\Adminhtml\Product\Attribute\Edit\Tab; +use Magento\Backend\Block\Template\Context; use Magento\Backend\Block\Widget\Form; use Magento\Backend\Block\Widget\Form\Generic; use Magento\Config\Model\Config\Source\Yesno; use Magento\Catalog\Model\Entity\Attribute; +use Magento\Eav\Block\Adminhtml\Attribute\PropertyLocker; +use Magento\Framework\Data\FormFactory; +use Magento\Framework\Registry; class Front extends Generic { @@ -24,28 +28,28 @@ class Front extends Generic protected $_yesNo; /** - * @var array + * @var PropertyLocker */ - private $disableSearchable; + private $propertyLocker; /** - * @param \Magento\Backend\Block\Template\Context $context - * @param \Magento\Framework\Registry $registry - * @param \Magento\Framework\Data\FormFactory $formFactory + * @param Context $context + * @param Registry $registry + * @param FormFactory $formFactory * @param Yesno $yesNo + * @param PropertyLocker $propertyLocker * @param array $data - * @param array $disableSearchable */ public function __construct( - \Magento\Backend\Block\Template\Context $context, - \Magento\Framework\Registry $registry, - \Magento\Framework\Data\FormFactory $formFactory, + Context $context, + Registry $registry, + FormFactory $formFactory, Yesno $yesNo, - array $data = [], - array $disableSearchable = [] + PropertyLocker $propertyLocker, + array $data = [] ) { $this->_yesNo = $yesNo; - $this->disableSearchable = $disableSearchable; + $this->propertyLocker = $propertyLocker; parent::__construct($context, $registry, $formFactory, $data); } @@ -71,7 +75,6 @@ protected function _prepareForm() ['legend' => __('Frontend Properties'), 'collapsable' => $this->getRequest()->has('popup')] ); - $attrCode = $attributeObject->getAttributeCode(); $fieldset->addField( 'is_searchable', 'select', @@ -80,7 +83,6 @@ protected function _prepareForm() 'label' => __('Use in Search'), 'title' => __('Use in Search'), 'values' => $yesnoSource, - 'disabled' => isset($this->disableSearchable[$attrCode]) && $this->disableSearchable[$attrCode] ? 1 : 0 ] ); @@ -223,6 +225,7 @@ protected function _prepareForm() ); $form->setValues($attributeObject->getData()); + $this->propertyLocker->lock($form); $this->setForm($form); return parent::_prepareForm(); } diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Main.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Main.php index 35155d15e785a..343e9f60273c2 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Main.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/Main.php @@ -61,7 +61,6 @@ protected function _prepareForm() $response = new \Magento\Framework\Object(); $response->setTypes([]); $this->_eventManager->dispatch('adminhtml_product_attribute_types', ['response' => $response]); - $_disabledTypes = []; $_hiddenFields = []; foreach ($response->getTypes() as $type) { $additionalTypes[] = $type; diff --git a/app/code/Magento/Catalog/Model/Product/Attribute/Source/Inputtype.php b/app/code/Magento/Catalog/Model/Product/Attribute/Source/Inputtype.php index 769a2aeb5a832..7573262af0520 100644 --- a/app/code/Magento/Catalog/Model/Product/Attribute/Source/Inputtype.php +++ b/app/code/Magento/Catalog/Model/Product/Attribute/Source/Inputtype.php @@ -53,7 +53,6 @@ public function toOptionArray() $response = new \Magento\Framework\Object(); $response->setTypes([]); $this->_eventManager->dispatch('adminhtml_product_attribute_types', ['response' => $response]); - $_disabledTypes = []; $_hiddenFields = []; foreach ($response->getTypes() as $type) { $inputTypes[] = $type; diff --git a/app/code/Magento/Catalog/etc/adminhtml/di.xml b/app/code/Magento/Catalog/etc/adminhtml/di.xml index 31e2f1092287e..29aadc03ae11e 100644 --- a/app/code/Magento/Catalog/etc/adminhtml/di.xml +++ b/app/code/Magento/Catalog/etc/adminhtml/di.xml @@ -66,18 +66,4 @@ - - - - true - true - true - true - true - true - true - true - - - diff --git a/app/code/Magento/Catalog/etc/eav_attributes.xml b/app/code/Magento/Catalog/etc/eav_attributes.xml index a7972b6b53113..3ba4dfae9d8b0 100644 --- a/app/code/Magento/Catalog/etc/eav_attributes.xml +++ b/app/code/Magento/Catalog/etc/eav_attributes.xml @@ -12,12 +12,31 @@ + + + + + + + + + + + + + + + + + + + diff --git a/app/code/Magento/CatalogSearch/Model/Resource/Engine.php b/app/code/Magento/CatalogSearch/Model/Resource/Engine.php index 8a6d49963700a..15b56ec7b331e 100644 --- a/app/code/Magento/CatalogSearch/Model/Resource/Engine.php +++ b/app/code/Magento/CatalogSearch/Model/Resource/Engine.php @@ -37,13 +37,6 @@ class Engine extends AbstractDb implements EngineInterface */ protected $_catalogSearchData = null; - /** - * Catalog search data - * - * @var \Magento\Search\Model\Resource\Helper - */ - protected $_resourceHelper; - /** * Construct * @@ -51,7 +44,6 @@ class Engine extends AbstractDb implements EngineInterface * @param \Magento\Catalog\Model\Product\Visibility $catalogProductVisibility * @param Advanced $searchResource * @param \Magento\CatalogSearch\Helper\Data $catalogSearchData - * @param \Magento\Search\Model\Resource\Helper $resourceHelper * @param string|null $resourcePrefix */ public function __construct( @@ -59,13 +51,11 @@ public function __construct( \Magento\Catalog\Model\Product\Visibility $catalogProductVisibility, \Magento\CatalogSearch\Model\Resource\Advanced $searchResource, \Magento\CatalogSearch\Helper\Data $catalogSearchData, - \Magento\Search\Model\Resource\Helper $resourceHelper, $resourcePrefix = null ) { $this->_catalogProductVisibility = $catalogProductVisibility; $this->_searchResource = $searchResource; $this->_catalogSearchData = $catalogSearchData; - $this->_resourceHelper = $resourceHelper; parent::__construct($context, $resourcePrefix); } @@ -118,7 +108,7 @@ public function saveEntityIndexes($storeId, $entityIndexes, $entity = 'product') } if ($data) { - $this->_resourceHelper->insertOnDuplicate($this->getMainTable(), $data, ['data_index']); + $this->_getWriteAdapter()->insertOnDuplicate($this->getMainTable(), $data, ['data_index']); } return $this; diff --git a/app/code/Magento/CatalogSearch/Model/Resource/Fulltext.php b/app/code/Magento/CatalogSearch/Model/Resource/Fulltext.php index 5997b47553eb1..8d2870e9b832d 100644 --- a/app/code/Magento/CatalogSearch/Model/Resource/Fulltext.php +++ b/app/code/Magento/CatalogSearch/Model/Resource/Fulltext.php @@ -5,20 +5,11 @@ */ namespace Magento\CatalogSearch\Model\Resource; -use Magento\Search\Model\Resource\Helper; - /** * CatalogSearch Fulltext Index resource model */ class Fulltext extends \Magento\Framework\Model\Resource\Db\AbstractDb { - /** - * Core string - * - * @var \Magento\Framework\Filter\FilterManager - */ - protected $filter; - /** * Core event manager proxy * @@ -26,30 +17,17 @@ class Fulltext extends \Magento\Framework\Model\Resource\Db\AbstractDb */ protected $_eventManager; - /** - * CatalogSearch resource helper - * - * @var \Magento\Search\Model\Resource\Helper - */ - protected $_resourceHelper; - /** * @param \Magento\Framework\Model\Resource\Db\Context $context * @param \Magento\Framework\Event\ManagerInterface $eventManager - * @param \Magento\Framework\Filter\FilterManager $filter - * @param Helper $resourceHelper * @param string|null $resourcePrefix */ public function __construct( \Magento\Framework\Model\Resource\Db\Context $context, \Magento\Framework\Event\ManagerInterface $eventManager, - \Magento\Framework\Filter\FilterManager $filter, - \Magento\Search\Model\Resource\Helper $resourceHelper, $resourcePrefix = null ) { $this->_eventManager = $eventManager; - $this->filter = $filter; - $this->_resourceHelper = $resourceHelper; parent::__construct($context, $resourcePrefix); } @@ -71,7 +49,7 @@ protected function _construct() public function resetSearchResults() { $adapter = $this->_getWriteAdapter(); - $adapter->update($this->getTable('search_query'), ['is_processed' => 0]); + $adapter->update($this->getTable('search_query'), ['is_processed' => 0], ['is_processed != 0']); $this->_eventManager->dispatch('catalogsearch_reset_search_result'); return $this; } diff --git a/app/code/Magento/CatalogSearch/Test/Unit/Model/Resource/FulltextTest.php b/app/code/Magento/CatalogSearch/Test/Unit/Model/Resource/FulltextTest.php new file mode 100644 index 0000000000000..f6e16d3332e7b --- /dev/null +++ b/app/code/Magento/CatalogSearch/Test/Unit/Model/Resource/FulltextTest.php @@ -0,0 +1,76 @@ +context = $this->getMockBuilder('\Magento\Framework\Model\Resource\Db\Context') + ->disableOriginalConstructor() + ->getMock(); + $this->resource = $this->getMockBuilder('\Magento\Framework\App\Resource') + ->disableOriginalConstructor() + ->getMock(); + $this->context->expects($this->once()) + ->method('getResources') + ->willReturn($this->resource); + $this->adapter = $this->getMockBuilder('\Magento\Framework\DB\Adapter\AdapterInterface') + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $this->resource->expects($this->once()) + ->method('getConnection') + ->with('core_write') + ->willReturn($this->adapter); + + $objectManager = new ObjectManager($this); + $this->target = $objectManager->getObject( + '\Magento\CatalogSearch\Model\Resource\Fulltext', + [ + 'context' => $this->context, + ] + ); + } + + public function testResetSearchResult() + { + $this->resource->expects($this->once()) + ->method('getTableName') + ->with('search_query', 'core_read') + ->willReturn('table_name_search_query'); + $this->adapter->expects($this->once()) + ->method('update') + ->with('table_name_search_query', ['is_processed' => 0], ['is_processed != 0']) + ->willReturn(10); + $result = $this->target->resetSearchResults(); + $this->assertEquals($this->target, $result); + } +} diff --git a/app/code/Magento/CatalogUrlRewrite/etc/eav_attributes.xml b/app/code/Magento/CatalogUrlRewrite/etc/eav_attributes.xml index 65818ad4546d1..076ffe0382866 100644 --- a/app/code/Magento/CatalogUrlRewrite/etc/eav_attributes.xml +++ b/app/code/Magento/CatalogUrlRewrite/etc/eav_attributes.xml @@ -9,6 +9,7 @@ + diff --git a/app/code/Magento/ConfigurableProduct/Api/ConfigurableProductManagementInterface.php b/app/code/Magento/ConfigurableProduct/Api/ConfigurableProductManagementInterface.php index 3588a1ca6a708..66e05cf340d40 100644 --- a/app/code/Magento/ConfigurableProduct/Api/ConfigurableProductManagementInterface.php +++ b/app/code/Magento/ConfigurableProduct/Api/ConfigurableProductManagementInterface.php @@ -6,6 +6,10 @@ */ namespace Magento\ConfigurableProduct\Api; +/** + * Interface ConfigurableProductManagementInterface + * @api + */ interface ConfigurableProductManagementInterface { /** diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/OptionRepositoryTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/OptionRepositoryTest.php index 34b66ecb320dc..5bf9e0b3106d3 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/OptionRepositoryTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/OptionRepositoryTest.php @@ -207,4 +207,57 @@ public function testGetListNotConfigurableProduct() $this->model->getList($productSku); } + + /** + * @param int $attributeId + * @param string $label + * @param array $optionValues + * @param string $msg + * @dataProvider validateOptionDataProvider + * @throws \Magento\Framework\Exception\InputException + */ + public function testValidateNewOptionData($attributeId, $label, $optionValues, $msg) + { + $this->setExpectedException('Magento\Framework\Exception\InputException', $msg); + $optionValueMock = $this->getMock('\Magento\ConfigurableProduct\Api\Data\OptionValueInterface'); + $optionValuesMock = []; + if (!empty($optionValues)) { + $optionValueMock->expects($this->any()) + ->method('getValueIndex') + ->willReturn($optionValues['v']); + $optionValueMock->expects($this->any()) + ->method('getPricingValue') + ->willReturn($optionValues['p']); + $optionValueMock->expects($this->any()) + ->method('getIsPercent') + ->willReturn($optionValues['r']); + $optionValuesMock = [$optionValueMock]; + } + + $optionMock = $this->getMock('\Magento\ConfigurableProduct\Api\Data\OptionInterface'); + $optionMock->expects($this->any()) + ->method('getAttributeId') + ->willReturn($attributeId); + $optionMock->expects($this->any()) + ->method('getLabel') + ->willReturn($label); + $optionMock->expects($this->any()) + ->method('getValues') + ->willReturn($optionValuesMock); + + $this->model->validateNewOptionData($optionMock); + } + + public function validateOptionDataProvider() + { + return [ + [null, '', ['v' => null, 'p' => null, 'r' => null], 'One or more input exceptions have occurred.'], + [1, 'Label', [], 'Option values are not specified.'], + [null, 'Label', ['v' => 1, 'p' => 1, 'r' => 1], 'Option attribute ID is not specified.'], + [1, '', ['v' => 1, 'p' => 1, 'r' => 1], 'Option label is not specified.'], + [1, 'Label', ['v' => null, 'p' => 1, 'r' => 1], 'Value index is not specified for an option.'], + [1, 'Label', ['v' => 1, 'p' => null, 'r' => 1], 'Price is not specified for an option.'], + [1, 'Label', ['v' => 1, 'p' => 1, 'r' => null], 'Percent/absolute is not specified for an option.'], + ]; + } } diff --git a/app/code/Magento/Downloadable/Api/LinkRepositoryInterface.php b/app/code/Magento/Downloadable/Api/LinkRepositoryInterface.php index 3a0d8053e4f8d..12b8458cecaec 100644 --- a/app/code/Magento/Downloadable/Api/LinkRepositoryInterface.php +++ b/app/code/Magento/Downloadable/Api/LinkRepositoryInterface.php @@ -7,31 +7,19 @@ use Magento\Downloadable\Api\Data\LinkInterface; +/** + * Interface LinkRepositoryInterface + * @package Magento\Downloadable\Api + */ interface LinkRepositoryInterface { - /** - * List of samples for downloadable product - * - * @param string $sku - * @return \Magento\Downloadable\Api\Data\SampleInterface[] - */ - public function getSamples($sku); - - /** - * List of samples for downloadable product - * - * @param \Magento\Catalog\Api\Data\ProductInterface $product - * @return \Magento\Downloadable\Api\Data\SampleInterface[] - */ - public function getSamplesByProduct(\Magento\Catalog\Api\Data\ProductInterface $product); - /** * List of links with associated samples * * @param string $sku * @return \Magento\Downloadable\Api\Data\LinkInterface[] */ - public function getLinks($sku); + public function getList($sku); /** * List of links with associated samples diff --git a/app/code/Magento/Downloadable/Api/SampleRepositoryInterface.php b/app/code/Magento/Downloadable/Api/SampleRepositoryInterface.php index 9a52cea8819f4..8aa184795bb3f 100644 --- a/app/code/Magento/Downloadable/Api/SampleRepositoryInterface.php +++ b/app/code/Magento/Downloadable/Api/SampleRepositoryInterface.php @@ -7,8 +7,28 @@ use Magento\Downloadable\Api\Data\SampleInterface; +/** + * Interface SampleRepositoryInterface + * @api + */ interface SampleRepositoryInterface { + /** + * List of samples for downloadable product + * + * @param string $sku + * @return \Magento\Downloadable\Api\Data\SampleInterface[] + */ + public function getList($sku); + + /** + * List of links with associated samples + * + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @return \Magento\Downloadable\Api\Data\SampleInterface[] + */ + public function getSamplesByProduct(\Magento\Catalog\Api\Data\ProductInterface $product); + /** * Update downloadable sample of the given product * diff --git a/app/code/Magento/Downloadable/Model/LinkRepository.php b/app/code/Magento/Downloadable/Model/LinkRepository.php index bca06682ba718..6f047f4b0a837 100644 --- a/app/code/Magento/Downloadable/Model/LinkRepository.php +++ b/app/code/Magento/Downloadable/Model/LinkRepository.php @@ -22,21 +22,11 @@ class LinkRepository implements \Magento\Downloadable\Api\LinkRepositoryInterfac */ protected $productRepository; - /** - * @var \Magento\Downloadable\Model\Product\Type - */ - protected $downloadableType; - /** * @var \Magento\Downloadable\Api\Data\LinkInterfaceFactory */ protected $linkDataObjectFactory; - /** - * @var \Magento\Downloadable\Api\Data\SampleInterfaceFactory - */ - protected $sampleDataObjectFactory; - /** * @var \Magento\Downloadable\Model\LinkFactory */ @@ -61,7 +51,6 @@ class LinkRepository implements \Magento\Downloadable\Api\LinkRepositoryInterfac * @param \Magento\Catalog\Api\ProductRepositoryInterface $productRepository * @param \Magento\Downloadable\Model\Product\Type $downloadableType * @param \Magento\Downloadable\Api\Data\LinkInterfaceFactory $linkDataObjectFactory - * @param \Magento\Downloadable\Api\Data\SampleInterfaceFactory $sampleDataObjectFactory * @param LinkFactory $linkFactory * @param Link\ContentValidator $contentValidator * @param EncoderInterface $jsonEncoder @@ -71,7 +60,6 @@ public function __construct( \Magento\Catalog\Api\ProductRepositoryInterface $productRepository, \Magento\Downloadable\Model\Product\Type $downloadableType, \Magento\Downloadable\Api\Data\LinkInterfaceFactory $linkDataObjectFactory, - \Magento\Downloadable\Api\Data\SampleInterfaceFactory $sampleDataObjectFactory, LinkFactory $linkFactory, Link\ContentValidator $contentValidator, EncoderInterface $jsonEncoder, @@ -80,7 +68,6 @@ public function __construct( $this->productRepository = $productRepository; $this->downloadableType = $downloadableType; $this->linkDataObjectFactory = $linkDataObjectFactory; - $this->sampleDataObjectFactory = $sampleDataObjectFactory; $this->linkFactory = $linkFactory; $this->contentValidator = $contentValidator; $this->jsonEncoder = $jsonEncoder; @@ -90,7 +77,7 @@ public function __construct( /** * {@inheritdoc} */ - public function getLinks($sku) + public function getList($sku) { /** @var \Magento\Catalog\Model\Product $product */ $product = $this->productRepository->get($sku); @@ -134,10 +121,10 @@ protected function buildLink($resourceData) } /** - * Subroutine for buildLink and buildSample + * Subroutine for build link * - * @param \Magento\Downloadable\Model\Link|\Magento\Downloadable\Model\Sample $resourceData - * @param \Magento\Downloadable\Api\Data\LinkInterface|\Magento\Downloadable\Api\Data\SampleInterface $dataObject + * @param \Magento\Downloadable\Model\Link $resourceData + * @param \Magento\Downloadable\Api\Data\LinkInterface $dataObject * @return null */ protected function setBasicFields($resourceData, $dataObject) @@ -156,43 +143,6 @@ protected function setBasicFields($resourceData, $dataObject) $dataObject->setSampleUrl($resourceData->getSampleUrl()); } - /** - * {@inheritdoc} - */ - public function getSamples($sku) - { - $product = $this->productRepository->get($sku); - return $this->getSamplesByProduct($product); - } - - /** - * @param \Magento\Catalog\Api\Data\ProductInterface $product - * @return array - */ - public function getSamplesByProduct(\Magento\Catalog\Api\Data\ProductInterface $product) - { - $sampleList = []; - $samples = $this->downloadableType->getSamples($product); - /** @var \Magento\Downloadable\Model\Sample $sample */ - foreach ($samples as $sample) { - $sampleList[] = $this->buildSample($sample); - } - return $sampleList; - } - - /** - * Build a sample data object - * - * @param \Magento\Downloadable\Model\Sample $resourceData - * @return \Magento\Downloadable\Model\Sample - */ - protected function buildSample($resourceData) - { - $sample = $this->sampleDataObjectFactory->create(); - $this->setBasicFields($resourceData, $sample); - return $sample; - } - /** * {@inheritdoc} * @SuppressWarnings(PHPMD.CyclomaticComplexity) diff --git a/app/code/Magento/Downloadable/Model/Plugin/AfterProductLoad.php b/app/code/Magento/Downloadable/Model/Plugin/AfterProductLoad.php index 83466a0fa080f..d8af61297efab 100644 --- a/app/code/Magento/Downloadable/Model/Plugin/AfterProductLoad.php +++ b/app/code/Magento/Downloadable/Model/Plugin/AfterProductLoad.php @@ -14,6 +14,11 @@ class AfterProductLoad */ protected $linkRepository; + /** + * @var \Magento\Downloadable\Api\SampleRepositoryInterface + */ + protected $sampleRepository; + /** * @var \Magento\Catalog\Api\Data\ProductExtensionFactory */ @@ -21,13 +26,16 @@ class AfterProductLoad /** * @param \Magento\Downloadable\Api\LinkRepositoryInterface $linkRepository + * @param \Magento\Downloadable\Api\SampleRepositoryInterface $sampleRepository * @param \Magento\Catalog\Api\Data\ProductExtensionFactory $productExtensionFactory */ public function __construct( \Magento\Downloadable\Api\LinkRepositoryInterface $linkRepository, + \Magento\Downloadable\Api\SampleRepositoryInterface $sampleRepository, \Magento\Catalog\Api\Data\ProductExtensionFactory $productExtensionFactory ) { $this->linkRepository = $linkRepository; + $this->sampleRepository = $sampleRepository; $this->productExtensionFactory = $productExtensionFactory; } @@ -41,16 +49,13 @@ public function afterLoad( if ($product->getTypeId() != \Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE) { return $product; } - - $productExtension = $product->getExtensionAttributes(); - if ($productExtension === null) { - $productExtension = $this->productExtensionFactory->create(); - } + $productExtension = $product->getExtensionAttributes() + ?: $this->productExtensionFactory->create(); $links = $this->linkRepository->getLinksByProduct($product); if ($links !== null) { $productExtension->setDownloadableProductLinks($links); } - $samples = $this->linkRepository->getSamplesByProduct($product); + $samples = $this->sampleRepository->getSamplesByProduct($product); if ($samples !== null) { $productExtension->setDownloadableProductSamples($samples); } diff --git a/app/code/Magento/Downloadable/Model/SampleRepository.php b/app/code/Magento/Downloadable/Model/SampleRepository.php index f357e6a5d8541..71d76e05f40a7 100644 --- a/app/code/Magento/Downloadable/Model/SampleRepository.php +++ b/app/code/Magento/Downloadable/Model/SampleRepository.php @@ -6,7 +6,8 @@ namespace Magento\Downloadable\Model; use Magento\Catalog\Api\ProductRepositoryInterface; -use Magento\Downloadable\Model\SampleFactory; +use Magento\Downloadable\Api\Data\SampleInterfaceFactory; +use Magento\Downloadable\Model\Product\Type; use Magento\Downloadable\Api\Data\File\ContentUploaderInterface; use Magento\Downloadable\Api\Data\SampleInterface; use Magento\Downloadable\Model\Sample\ContentValidator; @@ -16,7 +17,6 @@ /** * Class SampleRepository - * @package Magento\Downloadable\Model * @SuppressWarnings(PHPMD.CouplingBetweenObjects) */ class SampleRepository implements \Magento\Downloadable\Api\SampleRepositoryInterface @@ -27,14 +27,19 @@ class SampleRepository implements \Magento\Downloadable\Api\SampleRepositoryInte protected $productRepository; /** - * @var \Magento\Downloadable\Model\Product\Type + * @var ContentValidator + */ + protected $contentValidator; + + /** + * @var Type */ protected $downloadableType; /** - * @var ContentValidator + * @var SampleInterfaceFactory */ - protected $contentValidator; + protected $sampleDataObjectFactory; /** * @var ContentUploaderInterface @@ -48,7 +53,8 @@ class SampleRepository implements \Magento\Downloadable\Api\SampleRepositoryInte /** * @param ProductRepositoryInterface $productRepository - * @param \Magento\Downloadable\Model\Product\Type $downloadableType + * @param Type $downloadableType + * @param SampleInterfaceFactory $sampleDataObjectFactory * @param ContentValidator $contentValidator * @param ContentUploaderInterface $fileContentUploader * @param EncoderInterface $jsonEncoder @@ -56,7 +62,8 @@ class SampleRepository implements \Magento\Downloadable\Api\SampleRepositoryInte */ public function __construct( ProductRepositoryInterface $productRepository, - \Magento\Downloadable\Model\Product\Type $downloadableType, + Type $downloadableType, + SampleInterfaceFactory $sampleDataObjectFactory, ContentValidator $contentValidator, ContentUploaderInterface $fileContentUploader, EncoderInterface $jsonEncoder, @@ -68,6 +75,71 @@ public function __construct( $this->fileContentUploader = $fileContentUploader; $this->jsonEncoder = $jsonEncoder; $this->sampleFactory = $sampleFactory; + $this->downloadableType = $downloadableType; + $this->sampleDataObjectFactory = $sampleDataObjectFactory; + } + + /** + * {@inheritdoc} + */ + public function getList($sku) + { + /** @var \Magento\Catalog\Model\Product $product */ + $product = $this->productRepository->get($sku); + return $this->getSamplesByProduct($product); + } + + /** + * Build a sample data object + * + * @param \Magento\Downloadable\Model\Sample $resourceData + * @return \Magento\Downloadable\Model\Sample + */ + protected function buildSample($resourceData) + { + $sample = $this->sampleDataObjectFactory->create(); + $this->setBasicFields($resourceData, $sample); + return $sample; + } + + /** + * Subroutine for buildLink and buildSample + * + * @param \Magento\Downloadable\Model\Link|\Magento\Downloadable\Model\Sample $resourceData + * @param \Magento\Downloadable\Api\Data\LinkInterface|\Magento\Downloadable\Api\Data\SampleInterface $dataObject + * @return null + */ + protected function setBasicFields($resourceData, $dataObject) + { + $dataObject->setId($resourceData->getId()); + $storeTitle = $resourceData->getStoreTitle(); + $title = $resourceData->getTitle(); + if (!empty($storeTitle)) { + $dataObject->setTitle($storeTitle); + } else { + $dataObject->setTitle($title); + } + $dataObject->setSortOrder($resourceData->getSortOrder()); + $dataObject->setSampleType($resourceData->getSampleType()); + $dataObject->setSampleFile($resourceData->getSampleFile()); + $dataObject->setSampleUrl($resourceData->getSampleUrl()); + } + + /** + * List of links with associated samples + * + * @param \Magento\Catalog\Api\Data\ProductInterface $product + * @return \Magento\Downloadable\Api\Data\SampleInterface[] + */ + public function getSamplesByProduct(\Magento\Catalog\Api\Data\ProductInterface $product) + { + $sampleList = []; + $samples = $this->downloadableType->getSamples($product); + /** @var \Magento\Downloadable\Model\Sample $sample */ + foreach ($samples as $sample) { + $sampleList[] = $this->buildSample($sample); + } + return $sampleList; } /** @@ -77,7 +149,6 @@ public function __construct( * @param \Magento\Downloadable\Api\Data\SampleInterface $sample * @param bool $isGlobalScopeContent * @return int - * @SuppressWarnings(PHPMD.CyclomaticComplexity) */ public function save( $sku, @@ -90,7 +161,7 @@ public function save( if ($sampleId) { return $this->updateSample($product, $sample, $isGlobalScopeContent); } else { - if ($product->getTypeId() !== \Magento\Downloadable\Model\Product\Type::TYPE_DOWNLOADABLE) { + if ($product->getTypeId() !== Type::TYPE_DOWNLOADABLE) { throw new InputException(__('Product type of the product must be \'downloadable\'.')); } if (!$this->contentValidator->isValid($sample)) { diff --git a/app/code/Magento/Downloadable/Test/Unit/Model/LinkRepositoryTest.php b/app/code/Magento/Downloadable/Test/Unit/Model/LinkRepositoryTest.php index d4ec184847edc..e030603fd6f3a 100644 --- a/app/code/Magento/Downloadable/Test/Unit/Model/LinkRepositoryTest.php +++ b/app/code/Magento/Downloadable/Test/Unit/Model/LinkRepositoryTest.php @@ -49,10 +49,6 @@ class LinkRepositoryTest extends \PHPUnit_Framework_TestCase */ protected $linkDataObjectFactory; - /** - * @var \PHPUnit_Framework_MockObject_MockObject - */ - protected $sampleDataObjectFactory; /** * @var LinkRepository @@ -119,7 +115,6 @@ protected function setUp() $this->repositoryMock, $this->productTypeMock, $this->linkDataObjectFactory, - $this->sampleDataObjectFactory, $this->linkFactoryMock, $this->contentValidatorMock, $this->jsonEncoderMock, @@ -487,7 +482,7 @@ public function testDeleteThrowsExceptionIfLinkIdIsNotValid() $this->service->delete($linkId); } - public function testGetLinks() + public function testGetList() { $productSku = 'downloadable_sku'; @@ -540,58 +535,7 @@ public function testGetLinks() $this->setLinkAssertions($linkMock, $linkData); $this->linkDataObjectFactory->expects($this->once())->method('create')->willReturn($linkInterfaceMock); - $this->assertEquals([$linkInterfaceMock], $this->service->getLinks($productSku)); - } - - public function testGetSamples() - { - $productSku = 'downloadable_sku'; - - $sampleData = [ - 'id' => 324, - 'store_title' => 'rock melody sample', - 'title' => 'just melody sample', - 'sort_order' => 21, - 'sample_type' => 'file', - 'sample_url' => null, - 'sample_file' => '/r/o/rock.melody.ogg' - ]; - - $sampleMock = $this->getMock( - '\Magento\Downloadable\Model\Sample', - [ - 'getId', - 'getStoreTitle', - 'getTitle', - 'getSampleType', - 'getSampleFile', - 'getSampleUrl', - 'getSortOrder', - 'getData', - '__wakeup' - ], - [], - '', - false - ); - - $sampleInterfaceMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleInterface'); - - $this->repositoryMock->expects($this->once()) - ->method('get') - ->with($productSku) - ->will($this->returnValue($this->productMock)); - - $this->productTypeMock->expects($this->once()) - ->method('getSamples') - ->with($this->productMock) - ->will($this->returnValue([$sampleMock])); - - $this->setSampleAssertions($sampleMock, $sampleData); - - $this->sampleDataObjectFactory->expects($this->once())->method('create')->willReturn($sampleInterfaceMock); - - $this->assertEquals([$sampleInterfaceMock], $this->service->getSamples($productSku)); + $this->assertEquals([$linkInterfaceMock], $this->service->getList($productSku)); } protected function setLinkAssertions($resource, $inputData) @@ -622,21 +566,4 @@ protected function setLinkAssertions($resource, $inputData) $resource->expects($this->any())->method('getLinkUrl') ->will($this->returnValue($inputData['link_url'])); } - - protected function setSampleAssertions($resource, $inputData) - { - $resource->expects($this->any())->method('getId')->will($this->returnValue($inputData['id'])); - $resource->expects($this->any())->method('getStoreTitle') - ->will($this->returnValue($inputData['store_title'])); - $resource->expects($this->any())->method('getTitle') - ->will($this->returnValue($inputData['title'])); - $resource->expects($this->any())->method('getSortOrder') - ->will($this->returnValue($inputData['sort_order'])); - $resource->expects($this->any())->method('getSampleType') - ->will($this->returnValue($inputData['sample_type'])); - $resource->expects($this->any())->method('getSampleFile') - ->will($this->returnValue($inputData['sample_file'])); - $resource->expects($this->any())->method('getSampleUrl') - ->will($this->returnValue($inputData['sample_url'])); - } } diff --git a/app/code/Magento/Downloadable/Test/Unit/Model/Plugin/AfterProductLoadTest.php b/app/code/Magento/Downloadable/Test/Unit/Model/Plugin/AfterProductLoadTest.php index 36f21e6fb5f28..305dacc61c95a 100644 --- a/app/code/Magento/Downloadable/Test/Unit/Model/Plugin/AfterProductLoadTest.php +++ b/app/code/Magento/Downloadable/Test/Unit/Model/Plugin/AfterProductLoadTest.php @@ -36,20 +36,27 @@ class AfterProductLoadTest extends \PHPUnit_Framework_TestCase */ protected $productExtensionFactory; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $sampleRepositoryMock; + protected function setUp() { - $this->linkRepositoryMock = $this->getMock('\Magento\Downloadable\Api\LinkRepositoryInterface'); - $this->productExtensionFactory = $this->getMockBuilder('\Magento\Catalog\Api\Data\ProductExtensionFactory') + $this->linkRepositoryMock = $this->getMock('Magento\Downloadable\Api\LinkRepositoryInterface'); + $this->sampleRepositoryMock = $this->getMock('Magento\Downloadable\Api\SampleRepositoryInterface'); + $this->productExtensionFactory = $this->getMockBuilder('Magento\Catalog\Api\Data\ProductExtensionFactory') ->disableOriginalConstructor() ->getMock(); $this->model = new \Magento\Downloadable\Model\Plugin\AfterProductLoad( $this->linkRepositoryMock, + $this->sampleRepositoryMock, $this->productExtensionFactory ); - $this->productMock = $this->getMockBuilder('\Magento\Catalog\Model\Product') + $this->productMock = $this->getMockBuilder('Magento\Catalog\Model\Product') ->disableOriginalConstructor() ->getMock(); - $this->productExtensionMock = $this->getMockBuilder('\Magento\Catalog\Api\Data\ProductExtension') + $this->productExtensionMock = $this->getMockBuilder('Magento\Catalog\Api\Data\ProductExtension') ->setMethods(['setDownloadableProductLinks', 'setDownloadableProductSamples'])->getMock(); } @@ -63,13 +70,13 @@ public function testAfterLoad() ->method('create') ->willReturn($this->productExtensionMock); - $linkMock = $this->getMock('\Magento\Downloadable\Api\Data\LinkInterface'); + $linkMock = $this->getMock('Magento\Downloadable\Api\Data\LinkInterface'); $this->linkRepositoryMock->expects($this->once()) ->method('getLinksByProduct') ->with($this->productMock) ->willReturn([$linkMock]); - $sampleMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleInterface'); - $this->linkRepositoryMock->expects($this->once()) + $sampleMock = $this->getMock('Magento\Downloadable\Api\Data\SampleInterface'); + $this->sampleRepositoryMock->expects($this->once()) ->method('getSamplesByProduct') ->with($this->productMock) ->willReturn([$sampleMock]); @@ -104,13 +111,13 @@ public function testAfterLoadWithExistingExtensionAttributes() $this->productExtensionFactory->expects($this->never()) ->method('create'); - $linkMock = $this->getMock('\Magento\Downloadable\Api\Data\LinkInterface'); + $linkMock = $this->getMock('Magento\Downloadable\Api\Data\LinkInterface'); $this->linkRepositoryMock->expects($this->once()) ->method('getLinksByProduct') ->with($this->productMock) ->willReturn([$linkMock]); - $sampleMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleInterface'); - $this->linkRepositoryMock->expects($this->once()) + $sampleMock = $this->getMock('Magento\Downloadable\Api\Data\SampleInterface'); + $this->sampleRepositoryMock->expects($this->once()) ->method('getSamplesByProduct') ->with($this->productMock) ->willReturn([$sampleMock]); @@ -143,12 +150,12 @@ public function testAfterLoadOnlyLinks() ->method('create') ->willReturn($this->productExtensionMock); - $linkMock = $this->getMock('\Magento\Downloadable\Api\Data\LinkInterface'); + $linkMock = $this->getMock('Magento\Downloadable\Api\Data\LinkInterface'); $this->linkRepositoryMock->expects($this->once()) ->method('getLinksByProduct') ->with($this->productMock) ->willReturn([$linkMock]); - $this->linkRepositoryMock->expects($this->once()) + $this->sampleRepositoryMock->expects($this->once()) ->method('getSamplesByProduct') ->with($this->productMock) ->willReturn(null); @@ -183,8 +190,8 @@ public function testAfterLoadOnlySamples() ->method('getLinksByProduct') ->with($this->productMock) ->willReturn(null); - $sampleMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleInterface'); - $this->linkRepositoryMock->expects($this->once()) + $sampleMock = $this->getMock('Magento\Downloadable\Api\Data\SampleInterface'); + $this->sampleRepositoryMock->expects($this->once()) ->method('getSamplesByProduct') ->with($this->productMock) ->willReturn([$sampleMock]); diff --git a/app/code/Magento/Downloadable/Test/Unit/Model/SampleRepositoryTest.php b/app/code/Magento/Downloadable/Test/Unit/Model/SampleRepositoryTest.php index 7e25af50c3f6b..672599aa0e770 100644 --- a/app/code/Magento/Downloadable/Test/Unit/Model/SampleRepositoryTest.php +++ b/app/code/Magento/Downloadable/Test/Unit/Model/SampleRepositoryTest.php @@ -50,6 +50,11 @@ class SampleRepositoryTest extends \PHPUnit_Framework_TestCase */ protected $service; + /** + * @var \PHPUnit_Framework_MockObject_MockObject + */ + protected $sampleDataObjectFactory; + protected function setUp() { $this->productMock = $this->getMock( @@ -81,10 +86,23 @@ protected function setUp() '', false ); + $this->productTypeMock = $this->getMockBuilder('\Magento\Downloadable\Model\Product\Type') + ->disableOriginalConstructor() + ->getMock(); + $this->sampleDataObjectFactory = $this->getMockBuilder('\Magento\Downloadable\Api\Data\SampleInterfaceFactory') + ->setMethods( + [ + 'create', + ] + ) + ->disableOriginalConstructor() + ->getMock(); + $this->service = new \Magento\Downloadable\Model\SampleRepository( $this->repositoryMock, $this->productTypeMock, + $this->sampleDataObjectFactory, $this->contentValidatorMock, $this->contentUploaderMock, $this->jsonEncoderMock, @@ -371,4 +389,77 @@ public function testDeleteThrowsExceptionIfSampleIdIsNotValid() $this->service->delete($sampleId); } + + + public function testGetList() + { + $productSku = 'downloadable_sku'; + + $sampleData = [ + 'id' => 324, + 'store_title' => 'rock melody sample', + 'title' => 'just melody sample', + 'sort_order' => 21, + 'sample_type' => 'file', + 'sample_url' => null, + 'sample_file' => '/r/o/rock.melody.ogg' + ]; + + $sampleMock = $this->getMock( + '\Magento\Downloadable\Model\Sample', + [ + 'getId', + 'getStoreTitle', + 'getTitle', + 'getSampleType', + 'getSampleFile', + 'getSampleUrl', + 'getSortOrder', + 'getData', + '__wakeup' + ], + [], + '', + false + ); + + $sampleInterfaceMock = $this->getMock('\Magento\Downloadable\Api\Data\SampleInterface'); + + $this->repositoryMock->expects($this->once()) + ->method('get') + ->with($productSku) + ->will($this->returnValue($this->productMock)); + + $this->productTypeMock->expects($this->once()) + ->method('getSamples') + ->with($this->productMock) + ->will($this->returnValue([$sampleMock])); + + $this->setSampleAssertions($sampleMock, $sampleData); + + $this->sampleDataObjectFactory->expects($this->once())->method('create')->willReturn($sampleInterfaceMock); + + $this->assertEquals([$sampleInterfaceMock], $this->service->getList($productSku)); + } + + /** + * @param $resource + * @param $inputData + */ + protected function setSampleAssertions($resource, $inputData) + { + $resource->expects($this->any())->method('getId')->will($this->returnValue($inputData['id'])); + $resource->expects($this->any())->method('getStoreTitle') + ->will($this->returnValue($inputData['store_title'])); + $resource->expects($this->any())->method('getTitle') + ->will($this->returnValue($inputData['title'])); + $resource->expects($this->any())->method('getSortOrder') + ->will($this->returnValue($inputData['sort_order'])); + $resource->expects($this->any())->method('getSampleType') + ->will($this->returnValue($inputData['sample_type'])); + $resource->expects($this->any())->method('getSampleFile') + ->will($this->returnValue($inputData['sample_file'])); + $resource->expects($this->any())->method('getSampleUrl') + ->will($this->returnValue($inputData['sample_url'])); + } } diff --git a/app/code/Magento/Downloadable/etc/webapi.xml b/app/code/Magento/Downloadable/etc/webapi.xml index 7f597119f9e74..4b1f86ead0eaa 100644 --- a/app/code/Magento/Downloadable/etc/webapi.xml +++ b/app/code/Magento/Downloadable/etc/webapi.xml @@ -8,13 +8,13 @@ - + - + diff --git a/app/code/Magento/Eav/Block/Adminhtml/Attribute/Edit/Main/AbstractMain.php b/app/code/Magento/Eav/Block/Adminhtml/Attribute/Edit/Main/AbstractMain.php index 597b4f563dd27..0bff79e95a10f 100644 --- a/app/code/Magento/Eav/Block/Adminhtml/Attribute/Edit/Main/AbstractMain.php +++ b/app/code/Magento/Eav/Block/Adminhtml/Attribute/Edit/Main/AbstractMain.php @@ -32,9 +32,9 @@ abstract class AbstractMain extends \Magento\Backend\Block\Widget\Form\Generic protected $_eavData = null; /** - * @var \Magento\Eav\Model\Entity\Attribute\Config + * @var \Magento\Eav\Block\Adminhtml\Attribute\PropertyLocker */ - protected $_attributeConfig; + protected $propertyLocker; /** * @var \Magento\Config\Model\Config\Source\YesnoFactory @@ -53,7 +53,7 @@ abstract class AbstractMain extends \Magento\Backend\Block\Widget\Form\Generic * @param \Magento\Eav\Helper\Data $eavData * @param \Magento\Config\Model\Config\Source\YesnoFactory $yesnoFactory * @param \Magento\Eav\Model\Adminhtml\System\Config\Source\InputtypeFactory $inputTypeFactory - * @param \Magento\Eav\Model\Entity\Attribute\Config $attributeConfig + * @param \Magento\Eav\Block\Adminhtml\Attribute\PropertyLocker $propertyLocker * @param array $data */ public function __construct( @@ -63,13 +63,13 @@ public function __construct( \Magento\Eav\Helper\Data $eavData, \Magento\Config\Model\Config\Source\YesnoFactory $yesnoFactory, \Magento\Eav\Model\Adminhtml\System\Config\Source\InputtypeFactory $inputTypeFactory, - \Magento\Eav\Model\Entity\Attribute\Config $attributeConfig, + \Magento\Eav\Block\Adminhtml\Attribute\PropertyLocker $propertyLocker, array $data = [] ) { $this->_eavData = $eavData; $this->_yesnoFactory = $yesnoFactory; $this->_inputTypeFactory = $inputTypeFactory; - $this->_attributeConfig = $attributeConfig; + $this->propertyLocker = $propertyLocker; parent::__construct($context, $registry, $formFactory, $data); } @@ -257,6 +257,7 @@ protected function _prepareForm() } } + $this->propertyLocker->lock($form); $this->setForm($form); return parent::_prepareForm(); @@ -277,27 +278,6 @@ protected function _initFormValues() return parent::_initFormValues(); } - /** - * This method is called before rendering HTML - * - * @return $this - */ - protected function _beforeToHtml() - { - parent::_beforeToHtml(); - $attributeObject = $this->getAttributeObject(); - if ($attributeObject->getId()) { - $form = $this->getForm(); - foreach ($this->_attributeConfig->getLockedFields($attributeObject) as $field) { - if ($element = $form->getElement($field)) { - $element->setDisabled(1); - $element->setReadonly(1); - } - } - } - return $this; - } - /** * Processing block html after rendering * Adding js block to the end of this block diff --git a/app/code/Magento/Eav/Block/Adminhtml/Attribute/PropertyLocker.php b/app/code/Magento/Eav/Block/Adminhtml/Attribute/PropertyLocker.php new file mode 100644 index 0000000000000..ccaab44afee61 --- /dev/null +++ b/app/code/Magento/Eav/Block/Adminhtml/Attribute/PropertyLocker.php @@ -0,0 +1,57 @@ + + */ +class PropertyLocker +{ + /** + * @var Config + */ + private $attributeConfig; + + /** + * @var Registry + */ + protected $registry; + + /** + * @param Registry $registry + * @param Config $attributeConfig + */ + public function __construct( + Registry $registry, + Config $attributeConfig + ) { + $this->registry = $registry; + $this->attributeConfig = $attributeConfig; + } + + /** + * @param \Magento\Framework\Data\Form $form + * @return void + */ + public function lock(\Magento\Framework\Data\Form $form) + { + /** @var \Magento\Eav\Model\Entity\Attribute\AbstractAttribute $attributeObject */ + $attributeObject = $this->registry->registry('entity_attribute'); + if ($attributeObject->getId()) { + foreach ($this->attributeConfig->getLockedFields($attributeObject) as $field) { + if ($element = $form->getElement($field)) { + $element->setDisabled(1); + $element->setReadonly(1); + } + } + } + } +} diff --git a/app/code/Magento/Eav/Test/Unit/Block/Adminhtml/Attribute/PropertyLockerTest.php b/app/code/Magento/Eav/Test/Unit/Block/Adminhtml/Attribute/PropertyLockerTest.php new file mode 100644 index 0000000000000..cf0615c42a7d0 --- /dev/null +++ b/app/code/Magento/Eav/Test/Unit/Block/Adminhtml/Attribute/PropertyLockerTest.php @@ -0,0 +1,71 @@ +attributeMock = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\AbstractAttribute') + ->setMethods(['getId']) + ->disableOriginalConstructor() + ->getMock(); + + $registryMock = $this->getMockBuilder('\Magento\Framework\Registry') + ->setMethods(['registry']) + ->disableOriginalConstructor() + ->getMock(); + $registryMock->expects($this->atLeastOnce())->method('registry')->willReturn($this->attributeMock); + + $this->attributeConfigMock = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\Config') + ->setMethods(['getLockedFields']) + ->disableOriginalConstructor() + ->getMock(); + + $this->formMock = $this->getMockBuilder('Magento\Framework\Data\Form') + ->setMethods(['getElement']) + ->disableOriginalConstructor() + ->getMock(); + + $this->object = new PropertyLocker($registryMock, $this->attributeConfigMock); + } + + /** + * @covers \Magento\Eav\Block\Adminhtml\Attribute\PropertyLocker::lock + */ + public function testLock() + { + $lockedFields = [ + 'is_searchable' => 'is_searchable', + 'is_filterable' => 'is_filterable' + ]; + $this->attributeMock->expects($this->once())->method('getId')->willReturn(1); + $this->attributeConfigMock->expects($this->once())->method('getLockedFields')->willReturn($lockedFields); + + $elementMock = $this->getMockBuilder('\Magento\Framework\Data\Form\Element\AbstractElement') + ->setMethods(['setDisabled', 'setReadonly']) + ->disableOriginalConstructor() + ->getMockForAbstractClass(); + $elementMock->expects($this->exactly(2))->method('setDisabled'); + $elementMock->expects($this->exactly(2))->method('setReadonly'); + $this->formMock->expects($this->exactly(2))->method('getElement')->willReturn($elementMock); + $this->object->lock($this->formMock); + } +} diff --git a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php index 5ee51f1ecbfb4..bebfa0435d69f 100644 --- a/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php +++ b/app/code/Magento/GroupedProduct/Model/Product/Type/Grouped.php @@ -378,7 +378,7 @@ protected function _prepareProduct(\Magento\Framework\Object $buyRequest, $produ foreach ($associatedProducts as $subProduct) { $qty = $productsInfo[$subProduct->getId()]; - if (!is_numeric($qty)) { + if (!is_numeric($qty) || empty($qty)) { continue; } diff --git a/app/code/Magento/GroupedProduct/Test/Unit/Model/Product/Type/GroupedTest.php b/app/code/Magento/GroupedProduct/Test/Unit/Model/Product/Type/GroupedTest.php index 4cf5af00c0294..aed377242d123 100644 --- a/app/code/Magento/GroupedProduct/Test/Unit/Model/Product/Type/GroupedTest.php +++ b/app/code/Magento/GroupedProduct/Test/Unit/Model/Product/Type/GroupedTest.php @@ -576,4 +576,26 @@ public function testPrepareForCartAdvancedWithProductsStrictTrue() $this->_model->prepareForCartAdvanced($buyRequest, $this->product) ); } + + public function testPrepareForCartAdvancedZeroQty() + { + $expectedMsg = "Please specify the quantity of product(s)."; + $associatedId = 9384; + $associatedProduct = $this->getMock('Magento\Catalog\Model\Product', [], [], '', false); + $associatedProduct->expects($this->atLeastOnce())->method('getId')->will($this->returnValue($associatedId)); + + $buyRequest = new \Magento\Framework\Object(); + $buyRequest->setSuperGroup([$associatedId => 0]); + + $cached = true; + $this->product + ->expects($this->atLeastOnce()) + ->method('hasData') + ->will($this->returnValue($cached)); + $this->product + ->expects($this->atLeastOnce()) + ->method('getData') + ->will($this->returnValue([$associatedProduct])); + $this->assertEquals($expectedMsg, $this->_model->prepareForCartAdvanced($buyRequest, $this->product)); + } } diff --git a/app/code/Magento/LayeredNavigation/Block/Navigation/FilterRenderer.php b/app/code/Magento/LayeredNavigation/Block/Navigation/FilterRenderer.php index fb4ff5033e26c..11114ba621c51 100644 --- a/app/code/Magento/LayeredNavigation/Block/Navigation/FilterRenderer.php +++ b/app/code/Magento/LayeredNavigation/Block/Navigation/FilterRenderer.php @@ -7,16 +7,17 @@ */ namespace Magento\LayeredNavigation\Block\Navigation; +use Magento\Catalog\Model\Layer\Filter\FilterInterface; use Magento\Framework\View\Element\Template; +use Magento\LayeredNavigation\Block\Navigation\FilterRendererInterface; -class FilterRenderer extends \Magento\Framework\View\Element\Template implements - \Magento\LayeredNavigation\Block\Navigation\FilterRendererInterface +class FilterRenderer extends Template implements FilterRendererInterface { /** - * @param \Magento\Catalog\Model\Layer\Filter\AbstractFilter $filter + * @param FilterInterface $filter * @return string */ - public function render(\Magento\Catalog\Model\Layer\Filter\AbstractFilter $filter) + public function render(FilterInterface $filter) { $this->assign('filterItems', $filter->getItems()); $html = $this->_toHtml(); diff --git a/app/code/Magento/LayeredNavigation/Block/Navigation/FilterRendererInterface.php b/app/code/Magento/LayeredNavigation/Block/Navigation/FilterRendererInterface.php index c382efa03d5bf..ee4f21d11b1d9 100644 --- a/app/code/Magento/LayeredNavigation/Block/Navigation/FilterRendererInterface.php +++ b/app/code/Magento/LayeredNavigation/Block/Navigation/FilterRendererInterface.php @@ -5,13 +5,19 @@ */ namespace Magento\LayeredNavigation\Block\Navigation; +use Magento\Catalog\Model\Layer\Filter\FilterInterface; + +/** + * Interface FilterRendererInterface + * @api + */ interface FilterRendererInterface { /** * Render filter * - * @param \Magento\Catalog\Model\Layer\Filter\AbstractFilter $filter + * @param FilterInterface $filter * @return string */ - public function render(\Magento\Catalog\Model\Layer\Filter\AbstractFilter $filter); + public function render(FilterInterface $filter); } diff --git a/app/code/Magento/Search/Controller/Adminhtml/Term/Save.php b/app/code/Magento/Search/Controller/Adminhtml/Term/Save.php index 4226695723fd5..3a31a0555a739 100644 --- a/app/code/Magento/Search/Controller/Adminhtml/Term/Save.php +++ b/app/code/Magento/Search/Controller/Adminhtml/Term/Save.php @@ -5,12 +5,31 @@ */ namespace Magento\Search\Controller\Adminhtml\Term; -use Magento\Search\Controller\Adminhtml\Term as TermController; +use Magento\Backend\App\Action\Context; use Magento\Framework\Controller\ResultFactory; +use Magento\Search\Model\QueryFactory; +use Magento\Search\Controller\Adminhtml\Term as TermController; use Magento\Framework\Exception\LocalizedException; class Save extends TermController { + /** + * @var QueryFactory + */ + private $queryFactory; + + /** + * @param Context $context + * @param QueryFactory $queryFactory + */ + public function __construct( + Context $context, + QueryFactory $queryFactory + ) { + parent::__construct($context); + $this->queryFactory = $queryFactory; + } + /** * Save search query * @@ -19,54 +38,69 @@ class Save extends TermController */ public function execute() { - $hasError = false; $data = $this->getRequest()->getPostValue(); - $queryId = $this->getRequest()->getPost('query_id', null); - /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ - $resultRedirect = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); if ($this->getRequest()->isPost() && $data) { - /* @var $model \Magento\Search\Model\Query */ - $model = $this->_objectManager->create('Magento\Search\Model\Query'); - - // validate query - $queryText = $this->getRequest()->getPost('query_text', false); - $storeId = $this->getRequest()->getPost('store_id', false); - try { - if ($queryText) { - $model->setStoreId($storeId); - $model->loadByQueryText($queryText); - if ($model->getId() && $model->getId() != $queryId) { - throw new LocalizedException( - __('You already have an identical search term query.') - ); - } elseif (!$model->getId() && $queryId) { - $model->load($queryId); - } - } elseif ($queryId) { - $model->load($queryId); - } - + $model = $this->loadQuery(); $model->addData($data); $model->setIsProcessed(0); $model->save(); $this->messageManager->addSuccess(__('You saved the search term.')); } catch (LocalizedException $e) { $this->messageManager->addError($e->getMessage()); - $hasError = true; + return $this->proceedToEdit($data); } catch (\Exception $e) { $this->messageManager->addException($e, __('Something went wrong while saving the search query.')); - $hasError = true; + return $this->proceedToEdit($data); } } - if ($hasError) { - $this->_getSession()->setPageData($data); - $resultRedirect->setPath('search/*/edit', ['id' => $queryId]); - return $resultRedirect; - } else { - $resultRedirect->setPath('search/*'); - return $resultRedirect; + /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + $redirectResult = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + return $redirectResult->setPath('search/*'); + } + + /** + * Create\Load Query model instance + * + * @return \Magento\Search\Model\Query + * @throws \Magento\Framework\Exception\LocalizedException + */ + private function loadQuery() + { + //validate query + $queryText = $this->getRequest()->getPost('query_text', false); + $queryId = $this->getRequest()->getPost('query_id', null); + + /* @var $model \Magento\Search\Model\Query */ + $model = $this->queryFactory->create(); + if ($queryText) { + $storeId = $this->getRequest()->getPost('store_id', false); + $model->setStoreId($storeId); + $model->loadByQueryText($queryText); + if ($model->getId() && $model->getId() != $queryId) { + throw new \Magento\Framework\Exception\LocalizedException( + __('You already have an identical search term query.') + ); + } + } + if ($queryId && !$model->getId()) { + $model->load($queryId); } + return $model; + } + + /** + * Redirect to Edit page + * + * @param array $data + * @return \Magento\Backend\Model\View\Result\Redirect + */ + private function proceedToEdit($data) + { + $this->_getSession()->setPageData($data); + /** @var \Magento\Backend\Model\View\Result\Redirect $resultRedirect */ + $redirectResult = $this->resultFactory->create(ResultFactory::TYPE_REDIRECT); + return $redirectResult->setPath('search/*/edit', ['id' => $this->getRequest()->getPost('query_id', null)]); } } diff --git a/app/code/Magento/Search/Model/Resource/Helper.php b/app/code/Magento/Search/Model/Resource/Helper.php deleted file mode 100644 index 3a9ddcf7bb682..0000000000000 --- a/app/code/Magento/Search/Model/Resource/Helper.php +++ /dev/null @@ -1,84 +0,0 @@ - words, 1 => terms) - * @SuppressWarnings(PHPMD.CyclomaticComplexity) - */ - public function prepareTerms($str, $maxWordLength = 0) - { - $boolWords = ['+' => '+', '-' => '-', '|' => '|', '<' => '<', '>' => '>', '~' => '~', '*' => '*']; - $brackets = ['(' => '(', ')' => ')']; - $words = [0 => ""]; - $terms = []; - preg_match_all('/([\(\)]|[\"\'][^"\']*[\"\']|[^\s\"\(\)]*)/uis', $str, $matches); - $isOpenBracket = 0; - foreach ($matches[1] as $word) { - $word = trim($word); - if (strlen($word)) { - $word = str_replace('"', '', $word); - $isBool = in_array(strtoupper($word), $boolWords); - $isBracket = in_array($word, $brackets); - if (!$isBool && !$isBracket) { - $terms[$word] = $word; - $word = '"' . $word . '"'; - $words[] = $word; - } elseif ($isBracket) { - if ($word == '(') { - $isOpenBracket++; - } else { - $isOpenBracket--; - } - $words[] = $word; - } elseif ($isBool) { - $words[] = $word; - } - } - } - if ($isOpenBracket > 0) { - $words[] = sprintf("%')" . $isOpenBracket . "s", ''); - } elseif ($isOpenBracket < 0) { - $words[0] = sprintf("%'(" . $isOpenBracket . "s", ''); - } - if ($maxWordLength && count($terms) > $maxWordLength) { - $terms = array_slice($terms, 0, $maxWordLength); - } - $result = [$words, $terms]; - return $result; - } - - /** - * Use sql compatible with Full Text indexes - * - * @param string $table The table to insert data into. - * @param array $data Column-value pairs or array of column-value pairs. - * @param array $fields update fields pairs or values - * @return int The number of affected rows. - */ - public function insertOnDuplicate($table, array $data, array $fields = []) - { - return $this->_getWriteAdapter()->insertOnDuplicate($table, $data, $fields); - } -} diff --git a/app/code/Magento/Search/Model/Resource/Query/Collection.php b/app/code/Magento/Search/Model/Resource/Query/Collection.php index c441ac7b760cc..03772a446b6dd 100644 --- a/app/code/Magento/Search/Model/Resource/Query/Collection.php +++ b/app/code/Magento/Search/Model/Resource/Query/Collection.php @@ -30,7 +30,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac /** * Search resource helper * - * @var \Magento\Search\Model\Resource\Helper + * @var \Magento\Framework\DB\Helper */ protected $_resourceHelper; @@ -40,7 +40,7 @@ class Collection extends \Magento\Framework\Model\Resource\Db\Collection\Abstrac * @param \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy * @param \Magento\Framework\Event\ManagerInterface $eventManager * @param \Magento\Store\Model\StoreManagerInterface $storeManager - * @param \Magento\Search\Model\Resource\Helper $resourceHelper + * @param \Magento\Framework\DB\Helper $resourceHelper * @param \Zend_Db_Adapter_Abstract $connection * @param \Magento\Framework\Model\Resource\Db\AbstractDb $resource */ @@ -50,7 +50,7 @@ public function __construct( \Magento\Framework\Data\Collection\Db\FetchStrategyInterface $fetchStrategy, \Magento\Framework\Event\ManagerInterface $eventManager, \Magento\Store\Model\StoreManagerInterface $storeManager, - \Magento\Search\Model\Resource\Helper $resourceHelper, + \Magento\Framework\DB\Helper $resourceHelper, $connection = null, \Magento\Framework\Model\Resource\Db\AbstractDb $resource = null ) { diff --git a/app/code/Magento/Search/Setup/UpgradeSchema.php b/app/code/Magento/Search/Setup/UpgradeSchema.php new file mode 100644 index 0000000000000..461c7fd3d3d23 --- /dev/null +++ b/app/code/Magento/Search/Setup/UpgradeSchema.php @@ -0,0 +1,49 @@ +moduleList = $moduleList; + } + + /** + * Upgrades DB schema for a module + * + * @param SchemaSetupInterface $setup + * @param ModuleContextInterface $context + * @return void + */ + public function upgrade(SchemaSetupInterface $setup, ModuleContextInterface $context) + { + if (version_compare($context->getVersion(), '2.0.0.1') < 0) { + $setup->startSetup(); + $connection = $setup->getConnection(); + $tableName = $setup->getTable('search_query'); + $idxName = $setup->getIdxName('search_query', ['is_processed']); + $connection->addIndex($tableName, $idxName, ['is_processed']); + $setup->endSetup(); + } + } +} diff --git a/app/code/Magento/Search/Test/Unit/Controller/Adminhtml/Term/SaveTest.php b/app/code/Magento/Search/Test/Unit/Controller/Adminhtml/Term/SaveTest.php new file mode 100644 index 0000000000000..5197e7d83e450 --- /dev/null +++ b/app/code/Magento/Search/Test/Unit/Controller/Adminhtml/Term/SaveTest.php @@ -0,0 +1,236 @@ +context = $this->getMockBuilder('Magento\Backend\App\Action\Context') + ->disableOriginalConstructor() + ->getMock(); + + $this->redirect = $this->getMockBuilder('Magento\Backend\Model\View\Result\Redirect') + ->setMethods(['setPath']) + ->disableOriginalConstructor() + ->getMock(); + $redirectFactory = $this->getMockBuilder('\Magento\Framework\Controller\ResultFactory') + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + $redirectFactory->expects($this->any()) + ->method('create') + ->will($this->returnValue($this->redirect)); + $this->context->expects($this->any()) + ->method('getResultRedirectFactory') + ->willReturn($redirectFactory); + $this->context->expects($this->any()) + ->method('getResultFactory') + ->willReturn($redirectFactory); + + $this->request = $this->getMockBuilder('\Magento\Framework\App\RequestInterface') + ->disableOriginalConstructor() + ->setMethods(['getPostValue', 'isPost', 'getPost']) + ->getMockForAbstractClass(); + $this->context->expects($this->atLeastOnce()) + ->method('getRequest') + ->willReturn($this->request); + + $objectManager = $this->getMockBuilder('\Magento\Framework\ObjectManagerInterface') + ->disableOriginalConstructor() + ->setMethods(['create']) + ->getMockForAbstractClass(); + $this->context->expects($this->any()) + ->method('getObjectManager') + ->willReturn($objectManager); + + $this->messageManager = $this->getMockBuilder('\Magento\Framework\Message\ManagerInterface') + ->disableOriginalConstructor() + ->setMethods(['addSuccess', 'addError', 'addException']) + ->getMockForAbstractClass(); + $this->context->expects($this->any()) + ->method('getMessageManager') + ->willReturn($this->messageManager); + + $this->session = $this->getMockBuilder('\Magento\Backend\Model\Session') + ->disableOriginalConstructor() + ->setMethods(['setPageData']) + ->getMock(); + $this->context->expects($this->any()) + ->method('getSession') + ->willReturn($this->session); + + $this->query = $this->getMockBuilder('Magento\Search\Model\Query') + ->disableOriginalConstructor() + ->setMethods(['getId', 'load', 'addData', 'setIsProcessed', 'save', 'loadByQueryText', 'setStoreId']) + ->getMock(); + $queryFactory = $this->getMockBuilder('Magento\Search\Model\QueryFactory') + ->setMethods(['create']) + ->disableOriginalConstructor() + ->getMock(); + $queryFactory->expects($this->any()) + ->method('create') + ->will($this->returnValue($this->query)); + + $this->controller = $objectManagerHelper->getObject( + 'Magento\Search\Controller\Adminhtml\Term\Save', + [ + 'context' => $this->context, + 'queryFactory' => $queryFactory, + ] + ); + } + + /** + * @param bool $isPost + * @param array $data + * @dataProvider executeIsPostDataDataProvider + */ + public function testExecuteIsPostData($isPost, $data) + { + $this->request->expects($this->at(0))->method('getPostValue')->willReturn($data); + $this->request->expects($this->at(1))->method('isPost')->willReturn($isPost); + $this->redirect->expects($this->once())->method('setPath')->willReturnSelf(); + $this->assertSame($this->redirect, $this->controller->execute()); + } + + /** + * @return array + */ + public function executeIsPostDataDataProvider() + { + return [ + [false, ['0' => '0']], + [true, []] + ]; + } + + public function testExecuteLoadQueryQueryId() + { + $queryId = 1; + $queryText = ''; + $this->mockGetRequestData($queryText, $queryId); + + $this->query->expects($this->once())->method('getId')->willReturn(false); + $this->query->expects($this->once())->method('load')->with($queryId); + + $this->messageManager->expects($this->once())->method('addSuccess'); + + $this->redirect->expects($this->once())->method('setPath')->willReturnSelf(); + $this->assertSame($this->redirect, $this->controller->execute()); + } + + public function testExecuteLoadQueryQueryIdQueryText() + { + $queryId = 1; + $queryText = 'search'; + $this->mockGetRequestData($queryText, $queryId); + + $this->request->expects($this->at(4))->method('getPost')->with('store_id', false)->willReturn(1); + + $this->query->expects($this->once())->method('setStoreId'); + $this->query->expects($this->once())->method('loadByQueryText')->with($queryText); + $this->query->expects($this->any())->method('getId')->willReturn($queryId); + + $this->messageManager->expects($this->once())->method('addSuccess'); + + $this->redirect->expects($this->once())->method('setPath')->willReturnSelf(); + $this->assertSame($this->redirect, $this->controller->execute()); + } + + public function testExecuteLoadQueryQueryIdQueryText2() + { + $queryId = 1; + $queryText = 'search'; + $this->mockGetRequestData($queryText, $queryId); + + $this->request->expects($this->at(4))->method('getPost')->with('store_id', false)->willReturn(1); + + $this->query->expects($this->once())->method('setStoreId'); + $this->query->expects($this->once())->method('loadByQueryText')->with($queryText); + $this->query->expects($this->any())->method('getId')->willReturn(false); + $this->query->expects($this->once())->method('load')->with($queryId); + + $this->messageManager->expects($this->once())->method('addSuccess'); + + $this->redirect->expects($this->once())->method('setPath')->willReturnSelf(); + $this->assertSame($this->redirect, $this->controller->execute()); + } + + public function testExecuteLoadQueryQueryIdQueryTextException() + { + $queryId = 1; + $anotherQueryId = 2; + $queryText = 'search'; + $this->mockGetRequestData($queryText, $queryId); + + $this->request->expects($this->at(4))->method('getPost')->with('store_id', false)->willReturn(1); + + $this->query->expects($this->once())->method('setStoreId'); + $this->query->expects($this->once())->method('loadByQueryText')->with($queryText); + $this->query->expects($this->any())->method('getId')->willReturn($anotherQueryId); + + $this->messageManager->expects($this->once())->method('addError'); + $this->session->expects($this->once())->method('setPageData'); + $this->redirect->expects($this->once())->method('setPath')->willReturnSelf(); + $this->assertSame($this->redirect, $this->controller->execute()); + } + + public function testExecuteException() + { + $queryId = 1; + $queryText = 'search'; + $this->mockGetRequestData($queryText, $queryId); + + $this->request->expects($this->at(4))->method('getPost')->with('store_id', false)->willReturn(1); + + $this->query->expects($this->once())->method('setStoreId'); + $this->query->expects($this->once())->method('loadByQueryText')->willThrowException(new \Exception()); + + $this->messageManager->expects($this->once())->method('addException'); + $this->session->expects($this->once())->method('setPageData'); + $this->redirect->expects($this->once())->method('setPath')->willReturnSelf(); + $this->assertSame($this->redirect, $this->controller->execute()); + } + + /** + * @param string $queryText + * @param int $queryId + */ + private function mockGetRequestData($queryText, $queryId) + { + $this->request->expects($this->at(0))->method('getPostValue')->willReturn(['0' => '0']); + $this->request->expects($this->at(1))->method('isPost')->willReturn(true); + $this->request->expects($this->at(2))->method('getPost')->with('query_text', false)->willReturn($queryText); + $this->request->expects($this->at(3))->method('getPost')->with('query_id', null)->willReturn($queryId); + } +} diff --git a/app/code/Magento/Search/etc/module.xml b/app/code/Magento/Search/etc/module.xml index 8719bbd18c2cf..2648b158b5042 100644 --- a/app/code/Magento/Search/etc/module.xml +++ b/app/code/Magento/Search/etc/module.xml @@ -7,7 +7,7 @@ --> - + diff --git a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/LinkRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/LinkRepositoryTest.php index 656da53f38e84..4c6ff5ed4465b 100644 --- a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/LinkRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/LinkRepositoryTest.php @@ -920,26 +920,12 @@ public function getListForAbsentProductProvider() ] ]; - $sampleExpectation = [ - 'fields' => [ - 'title' => 'Downloadable Product Sample Title', - 'sort_order' => 0, - 'sample_file' => '/f/u/jellyfish_1_4.jpg', - 'sample_type' => 'file' - ] - ]; - return [ 'links' => [ '/downloadable-links', - 'GetLinks', + 'GetList', $linkExpectation, ], - 'samples' => [ - '/downloadable-links/samples', - 'GetSamples', - $sampleExpectation, - ], ]; } } diff --git a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/SampleRepositoryTest.php b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/SampleRepositoryTest.php index 0a1bba69a8989..dfd7ee356eb76 100644 --- a/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/SampleRepositoryTest.php +++ b/dev/tests/api-functional/testsuite/Magento/Downloadable/Api/SampleRepositoryTest.php @@ -515,4 +515,56 @@ public function testDeleteThrowsExceptionIfThereIsNoDownloadableSampleWithGivenI $this->_webApiCall($this->deleteServiceInfo, $requestData); } + + /** + * @magentoApiDataFixture Magento/Downloadable/_files/product_downloadable_with_files.php + * @dataProvider getListForAbsentProductProvider + */ + public function testGetList($urlTail, $method, $expectations) + { + $sku = 'downloadable-product'; + + $serviceInfo = [ + 'rest' => [ + 'resourcePath' => '/V1/products/' . $sku . $urlTail, + 'httpMethod' => \Magento\Framework\Webapi\Rest\Request::HTTP_METHOD_GET, + ], + 'soap' => [ + 'service' => 'downloadableSampleRepositoryV1', + 'serviceVersion' => 'V1', + 'operation' => 'downloadableSampleRepositoryV1' . $method, + ], + ]; + + $requestData = ['sku' => $sku]; + + $list = $this->_webApiCall($serviceInfo, $requestData); + + $this->assertEquals(1, count($list)); + + $link = reset($list); + foreach ($expectations['fields'] as $index => $value) { + $this->assertEquals($value, $link[$index]); + } + } + + public function getListForAbsentProductProvider() + { + $sampleExpectation = [ + 'fields' => [ + 'title' => 'Downloadable Product Sample Title', + 'sort_order' => 0, + 'sample_file' => '/f/u/jellyfish_1_4.jpg', + 'sample_type' => 'file' + ] + ]; + + return [ + 'samples' => [ + '/downloadable-links/samples', + 'GetList', + $sampleExpectation, + ], + ]; + } } diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/FrontTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/FrontTest.php index 631738f29155b..97fae046b884b 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/FrontTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Block/Adminhtml/Product/Attribute/Edit/Tab/FrontTest.php @@ -37,7 +37,7 @@ public function testToHtml($attributeCode) { /** @var \Magento\Catalog\Model\Resource\Eav\Attribute $model */ $model = $this->objectManager->create('Magento\Catalog\Model\Resource\Eav\Attribute'); - $model->load($attributeCode, 'attribute_code'); + $model->loadByCode(\Magento\Catalog\Model\Product::ENTITY, $attributeCode); /** @var \Magento\Framework\Registry $coreRegistry */ $coreRegistry = $this->objectManager->get('\Magento\Framework\Registry'); diff --git a/dev/tests/integration/testsuite/Magento/Eav/Block/Adminhtml/Attribute/Edit/Main/AbstractTest.php b/dev/tests/integration/testsuite/Magento/Eav/Block/Adminhtml/Attribute/Edit/Main/AbstractMainTest.php similarity index 93% rename from dev/tests/integration/testsuite/Magento/Eav/Block/Adminhtml/Attribute/Edit/Main/AbstractTest.php rename to dev/tests/integration/testsuite/Magento/Eav/Block/Adminhtml/Attribute/Edit/Main/AbstractMainTest.php index 7ab902da2f613..3e8b1f30a0c2a 100644 --- a/dev/tests/integration/testsuite/Magento/Eav/Block/Adminhtml/Attribute/Edit/Main/AbstractTest.php +++ b/dev/tests/integration/testsuite/Magento/Eav/Block/Adminhtml/Attribute/Edit/Main/AbstractMainTest.php @@ -9,7 +9,7 @@ */ namespace Magento\Eav\Block\Adminhtml\Attribute\Edit\Main; -class AbstractTest extends \PHPUnit_Framework_TestCase +class AbstractMainTest extends \PHPUnit_Framework_TestCase { /** * @magentoAppIsolation enabled @@ -38,7 +38,7 @@ public function testPrepareForm() $objectManager->get('Magento\Eav\Helper\Data'), $objectManager->get('Magento\Config\Model\Config\Source\YesnoFactory'), $objectManager->get('Magento\Eav\Model\Adminhtml\System\Config\Source\InputtypeFactory'), - $objectManager->get('Magento\Eav\Model\Entity\Attribute\Config') + $objectManager->get('Magento\Eav\Block\Adminhtml\Attribute\PropertyLocker') ] )->setLayout( $objectManager->create('Magento\Framework\View\Layout') diff --git a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php index 7f76c862105e0..9be8e1ae1f468 100755 --- a/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php +++ b/dev/tests/static/testsuite/Magento/Test/Legacy/_files/obsolete_classes.php @@ -3336,4 +3336,5 @@ ['Magento\Log\Model\LogFactory\Clean'], ['Magento\Log\Model\Shell\CommandInterface'], ['Magento\Framework\App\Filesystem\DirectoryList\AbstractShell'], + ['Magento\Search\Model\Resource\Helper'], ];