diff --git a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php index d7cd6ba3984241576669bac898c412a9351d0858..89081edb46ca1c6f1f3849f6a7f8246dd0625fba 100644 --- a/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php +++ b/app/code/Magento/Catalog/Controller/Adminhtml/Product/Save.php @@ -9,7 +9,12 @@ namespace Magento\Catalog\Controller\Adminhtml\Product; use Magento\Backend\App\Action; use Magento\Catalog\Controller\Adminhtml\Product; use Magento\Store\Model\StoreManagerInterface; +use Magento\Framework\App\Request\DataPersistorInterface; +/** + * Class Save + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ class Save extends \Magento\Catalog\Controller\Adminhtml\Product { /** @@ -37,6 +42,11 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Product */ protected $productRepository; + /** + * @var DataPersistorInterface + */ + protected $dataPersistor; + /** * @var StoreManagerInterface */ @@ -110,6 +120,7 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Product $this->copyToStores($data, $productId); $this->messageManager->addSuccess(__('You saved the product.')); + $this->getDataPersistor()->clear('catalog_product'); if ($product->getSku() != $originalSku) { $this->messageManager->addNotice( __( @@ -131,11 +142,13 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Product } catch (\Magento\Framework\Exception\LocalizedException $e) { $this->messageManager->addError($e->getMessage()); $this->_session->setProductData($data); + $this->getDataPersistor()->set('catalog_product', $data); $redirectBack = $productId ? true : 'new'; } catch (\Exception $e) { $this->_objectManager->get('Psr\Log\LoggerInterface')->critical($e); $this->messageManager->addError($e->getMessage()); $this->_session->setProductData($data); + $this->getDataPersistor()->set('catalog_product', $data); $redirectBack = $productId ? true : 'new'; } } else { @@ -246,4 +259,18 @@ class Save extends \Magento\Catalog\Controller\Adminhtml\Product } return $this->storeManager; } + + /** + * Retrieve data persistor + * + * @return DataPersistorInterface|mixed + */ + protected function getDataPersistor() + { + if (null === $this->dataPersistor) { + $this->dataPersistor = $this->_objectManager->get(DataPersistorInterface::class); + } + + return $this->dataPersistor; + } } diff --git a/app/code/Magento/Catalog/Model/ImageExtractor.php b/app/code/Magento/Catalog/Model/ImageExtractor.php index bf45816f45a1c063ef616f16b074326fdc885e3e..c83c7106ce20a5621951ee950c2812251341730f 100644 --- a/app/code/Magento/Catalog/Model/ImageExtractor.php +++ b/app/code/Magento/Catalog/Model/ImageExtractor.php @@ -30,7 +30,11 @@ class ImageExtractor implements \Magento\Framework\View\Xsd\Media\TypeDataExtrac if ($attribute->nodeType != XML_ELEMENT_NODE) { continue; } - $nodeValue = $attribute->nodeValue; + if ($attribute->tagName == 'background') { + $nodeValue = $this->processImageBackground($attribute->nodeValue); + } else { + $nodeValue = $attribute->nodeValue; + } $result[$mediaParentTag][$moduleNameImage][Image::MEDIA_TYPE_CONFIG_NODE][$imageId][$attribute->tagName] = $nodeValue; } @@ -38,4 +42,20 @@ class ImageExtractor implements \Magento\Framework\View\Xsd\Media\TypeDataExtrac return $result; } + + /** + * Convert rgb background string into array + * + * @param string $backgroundString + * @return int[] + */ + private function processImageBackground($backgroundString) + { + $pattern = '#\[(\d{1,3}),\s*(\d{1,3}),\s*(\d{1,3})\]#'; + $backgroundArray = []; + if (preg_match($pattern, $backgroundString, $backgroundArray)) { + array_shift($backgroundArray); + } + return $backgroundArray; + } } diff --git a/app/code/Magento/Catalog/Model/Locator/RegistryLocator.php b/app/code/Magento/Catalog/Model/Locator/RegistryLocator.php index 433fe2b324bdd5129aa1a35c6e8e5e30e68bb9ad..3b288b00b6e467d49715013c73ffc879a9943380 100644 --- a/app/code/Magento/Catalog/Model/Locator/RegistryLocator.php +++ b/app/code/Magento/Catalog/Model/Locator/RegistryLocator.php @@ -5,7 +5,10 @@ */ namespace Magento\Catalog\Model\Locator; +use Magento\Catalog\Api\Data\ProductInterface; +use Magento\Framework\Exception\NotFoundException; use Magento\Framework\Registry; +use Magento\Store\Api\Data\StoreInterface; /** * Class RegistryLocator @@ -15,7 +18,17 @@ class RegistryLocator implements LocatorInterface /** * @var Registry */ - protected $registry; + private $registry; + + /** + * @var ProductInterface + */ + private $product; + + /** + * @var StoreInterface + */ + private $store; /** * @param Registry $registry @@ -27,30 +40,46 @@ class RegistryLocator implements LocatorInterface /** * {@inheritdoc} + * @throws NotFoundException */ public function getProduct() { - return $this->registry->registry('current_product'); + if (null !== $this->product) { + return $this->product; + } + + if ($product = $this->registry->registry('current_product')) { + return $this->product = $product; + } + + throw new NotFoundException(__('Product was not registered')); } /** * {@inheritdoc} + * @throws NotFoundException */ public function getStore() { - return $this->registry->registry('current_store'); - } + if (null !== $this->store) { + return $this->store; + } + if ($store = $this->registry->registry('current_store')) { + return $this->store = $store; + } + + throw new NotFoundException(__('Store was not registered')); + } /** * {@inheritdoc} */ public function getWebsiteIds() { - return $this->registry->registry('current_product')->getWebsiteIds(); + return $this->getProduct()->getWebsiteIds(); } - /** * {@inheritdoc} */ diff --git a/app/code/Magento/Catalog/Test/Unit/Model/ImageExtractorTest.php b/app/code/Magento/Catalog/Test/Unit/Model/ImageExtractorTest.php new file mode 100644 index 0000000000000000000000000000000000000000..fe255ea63ca667bc2959b0256b93df6038a528ab --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/ImageExtractorTest.php @@ -0,0 +1,40 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Catalog\Test\Unit\Model; + +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; + +class ImageExtractorTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var \Magento\Catalog\Model\ImageExtractor + */ + private $model; + + protected function setUp() + { + $objectManager = new ObjectManager($this); + $this->model = $objectManager->getObject(\Magento\Catalog\Model\ImageExtractor::class); + } + + public function testProcess() + { + $expectedArray = include(__DIR__ . '/_files/converted_view.php'); + $this->assertEquals($expectedArray, $this->model->process($this->getDomElement(), 'media')); + } + + /** + * Get mocked dom element + * + * @return \DOMElement + */ + private function getDomElement() + { + $doc = new \DOMDocument(); + $doc->load(__DIR__ . '/_files/valid_view.xml'); + return $doc->getElementsByTagName('images')->item(0); + } +} diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Locator/RegistryLocatorTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Locator/RegistryLocatorTest.php index 86df3eaf30ebb1c02dd51cd3514d6ee458cafbf4..d66bb4192a693887abb1f81ed61745af9b6b880d 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Locator/RegistryLocatorTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Locator/RegistryLocatorTest.php @@ -9,6 +9,7 @@ use Magento\Catalog\Api\Data\ProductInterface; use Magento\Catalog\Model\Locator\RegistryLocator; use Magento\Framework\Registry; use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Store\Api\Data\StoreInterface; /** * Class RegistryLocatorTest @@ -26,36 +27,75 @@ class RegistryLocatorTest extends \PHPUnit_Framework_TestCase protected $model; /** - * @var Registry + * @var Registry|\PHPUnit_Framework_MockObject_MockObject */ protected $registryMock; /** - * @var ProductInterface + * @var ProductInterface|\PHPUnit_Framework_MockObject_MockObject */ protected $productMock; + /** + * @var StoreInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $storeMock; + protected function setUp() { $this->objectManager = new ObjectManager($this); - $this->registryMock = $this->getMockBuilder('Magento\Framework\Registry') + $this->registryMock = $this->getMockBuilder(Registry::class) ->setMethods(['registry']) ->getMock(); - $this->productMock = $this->getMockBuilder('Magento\Catalog\Api\Data\ProductInterface') + $this->productMock = $this->getMockBuilder(ProductInterface::class) + ->getMockForAbstractClass(); + $this->storeMock = $this->getMockBuilder(StoreInterface::class) ->getMockForAbstractClass(); + $this->model = $this->objectManager->getObject(RegistryLocator::class, [ + 'registry' => $this->registryMock, + ]); + } + + public function testGetProduct() + { $this->registryMock->expects($this->once()) ->method('registry') ->with('current_product') ->willReturn($this->productMock); - $this->model = $this->objectManager->getObject('Magento\Catalog\Model\Locator\RegistryLocator', [ - 'registry' => $this->registryMock, - ]); + $this->assertInstanceOf(ProductInterface::class, $this->model->getProduct()); + // Lazy loading + $this->assertInstanceOf(ProductInterface::class, $this->model->getProduct()); } - public function testGetProduct() + public function testGetStore() + { + $this->registryMock->expects($this->once()) + ->method('registry') + ->with('current_store') + ->willReturn($this->storeMock); + + $this->assertInstanceOf(StoreInterface::class, $this->model->getStore()); + // Lazy loading + $this->assertInstanceOf(StoreInterface::class, $this->model->getStore()); + } + + /** + * @expectedException \Magento\Framework\Exception\NotFoundException + * @expectedExceptionMessage Product was not registered + */ + public function testGetProductWithException() + { + $this->assertInstanceOf(ProductInterface::class, $this->model->getProduct()); + } + + /** + * @expectedException \Magento\Framework\Exception\NotFoundException + * @expectedExceptionMessage Store was not registered + */ + public function testGetStoreWithException() { - $this->assertInstanceOf('Magento\Catalog\Api\Data\ProductInterface', $this->model->getProduct()); + $this->assertInstanceOf(StoreInterface::class, $this->model->getStore()); } } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/_files/converted_view.php b/app/code/Magento/Catalog/Test/Unit/Model/_files/converted_view.php new file mode 100644 index 0000000000000000000000000000000000000000..49d865253ced4917fabaa7c245ef238421a05e46 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/_files/converted_view.php @@ -0,0 +1,19 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +return [ + "media" => [ + "Magento_Catalog" => [ + "images" => [ + "swatch_thumb_base" => [ + "type" => "swatch_thumb", + "width" => 75, + "height" => 75, + "background" => [255, 25, 2] + ] + ] + ] + ] +]; diff --git a/app/code/Magento/Catalog/Test/Unit/Model/_files/valid_view.xml b/app/code/Magento/Catalog/Test/Unit/Model/_files/valid_view.xml new file mode 100644 index 0000000000000000000000000000000000000000..c6a1aec333fab172f6094a3c8903dea8e0b17ff4 --- /dev/null +++ b/app/code/Magento/Catalog/Test/Unit/Model/_files/valid_view.xml @@ -0,0 +1,18 @@ +<?xml version="1.0"?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<view xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Config/etc/view.xsd"> + <media> + <images module="Magento_Catalog"> + <image id="swatch_thumb_base" type="swatch_thumb"> + <width>75</width> + <height>75</height> + <background>[255, 25, 2]</background> + </image> + </images> + </media> +</view> diff --git a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AbstractModifierTest.php b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AbstractModifierTest.php index 72ebbf5529a581c5030fa7c79bae622769369519..648775613d37fa2d73ede066cb6a1ea622c4eb48 100644 --- a/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AbstractModifierTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Ui/DataProvider/Product/Form/Modifier/AbstractModifierTest.php @@ -66,7 +66,7 @@ abstract class AbstractModifierTest extends \PHPUnit_Framework_TestCase 'getExistsStoreValueFlag' ])->getMockForAbstractClass(); $this->storeMock = $this->getMockBuilder(StoreInterface::class) - ->setMethods(['load', 'getId']) + ->setMethods(['load', 'getId', 'getConfig']) ->getMockForAbstractClass(); $this->arrayManagerMock = $this->getMockBuilder(ArrayManager::class) ->disableOriginalConstructor() diff --git a/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Websites.php b/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Websites.php index 92b551a820194879de22d9ce789ed62c6d4f04f4..f3c441f1aec06c6bfa1fb9141ef6936a6d404b29 100644 --- a/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Websites.php +++ b/app/code/Magento/Catalog/Ui/Component/Listing/Columns/Websites.php @@ -56,6 +56,9 @@ class Websites extends \Magento\Ui\Component\Listing\Columns\Column foreach ($dataSource['data']['items'] as & $item) { $websites = []; foreach ($item[$fieldName] as $websiteId) { + if (!isset($websiteNames[$websiteId])) { + continue; + } $websites[] = $websiteNames[$websiteId]; } $item[$fieldName] = implode(', ', $websites); diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php index ca9f88a81e1f925f866df8ddd30c1f27375059b1..454cf335632e6935a4d1ca693a03b14fb5dff891 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/Eav.php @@ -18,6 +18,7 @@ use Magento\Eav\Model\Config; use Magento\Eav\Model\ResourceModel\Entity\Attribute\Group\CollectionFactory as GroupCollectionFactory; use Magento\Framework\Api\SearchCriteriaBuilder; use Magento\Framework\Api\SortOrderBuilder; +use Magento\Framework\App\Request\DataPersistorInterface; use Magento\Framework\App\RequestInterface; use Magento\Framework\Filter\Translit; use Magento\Framework\Stdlib\ArrayManager; @@ -155,6 +156,11 @@ class Eav extends AbstractModifier */ private $attributesToEliminate; + /** + * @var DataPersistorInterface + */ + private $dataPersistor; + /** * @param LocatorInterface $locator * @param EavValidationRules $eavValidationRules @@ -172,6 +178,7 @@ class Eav extends AbstractModifier * @param Translit $translitFilter * @param ArrayManager $arrayManager * @param ScopeOverriddenValue $scopeOverriddenValue + * @param DataPersistorInterface $dataPersistor * @param array $attributesToDisable * @param array $attributesToEliminate * @SuppressWarnings(PHPMD.ExcessiveParameterList) @@ -193,6 +200,7 @@ class Eav extends AbstractModifier Translit $translitFilter, ArrayManager $arrayManager, ScopeOverriddenValue $scopeOverriddenValue, + DataPersistorInterface $dataPersistor, $attributesToDisable = [], $attributesToEliminate = [] ) { @@ -212,6 +220,7 @@ class Eav extends AbstractModifier $this->translitFilter = $translitFilter; $this->arrayManager = $arrayManager; $this->scopeOverriddenValue = $scopeOverriddenValue; + $this->dataPersistor = $dataPersistor; $this->attributesToDisable = $attributesToDisable; $this->attributesToEliminate = $attributesToEliminate; } @@ -322,6 +331,10 @@ class Eav extends AbstractModifier */ public function modifyData(array $data) { + if (!$this->locator->getProduct()->getId() && $this->dataPersistor->get('catalog_product')) { + return $this->resolvePersistentData($data); + } + $productId = $this->locator->getProduct()->getId(); /** @var string $groupCode */ @@ -340,6 +353,29 @@ class Eav extends AbstractModifier return $data; } + /** + * Resolve data persistence + * + * @param array $data + * @return array + */ + private function resolvePersistentData(array $data) + { + $persistentData = (array)$this->dataPersistor->get('catalog_product'); + $productId = $this->locator->getProduct()->getId(); + + if (empty($data[$productId][self::DATA_SOURCE_DEFAULT])) { + $data[$productId][self::DATA_SOURCE_DEFAULT] = []; + } + + $data[$productId] = array_replace_recursive( + $data[$productId][self::DATA_SOURCE_DEFAULT], + $persistentData + ); + + return $data; + } + /** * Get product type * @@ -548,7 +584,7 @@ class Eav extends AbstractModifier $meta = $this->customizePriceAttribute($attribute, $meta); break; case 'gallery': - // Gallery attribute is being handled by "Images And Videos Tab" + // Gallery attribute is being handled by "Images And Videos" section $meta = []; break; } diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php index 7b85bbbb8aaec682b3f9d8ee9efd36cfc4d70a90..b4147229b81d6be08e7757d3546175a94bece238 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/Modifier/General.php @@ -163,24 +163,18 @@ class General extends AbstractModifier protected function customizeStatusField(array $meta) { $switcherConfig = [ - 'arguments' => [ - 'data' => [ - 'config' => [ - 'dataType' => Form\Element\DataType\Number::NAME, - 'formElement' => Form\Element\Checkbox::NAME, - 'componentType' => Form\Field::NAME, - 'prefer' => 'toggle', - 'valueMap' => [ - 'true' => '1', - 'false' => '2' - ], - ], - ], + 'dataType' => Form\Element\DataType\Number::NAME, + 'formElement' => Form\Element\Checkbox::NAME, + 'componentType' => Form\Field::NAME, + 'prefer' => 'toggle', + 'valueMap' => [ + 'true' => '1', + 'false' => '2' ], ]; $path = $this->arrayManager->findPath(ProductAttributeInterface::CODE_STATUS, $meta, null, 'children'); - $meta = $this->arrayManager->merge($path, $meta, $switcherConfig); + $meta = $this->arrayManager->merge($path . static::META_CONFIG_PATH, $meta, $switcherConfig); return $meta; } @@ -203,7 +197,7 @@ class General extends AbstractModifier [ 'dataScope' => ProductAttributeInterface::CODE_WEIGHT, 'validation' => [ - 'validate-number' => true, + 'validate-zero-or-greater' => true ], 'additionalClasses' => 'admin__field-small', 'addafter' => $this->locator->getStore()->getConfig('general/locale/weight_unit'), @@ -220,44 +214,33 @@ class General extends AbstractModifier null, 'children' ); - $meta = $this->arrayManager->merge($containerPath, $meta, [ - 'arguments' => [ - 'data' => [ - 'config' => [ - 'component' => 'Magento_Ui/js/form/components/group', - ], - ], - ], + $meta = $this->arrayManager->merge($containerPath . static::META_CONFIG_PATH, $meta, [ + 'component' => 'Magento_Ui/js/form/components/group', ]); $hasWeightPath = $this->arrayManager->slicePath($weightPath, 0, -1) . '/' . ProductAttributeInterface::CODE_HAS_WEIGHT; $meta = $this->arrayManager->set( - $hasWeightPath, + $hasWeightPath . static::META_CONFIG_PATH, $meta, [ - 'arguments' => [ - 'data' => [ - 'config' => [ - 'dataType' => 'boolean', - 'formElement' => Form\Element\Select::NAME, - 'componentType' => Form\Field::NAME, - 'dataScope' => 'product_has_weight', - 'label' => '', - 'options' => [ - [ - 'label' => __('This item has weight'), - 'value' => 1 - ], - [ - 'label' => __('This item has no weight'), - 'value' => 0 - ], - ], - 'value' => (int)$this->locator->getProduct()->getTypeInstance()->hasWeight(), - ], + + 'dataType' => 'boolean', + 'formElement' => Form\Element\Select::NAME, + 'componentType' => Form\Field::NAME, + 'dataScope' => 'product_has_weight', + 'label' => '', + 'options' => [ + [ + 'label' => __('This item has weight'), + 'value' => 1 ], - ] + [ + 'label' => __('This item has no weight'), + 'value' => 0 + ], + ], + 'value' => (int)$this->locator->getProduct()->getTypeInstance()->hasWeight(), ] ); } @@ -340,39 +323,53 @@ class General extends AbstractModifier ProductAttributeInterface::CODE_SEO_FIELD_META_KEYWORD, ProductAttributeInterface::CODE_SEO_FIELD_META_DESCRIPTION, ]; + $textListeners = [ + ProductAttributeInterface::CODE_SEO_FIELD_META_KEYWORD, + ProductAttributeInterface::CODE_SEO_FIELD_META_DESCRIPTION + ]; + foreach ($listeners as $listener) { $listenerPath = $this->arrayManager->findPath($listener, $meta, null, 'children'); $importsConfig = [ - 'arguments' => [ - 'data' => [ - 'config' => [ - 'component' => 'Magento_Catalog/js/components/import-handler', - 'imports' => [ - 'handleChanges' => '${$.provider}:data.product.name', - ], - 'autoImportIfEmpty' => true, - 'allowImport' => $this->locator->getProduct()->getId() ? false : true, - ], - ], + 'mask' => $this->locator->getStore()->getConfig('catalog/fields_masks/' . $listener), + 'component' => 'Magento_Catalog/js/components/import-handler', + 'imports' => [ + 'handleNameChanges' => '${$.provider}:data.product.name', + 'handleDescriptionChanges' => '${$.provider}:data.product.description', + 'handleSkuChanges' => '${$.provider}:data.product.sku', + 'handleColorChanges' => '${$.provider}:data.product.color', + 'handleCountryChanges' => '${$.provider}:data.product.country_of_manufacture', + 'handleGenderChanges' => '${$.provider}:data.product.gender', + 'handleMaterialChanges' => '${$.provider}:data.product.material', + 'handleShortDescriptionChanges' => '${$.provider}:data.product.short_description', + 'handleSizeChanges' => '${$.provider}:data.product.size' ], ]; - $meta = $this->arrayManager->merge($listenerPath, $meta, $importsConfig); + if (!in_array($listener, $textListeners)) { + $importsConfig['elementTmpl'] = 'ui/form/element/input'; + } + + $meta = $this->arrayManager->merge($listenerPath . static::META_CONFIG_PATH, $meta, $importsConfig); } + $skuPath = $this->arrayManager->findPath(ProductAttributeInterface::CODE_SKU, $meta, null, 'children'); + $meta = $this->arrayManager->merge( + $skuPath . static::META_CONFIG_PATH, + $meta, + [ + 'autoImportIfEmpty' => true, + 'allowImport' => $this->locator->getProduct()->getId() ? false : true, + ] + ); + $namePath = $this->arrayManager->findPath(ProductAttributeInterface::CODE_NAME, $meta, null, 'children'); return $this->arrayManager->merge( - $namePath, + $namePath . static::META_CONFIG_PATH, $meta, [ - 'arguments' => [ - 'data' => [ - 'config' => [ - 'valueUpdate' => 'keyup' - ], - ], - ], + 'valueUpdate' => 'keyup' ] ); } diff --git a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/ProductDataProvider.php b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/ProductDataProvider.php index 294b8188ea0106522e6a64f36b3c2dfd19f36221..a390bb6e9a9d99a97fb4ec2933ab515e3ce9665c 100644 --- a/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/ProductDataProvider.php +++ b/app/code/Magento/Catalog/Ui/DataProvider/Product/Form/ProductDataProvider.php @@ -18,7 +18,7 @@ class ProductDataProvider extends AbstractDataProvider /** * @var PoolInterface */ - protected $pool; + private $pool; /** * @param string $name diff --git a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/options.phtml b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/options.phtml index 6cb4325dd8ada0df072bd59158b465e06455876e..82b70fb8c71a885e0bd91f426c17ba17478d1899 100644 --- a/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/options.phtml +++ b/app/code/Magento/Catalog/view/adminhtml/templates/catalog/product/attribute/options.phtml @@ -10,8 +10,8 @@ ?> <fieldset class="fieldset"> <legend class="legend"><span><?php /* @escapeNotVerified */ echo __('Manage Options (Values of Your Attribute)') ?></span></legend> - <div id="manage-options-panel"> - <table class="admin__control-table"> + <div id="manage-options-panel" data-index="attribute_options_select_container"> + <table class="admin__control-table" data-index="attribute_options_select"> <thead> <tr id="attribute-options-table"> <th class="col-draggable"></th> @@ -37,7 +37,7 @@ <tr> <th colspan="<?php /* @escapeNotVerified */ echo $storetotal; ?>" class="col-actions-add"> <?php if (!$block->getReadOnly() && !$block->canManageOptionDefaultOnly()):?> - <button id="add_new_option_button" title="<?php /* @escapeNotVerified */ echo __('Add Option'); ?>" + <button id="add_new_option_button" data-action="add_new_row" title="<?php /* @escapeNotVerified */ echo __('Add Option'); ?>" type="button" class="action- scalable add"> <span><?php /* @escapeNotVerified */ echo __('Add Option'); ?></span> </button> diff --git a/app/code/Magento/Catalog/view/adminhtml/web/js/components/import-handler.js b/app/code/Magento/Catalog/view/adminhtml/web/js/components/import-handler.js index 38608556a92064e5d80b639b59f4f122afb60edd..fd69874c318e21606361d503cc55ea900ad604cf 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/js/components/import-handler.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/js/components/import-handler.js @@ -4,26 +4,150 @@ */ define([ - 'Magento_Ui/js/form/element/abstract' -], function (Abstract) { + 'Magento_Ui/js/form/element/textarea' +], function (Textarea) { 'use strict'; - return Abstract.extend({ + return Textarea.extend({ defaults: { allowImport: true, autoImportIfEmpty: false, - nameValue: '', - valueUpdate: 'input' + values: { + 'name': '', + 'description': '', + 'sku': '', + 'color': '', + 'country_of_manufacture': '', + 'gender': '', + 'material': '', + 'short_description': '', + 'size': '' + }, + valueUpdate: 'input', + mask: '' }, /** - * Import value, if it's allowed + * Handle name value changes, if it's allowed + * + * @param {String} newValue + */ + handleNameChanges: function (newValue) { + this.values.name = newValue; + this.updateValue(); + }, + + /** + * Handle description value changes, if it's allowed + * + * @param {String} newValue + */ + handleDescriptionChanges: function (newValue) { + this.values.description = newValue; + this.updateValue(); + }, + + /** + * Handle sku value changes, if it's allowed + * + * @param {String} newValue + */ + handleSkuChanges: function (newValue) { + if (this.code !== 'sku') { + this.values.sku = newValue; + this.updateValue(); + } + }, + + /** + * Handle color value changes, if it's allowed + * + * @param {String} newValue */ - handleChanges: function (newValue) { - this.nameValue = newValue; + handleColorChanges: function (newValue) { + this.values.color = newValue; + this.updateValue(); + }, + + /** + * Handle country value changes, if it's allowed + * + * @param {String} newValue + */ + handleCountryChanges: function (newValue) { + this.values.country = newValue; + this.updateValue(); + }, + + /** + * Handle gender value changes, if it's allowed + * + * @param {String} newValue + */ + handleGenderChanges: function (newValue) { + this.values.gender = newValue; + this.updateValue(); + }, + + /** + * Handle material value changes, if it's allowed + * + * @param {String} newValue + */ + handleMaterialChanges: function (newValue) { + this.values.material = newValue; + this.updateValue(); + }, + + /** + * Handle short description value changes, if it's allowed + * + * @param {String} newValue + */ + handleShortDescriptionChanges: function (newValue) { + this.values['short_description'] = newValue; + this.updateValue(); + }, + + /** + * Handle size value changes, if it's allowed + * + * @param {String} newValue + */ + handleSizeChanges: function (newValue) { + this.values.size = newValue; + this.updateValue(); + }, + + /** + * Update field value, if it's allowed + */ + updateValue: function () { + var str = this.mask, + nonEmptyValueFlag = false, + placeholder, + property, + tmpElement; + + if (!this.allowImport) { + return; + } + + for (property in this.values) { + if (this.values.hasOwnProperty(property)) { + placeholder = ''; + placeholder = placeholder.concat('{{', property, '}}'); + str = str.replace(placeholder, this.values[property]); + nonEmptyValueFlag = nonEmptyValueFlag || !!this.values[property]; + } + } + // strip tags + tmpElement = document.createElement('div'); + tmpElement.innerHTML = str; + str = tmpElement.textContent || tmpElement.innerText || ''; - if (this.allowImport) { - this.value(newValue); + if (nonEmptyValueFlag) { + this.value(str); } }, @@ -53,7 +177,7 @@ define([ this.allowImport = true; if (this.autoImportIfEmpty) { - this.value(this.nameValue); + this.updateValue(); } } else { this.allowImport = false; diff --git a/app/code/Magento/Cms/Model/ResourceModel/Page/Grid/Collection.php b/app/code/Magento/Cms/Model/ResourceModel/Page/Grid/Collection.php index 4337c5457e1c1e570b338f3be37c5e74fb15232d..b1bcb33b69d7ecc42375e4f07f0af2933e4e41a0 100644 --- a/app/code/Magento/Cms/Model/ResourceModel/Page/Grid/Collection.php +++ b/app/code/Magento/Cms/Model/ResourceModel/Page/Grid/Collection.php @@ -5,9 +5,11 @@ */ namespace Magento\Cms\Model\ResourceModel\Page\Grid; +use Magento\Cms\Model\Page; use Magento\Framework\Api\Search\SearchResultInterface; use Magento\Framework\Api\Search\AggregationInterface; use Magento\Cms\Model\ResourceModel\Page\Collection as PageCollection; +use Magento\Framework\View\Element\UiComponent\DataProvider\Document; /** * Class Collection @@ -23,7 +25,7 @@ class Collection extends PageCollection implements SearchResultInterface /** * @var \Magento\Framework\View\Element\UiComponent\DataProvider\Document[] */ - private $loadedData; + private $loadedData = []; /** * @param \Magento\Framework\Data\Collection\EntityFactoryInterface $entityFactory @@ -151,16 +153,14 @@ class Collection extends PageCollection implements SearchResultInterface */ public function getItems() { - if (isset($this->loadedData)) { + if ($this->loadedData) { return $this->loadedData; } - /** @var \Magento\Cms\Model\Page $page */ - $page = $this->_entityFactory->create(\Magento\Cms\Model\Page::class); - /** Load every record separately to make sure the list of associated stores is available */ - /** @var \Magento\Framework\View\Element\UiComponent\DataProvider\Document $pageDocument */ + + /** @var Document $pageDocument */ foreach (parent::getItems() as $pageDocument) { $this->loadedData[$pageDocument->getId()] = $pageDocument->setData( - $page->load($pageDocument->getId())->getData() + $this->_entityFactory->create(Page::class)->load($pageDocument->getId())->getData() ); } diff --git a/app/code/Magento/Cms/Test/Unit/Model/ResourceModel/Page/Grid/CollectionTest.php b/app/code/Magento/Cms/Test/Unit/Model/ResourceModel/Page/Grid/CollectionTest.php new file mode 100644 index 0000000000000000000000000000000000000000..408c9c662b863e6440bd64d9ece1d8581239c601 --- /dev/null +++ b/app/code/Magento/Cms/Test/Unit/Model/ResourceModel/Page/Grid/CollectionTest.php @@ -0,0 +1,140 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +namespace Magento\Cms\Test\Unit\Model\ResourceModel\Page\Grid; + +use Magento\Cms\Model\ResourceModel\Page\Grid\Collection; +use Magento\Framework\Api\Search\AggregationInterface; +use Magento\Framework\Data\Collection\Db\FetchStrategyInterface; +use Magento\Framework\Data\Collection\EntityFactoryInterface; +use Magento\Framework\DB\Adapter\AdapterInterface; +use Magento\Framework\Event\ManagerInterface; +use Magento\Framework\Model\Entity\MetadataPool; +use Magento\Framework\Model\ResourceModel\Db\AbstractDb; +use Magento\Framework\TestFramework\Unit\Helper\ObjectManager; +use Magento\Store\Model\StoreManagerInterface; +use Psr\Log\LoggerInterface; +use Magento\Framework\DB\Select; + +/** + * Class CollectionTest + * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + */ +class CollectionTest extends \PHPUnit_Framework_TestCase +{ + /** + * @var EntityFactoryInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $entityFactoryMock; + + /** + * @var LoggerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $loggerMock; + + /** + * @var FetchStrategyInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $fetchStrategyMock; + + /** + * @var ManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $eventManagerMock; + + /** + * @var StoreManagerInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $storeManagerMock; + + /** + * @var MetadataPool|\PHPUnit_Framework_MockObject_MockObject + */ + protected $metadataPoolMock; + + /** + * @var AdapterInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $connectionMock; + + /** + * @var AbstractDb|\PHPUnit_Framework_MockObject_MockObject + */ + protected $resourceMock; + + /** + * @var AggregationInterface|\PHPUnit_Framework_MockObject_MockObject + */ + protected $aggregationsMock; + + /** + * @var Select + */ + protected $selectMock; + + /** + * @var Collection + */ + protected $model; + + protected function setUp() + { + $this->entityFactoryMock = $this->getMockBuilder(EntityFactoryInterface::class) + ->getMockForAbstractClass(); + $this->loggerMock = $this->getMockBuilder(LoggerInterface::class) + ->getMockForAbstractClass(); + $this->fetchStrategyMock = $this->getMockBuilder(FetchStrategyInterface::class) + ->getMockForAbstractClass(); + $this->eventManagerMock = $this->getMockBuilder(ManagerInterface::class) + ->getMockForAbstractClass(); + $this->storeManagerMock = $this->getMockBuilder(StoreManagerInterface::class) + ->getMockForAbstractClass(); + $this->metadataPoolMock = $this->getMockBuilder(MetadataPool::class) + ->disableOriginalConstructor() + ->getMock(); + $this->resourceMock = $this->getMockBuilder(AbstractDb::class) + ->disableOriginalConstructor() + ->getMock(); + $this->aggregationsMock = $this->getMockBuilder(AggregationInterface::class) + ->getMockForAbstractClass(); + $this->connectionMock = $this->getMockBuilder(AdapterInterface::class) + ->getMockForAbstractClass(); + $this->selectMock = $this->getMockBuilder(Select::class) + ->disableOriginalConstructor() + ->getMock(); + + $this->resourceMock->expects($this->any()) + ->method('getConnection') + ->willReturn($this->connectionMock); + $this->connectionMock->expects($this->once()) + ->method('select') + ->willReturn($this->selectMock); + + $this->model = (new ObjectManager($this))->getObject(Collection::class, [ + 'entityFactory' => $this->entityFactoryMock, + 'logger' => $this->loggerMock, + 'fetchStrategy' => $this->fetchStrategyMock, + 'eventManager' => $this->eventManagerMock, + 'storeManager' => $this->storeManagerMock, + 'metadataPool' => $this->metadataPoolMock, + 'mainTable' => null, + 'eventPrefix' => 'test_event_prefix', + 'eventObject' => 'test_event_object', + 'resourceModel' => null, + 'resource' => $this->resourceMock, + ]); + } + + public function testSetterGetter() + { + $this->model->setAggregations($this->aggregationsMock); + $this->assertInstanceOf(AggregationInterface::class, $this->model->getAggregations()); + } + + public function testSetSearchCriteria() + { + $this->assertEquals($this->model, $this->model->setSearchCriteria()); + } +} diff --git a/app/code/Magento/Config/Model/Config/Backend/Cache.php b/app/code/Magento/Config/Model/Config/Backend/Cache.php index 361cbcd25510c23a46c9e107a09c865b18d05be3..ba437c0f971b2ada295c37ce0e9871b218aa4c1a 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Cache.php +++ b/app/code/Magento/Config/Model/Config/Backend/Cache.php @@ -22,12 +22,13 @@ class Cache extends \Magento\Framework\App\Config\Value /** * Clean cache, value was changed * - * @return void + * @return $this */ public function afterSave() { if ($this->isValueChanged()) { $this->_cacheManager->clean($this->_cacheTags); } + return $this; } } diff --git a/app/code/Magento/Config/Model/Config/Backend/Datashare.php b/app/code/Magento/Config/Model/Config/Backend/Datashare.php index dff894cb559605e6f04937fc939f127e3a2ca1cf..bd0bfaa478abc5713d73a830126b64e6028bba1d 100644 --- a/app/code/Magento/Config/Model/Config/Backend/Datashare.php +++ b/app/code/Magento/Config/Model/Config/Backend/Datashare.php @@ -14,9 +14,10 @@ namespace Magento\Config\Model\Config\Backend; class Datashare extends \Magento\Framework\App\Config\Value { /** - * @return void + * @return $this */ public function afterSave() { + return $this; } } diff --git a/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Initialization/Helper/Plugin/Configurable.php b/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Initialization/Helper/Plugin/Configurable.php index bd8bea9f25a57386f3fbba84cb2ea1ddf0c49983..df7ceda95692d9f92df1c983619931f202845868 100644 --- a/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Initialization/Helper/Plugin/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Controller/Adminhtml/Product/Initialization/Helper/Plugin/Configurable.php @@ -129,6 +129,11 @@ class Configurable { $associatedProductIds = $this->request->getPost('associated_product_ids', []); $variationsMatrix = $this->getVariationMatrix(); + + if ($associatedProductIds || $variationsMatrix) { + $this->variationHandler->prepareAttributeSet($product); + } + if (!empty($variationsMatrix)) { $generatedProductIds = $this->variationHandler->generateSimpleProducts($product, $variationsMatrix); $associatedProductIds = array_merge($associatedProductIds, $generatedProductIds); diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php index e2a2cdf527fd5a337c85fa5b72822f55d2e68829..2fc849be10f10988356b977298168173a18a4f7b 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php @@ -508,6 +508,7 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType $collection = $this->getUsedProductCollection($product) ->addAttributeToSelect('name') ->addAttributeToSelect('price') + ->addAttributeToSelect('weight') // ->addAttributeToSelect('msrp') // ->addAttributeToSelect('media_gallery') ->addFilterByRequiredOptions() diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/VariationHandler.php b/app/code/Magento/ConfigurableProduct/Model/Product/VariationHandler.php index 86d5aa130637b59f9d4ad431eda589679aebda31..9a40931c05d024f4f25cf793b30f1b4d30bb6019 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/VariationHandler.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/VariationHandler.php @@ -66,7 +66,6 @@ class VariationHandler */ public function generateSimpleProducts($parentProduct, $productsData) { - $this->prepareAttributeSetToBeBaseForNewVariations($parentProduct); $generatedProductIds = []; $productsData = $this->duplicateImagesForVariations($productsData); foreach ($productsData as $simpleProductData) { @@ -93,11 +92,22 @@ class VariationHandler /** * Prepare attribute set comprising all selected configurable attributes * + * @deprecated since 2.1.0 * @param \Magento\Catalog\Model\Product $product - * * @return void */ protected function prepareAttributeSetToBeBaseForNewVariations(\Magento\Catalog\Model\Product $product) + { + $this->prepareAttributeSet($product); + } + + /** + * Prepare attribute set comprising all selected configurable attributes + * + * @param \Magento\Catalog\Model\Product $product + * @return void + */ + public function prepareAttributeSet(\Magento\Catalog\Model\Product $product) { $attributes = $this->configurableProduct->getUsedProductAttributes($product); $attributeSetId = $product->getNewVariationsAttributeSetId(); @@ -156,7 +166,8 @@ class VariationHandler $product->setData($attribute->getAttributeCode(), $parentProduct->getData($attribute->getAttributeCode())); } - $postData['stock_data'] = $parentProduct->getStockData(); + $keysFilter = ['item_id', 'product_id', 'stock_id', 'type_id', 'website_id']; + $postData['stock_data'] = array_diff_key((array)$parentProduct->getStockData(), array_flip($keysFilter)); $postData['stock_data']['manage_stock'] = $postData['quantity_and_stock_status']['qty'] === '' ? 0 : 1; if (!isset($postData['stock_data']['is_in_stock'])) { $stockStatus = $parentProduct->getQuantityAndStockStatus(); diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/ConfigurableTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/ConfigurableTest.php index 055cc18ffbd02409698e97c200c6c6f4d1a3b863..f8b42171dd674cd09c17c3949fa20805fb35c871 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/ConfigurableTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Controller/Adminhtml/Product/Initialization/Helper/Plugin/ConfigurableTest.php @@ -57,7 +57,7 @@ class ConfigurableTest extends \PHPUnit_Framework_TestCase { $this->variationHandler = $this->getMockBuilder(VariationHandler::class) ->disableOriginalConstructor() - ->setMethods(['generateSimpleProducts']) + ->setMethods(['generateSimpleProducts', 'prepareAttributeSet']) ->getMock(); $this->request = $this->getMockBuilder(Http::class) @@ -183,6 +183,10 @@ class ConfigurableTest extends \PHPUnit_Framework_TestCase ->method('setConfigurableProductOptions') ->with($attributes); + $this->variationHandler->expects(static::once()) + ->method('prepareAttributeSet') + ->with($this->product); + $this->variationHandler->expects(static::once()) ->method('generateSimpleProducts') ->with($this->product, $variationMatrix) @@ -248,6 +252,9 @@ class ConfigurableTest extends \PHPUnit_Framework_TestCase ->method('setConfigurableProductOptions') ->with($attributes); + $this->variationHandler->expects(static::never()) + ->method('prepareAttributeSet'); + $this->variationHandler->expects(static::never()) ->method('generateSimpleProducts'); @@ -277,6 +284,8 @@ class ConfigurableTest extends \PHPUnit_Framework_TestCase ->method('getExtensionAttributes'); $this->request->expects(static::once()) ->method('getPost'); + $this->variationHandler->expects(static::never()) + ->method('prepareAttributeSet'); $this->variationHandler->expects(static::never()) ->method('generateSimpleProducts'); $this->plugin->afterInitialize($this->subject, $this->product); @@ -294,6 +303,8 @@ class ConfigurableTest extends \PHPUnit_Framework_TestCase ->method('getExtensionAttributes'); $this->request->expects(static::once()) ->method('getPost'); + $this->variationHandler->expects(static::never()) + ->method('prepareAttributeSet'); $this->variationHandler->expects(static::never()) ->method('generateSimpleProducts'); $this->plugin->afterInitialize($this->subject, $this->product); diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/VariationHandlerTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/VariationHandlerTest.php index 85f4154a1b81341797734603ac4efae95ae59013..7efc0794f11b80edb6893871b727298672142f6a 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/VariationHandlerTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/VariationHandlerTest.php @@ -18,27 +18,27 @@ class VariationHandlerTest extends \PHPUnit_Framework_TestCase /** * @var VariationHandler */ - protected $_model; + protected $model; /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Eav\Model\Entity\Attribute\SetFactory */ - protected $_attributeSetFactory; + protected $attributeSetFactory; /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Eav\Model\EntityFactory */ - protected $_entityFactoryMock; + protected $entityFactoryMock; /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Catalog\Model\ProductFactory */ - protected $_productFactoryMock; + protected $productFactoryMock; /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\CatalogInventory\Api\StockConfigurationInterface */ - protected $_stockConfiguration; + protected $stockConfiguration; /** * @var \PHPUnit_Framework_MockObject_MockObject|\Magento\ConfigurableProduct\Model\Product\Type\Configurable @@ -48,41 +48,41 @@ class VariationHandlerTest extends \PHPUnit_Framework_TestCase /** * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */ - protected $_objectHelper; + protected $objectHelper; /** * @var \Magento\Catalog\Model\Product|\PHPUnit_Framework_MockObject_MockObject */ - private $_product; + private $product; /** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ protected function setUp() { - $this->_objectHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->_productFactoryMock = $this->getMock( + $this->objectHelper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); + $this->productFactoryMock = $this->getMock( 'Magento\Catalog\Model\ProductFactory', ['create'], [], '', false ); - $this->_entityFactoryMock = $this->getMock( + $this->entityFactoryMock = $this->getMock( 'Magento\Eav\Model\EntityFactory', ['create'], [], '', false ); - $this->_attributeSetFactory = $this->getMock( + $this->attributeSetFactory = $this->getMock( 'Magento\Eav\Model\Entity\Attribute\SetFactory', ['create'], [], '', false ); - $this->_stockConfiguration = $this->getMock( + $this->stockConfiguration = $this->getMock( 'Magento\CatalogInventory\Api\StockConfigurationInterface', [], [], @@ -97,20 +97,68 @@ class VariationHandlerTest extends \PHPUnit_Framework_TestCase false ); - $this->_product = $this->getMock('Magento\Catalog\Model\Product', ['getMediaGallery'], [], '', false); + $this->product = $this->getMock('Magento\Catalog\Model\Product', ['getMediaGallery'], [], '', false); - $this->_model = $this->_objectHelper->getObject( + $this->model = $this->objectHelper->getObject( 'Magento\ConfigurableProduct\Model\Product\VariationHandler', [ - 'productFactory' => $this->_productFactoryMock, - 'entityFactory' => $this->_entityFactoryMock, - 'attributeSetFactory' => $this->_attributeSetFactory, - 'stockConfiguration' => $this->_stockConfiguration, + 'productFactory' => $this->productFactoryMock, + 'entityFactory' => $this->entityFactoryMock, + 'attributeSetFactory' => $this->attributeSetFactory, + 'stockConfiguration' => $this->stockConfiguration, 'configurableProduct' => $this->configurableProduct ] ); } + public function testPrepareAttributeSet() + { + + $productMock = $this->getMockBuilder('\Magento\Catalog\Model\Product') + ->setMethods(['getNewVariationsAttributeSetId']) + ->disableOriginalConstructor() + ->getMock(); + $attributeMock = $this->getMockBuilder('\Magento\Eav\Model\Entity\Attribute') + ->setMethods(['isInSet', 'setAttributeSetId', 'setAttributeGroupId', 'save']) + ->disableOriginalConstructor() + ->getMock(); + $attributeSetMock = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\Set') + ->setMethods(['load', 'addSetInfo', 'getDefaultGroupId']) + ->disableOriginalConstructor() + ->getMock(); + $eavEntityMock = $this->getMockBuilder('\Magento\Eav\Model\Entity') + ->setMethods(['setType', 'getTypeId']) + ->disableOriginalConstructor() + ->getMock(); + + $productMock->expects($this->once()) + ->method('getNewVariationsAttributeSetId') + ->willReturn('new_attr_set_id'); + $this->configurableProduct->expects($this->once()) + ->method('getUsedProductAttributes') + ->with($productMock) + ->willReturn([$attributeMock]); + $this->attributeSetFactory->expects($this->once())->method('create')->willReturn($attributeSetMock); + $attributeSetMock->expects($this->once())->method('load')->with('new_attr_set_id')->willReturnSelf(); + $this->entityFactoryMock->expects($this->once())->method('create')->willReturn($eavEntityMock); + $eavEntityMock->expects($this->once())->method('setType')->with('catalog_product')->willReturnSelf(); + $eavEntityMock->expects($this->once())->method('getTypeId')->willReturn('type_id'); + $attributeSetMock->expects($this->once())->method('addSetInfo')->with('type_id', [$attributeMock]); + $attributeMock->expects($this->once())->method('isInSet')->with('new_attr_set_id')->willReturn(false); + $attributeMock->expects($this->once())->method('setAttributeSetId')->with('new_attr_set_id')->willReturnSelf(); + $attributeSetMock->expects($this->once()) + ->method('getDefaultGroupId') + ->with('new_attr_set_id') + ->willReturn('default_group_id'); + $attributeMock->expects($this->once()) + ->method('setAttributeGroupId') + ->with('default_group_id') + ->willReturnSelf(); + $attributeMock->expects($this->once())->method('save')->willReturnSelf(); + + $this->model->prepareAttributeSet($productMock); + } + /** * @SuppressWarnings(PHPMD.ExcessiveMethodLength) */ @@ -169,18 +217,6 @@ class VariationHandlerTest extends \PHPUnit_Framework_TestCase ) ->disableOriginalConstructor() ->getMock(); - $attributeMock = $this->getMockBuilder('\Magento\Eav\Model\Entity\Attribute') - ->setMethods(['isInSet', 'setAttributeSetId', 'setAttributeGroupId', 'save']) - ->disableOriginalConstructor() - ->getMock(); - $attributeSetMock = $this->getMockBuilder('Magento\Eav\Model\Entity\Attribute\Set') - ->setMethods(['load', 'addSetInfo', 'getDefaultGroupId']) - ->disableOriginalConstructor() - ->getMock(); - $eavEntityMock = $this->getMockBuilder('\Magento\Eav\Model\Entity') - ->setMethods(['setType', 'getTypeId']) - ->disableOriginalConstructor() - ->getMock(); $productTypeMock = $this->getMockBuilder('Magento\Catalog\Model\Product\Type') ->setMethods(['getSetAttributes']) ->disableOriginalConstructor() @@ -194,29 +230,10 @@ class VariationHandlerTest extends \PHPUnit_Framework_TestCase ->disableOriginalConstructor() ->getMock(); - $this->configurableProduct->expects($this->once())->method('getUsedProductAttributes') - ->willReturn([$attributeMock]); - $parentProductMock->expects($this->any()) + $parentProductMock->expects($this->once()) ->method('getNewVariationsAttributeSetId') ->willReturn('new_attr_set_id'); - $this->_attributeSetFactory->expects($this->once())->method('create')->willReturn($attributeSetMock); - $attributeSetMock->expects($this->once())->method('load')->with('new_attr_set_id')->willReturnSelf(); - $this->_entityFactoryMock->expects($this->once())->method('create')->willReturn($eavEntityMock); - $eavEntityMock->expects($this->once())->method('setType')->with('catalog_product')->willReturnSelf(); - $eavEntityMock->expects($this->once())->method('getTypeId')->willReturn('type_id'); - $attributeSetMock->expects($this->once())->method('addSetInfo')->with('type_id', [$attributeMock]); - $attributeMock->expects($this->once())->method('isInSet')->with('new_attr_set_id')->willReturn(false); - $attributeMock->expects($this->once())->method('setAttributeSetId')->with('new_attr_set_id')->willReturnSelf(); - $attributeSetMock->expects($this->once()) - ->method('getDefaultGroupId') - ->with('new_attr_set_id') - ->willReturn('default_group_id'); - $attributeMock->expects($this->once()) - ->method('setAttributeGroupId') - ->with('default_group_id') - ->willReturnSelf(); - $attributeMock->expects($this->once())->method('save')->willReturnSelf(); - $this->_productFactoryMock->expects($this->once())->method('create')->willReturn($newSimpleProductMock); + $this->productFactoryMock->expects($this->once())->method('create')->willReturn($newSimpleProductMock); $newSimpleProductMock->expects($this->once())->method('setStoreId')->with(0)->willReturnSelf(); $newSimpleProductMock->expects($this->once())->method('setTypeId')->with('simple')->willReturnSelf(); $newSimpleProductMock->expects($this->once()) @@ -238,7 +255,7 @@ class VariationHandlerTest extends \PHPUnit_Framework_TestCase ->method('getQuantityAndStockStatus') ->willReturn(['is_in_stock' => 1]); $newSimpleProductMock->expects($this->once())->method('getStoreId')->willReturn('store_id'); - $this->_stockConfiguration->expects($this->once()) + $this->stockConfiguration->expects($this->once()) ->method('getManageStock') ->with('store_id') ->willReturn(1); @@ -249,41 +266,41 @@ class VariationHandlerTest extends \PHPUnit_Framework_TestCase $newSimpleProductMock->expects($this->once())->method('save')->willReturnSelf(); $newSimpleProductMock->expects($this->once())->method('getId')->willReturn('product_id'); - $this->assertEquals(['product_id'], $this->_model->generateSimpleProducts($parentProductMock, $productsData)); + $this->assertEquals(['product_id'], $this->model->generateSimpleProducts($parentProductMock, $productsData)); } public function testProcessMediaGalleryWithImagesAndGallery() { - $this->_product->expects($this->atLeastOnce())->method('getMediaGallery')->with('images')->willReturn([]); + $this->product->expects($this->atLeastOnce())->method('getMediaGallery')->with('images')->willReturn([]); $productData['image'] = 'test'; $productData['media_gallery']['images'] = [ [ 'file' => 'test', ], ]; - $result = $this->_model->processMediaGallery($this->_product, $productData); + $result = $this->model->processMediaGallery($this->product, $productData); $this->assertEquals($productData, $result); } public function testProcessMediaGalleryIfImageIsEmptyButProductMediaGalleryIsNotEmpty() { - $this->_product->expects($this->atLeastOnce())->method('getMediaGallery')->with('images')->willReturn([]); + $this->product->expects($this->atLeastOnce())->method('getMediaGallery')->with('images')->willReturn([]); $productData['image'] = false; $productData['media_gallery']['images'] = [ [ 'name' => 'test', ], ]; - $result = $this->_model->processMediaGallery($this->_product, $productData); + $result = $this->model->processMediaGallery($this->product, $productData); $this->assertEquals($productData, $result); } public function testProcessMediaGalleryIfProductDataHasNoImagesAndGallery() { - $this->_product->expects($this->once())->method('getMediaGallery')->with('images')->willReturn([]); + $this->product->expects($this->once())->method('getMediaGallery')->with('images')->willReturn([]); $productData['image'] = false; $productData['media_gallery']['images'] = false; - $result = $this->_model->processMediaGallery($this->_product, $productData); + $result = $this->model->processMediaGallery($this->product, $productData); $this->assertEquals($productData, $result); } @@ -294,7 +311,7 @@ class VariationHandlerTest extends \PHPUnit_Framework_TestCase */ public function testProcessMediaGalleryForFillingGallery($productData, $expected) { - $this->assertEquals($expected, $this->_model->processMediaGallery($this->_product, $productData)); + $this->assertEquals($expected, $this->model->processMediaGallery($this->product, $productData)); } /** diff --git a/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurableAttributeSetHandler.php b/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurableAttributeSetHandler.php index ce7524a783e9649fda851b7ec0b18e3ae2f13f6f..5832c18744b661712a040b2f9f7e98490bdb21e8 100644 --- a/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurableAttributeSetHandler.php +++ b/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurableAttributeSetHandler.php @@ -199,6 +199,7 @@ class ConfigurableAttributeSetHandler extends AbstractModifier 'formElement' => Form\Element\Input::NAME, 'componentType' => Form\Field::NAME, 'dataScope' => 'configurableNewAttributeSetName', + 'additionalClasses' => 'new-attribute-set-name', 'label' => __('New Attribute Set Name'), 'sortOrder' => 40, 'validation' => ['required-entry' => true], diff --git a/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurablePanel.php b/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurablePanel.php index 5810eefe9007cd14f4e83ec34fba84df2e5b9c95..fb2161d3c64cb1093d82487f6219a9cfd81a5d0a 100644 --- a/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurablePanel.php +++ b/app/code/Magento/ConfigurableProduct/Ui/DataProvider/Product/Form/Modifier/ConfigurablePanel.php @@ -129,7 +129,7 @@ class ConfigurablePanel extends AbstractModifier 'config' => [ 'componentType' => Modal::NAME, 'dataScope' => '', - 'provider' => $this->dataSourceName, + 'provider' => static::FORM_NAME . '.product_form_data_source', 'options' => [ 'title' => __('Select Associated Product'), 'buttons' => [ @@ -138,9 +138,7 @@ class ConfigurablePanel extends AbstractModifier 'class' => 'action-primary', 'actions' => [ [ - 'targetName' => 'ns= ' . $this->associatedListingPrefix - . static::ASSOCIATED_PRODUCT_LISTING - . ', index=' . static::ASSOCIATED_PRODUCT_LISTING, + 'targetName' => 'index=' . static::ASSOCIATED_PRODUCT_LISTING, 'actionName' => 'save' ], 'closeModal' @@ -227,6 +225,10 @@ class ConfigurablePanel extends AbstractModifier . 'configurable_associated_product_listing.product_columns.ids', 'modalWithGrid' => 'ns=' . $this->formName . ', index=' . static::ASSOCIATED_PRODUCT_MODAL, + 'productsFilters' => $this->associatedListingPrefix + . 'configurable_associated_product_listing' + . '.' . $this->associatedListingPrefix + . 'configurable_associated_product_listing.listing_top.listing_filters', ], ], ], @@ -292,13 +294,12 @@ class ConfigurablePanel extends AbstractModifier 'displayAsLink' => true, 'actions' => [ [ - 'targetName' => 'ns=' . $this->formName . ', index=' + 'targetName' => 'ns=' . static::FORM_NAME . ', index=' . static::ASSOCIATED_PRODUCT_MODAL, 'actionName' => 'openModal', ], [ - 'targetName' => 'ns=' . $this->associatedListingPrefix - . static::ASSOCIATED_PRODUCT_LISTING + 'targetName' => 'ns=' . static::ASSOCIATED_PRODUCT_LISTING . ', index=' . static::ASSOCIATED_PRODUCT_LISTING, 'actionName' => 'showGridAssignProduct', ], @@ -325,13 +326,13 @@ class ConfigurablePanel extends AbstractModifier 'actions' => [ [ 'targetName' => - $this->dataScopeName . '.configurableModal', + 'product_form.product_form.configurableModal', 'actionName' => 'trigger', 'params' => ['active', true], ], [ 'targetName' => - $this->dataScopeName . '.configurableModal', + 'product_form.product_form.configurableModal', 'actionName' => 'openModal', ], ], @@ -369,7 +370,7 @@ class ConfigurablePanel extends AbstractModifier 'isEmpty' => true, 'itemTemplate' => 'record', 'dataScope' => 'data', - 'dataProviderFromGrid' => $this->associatedListingPrefix . static::ASSOCIATED_PRODUCT_LISTING, + 'dataProviderFromGrid' => static::ASSOCIATED_PRODUCT_LISTING, 'dataProviderChangeFromGrid' => 'change_product', 'dataProviderFromWizard' => 'variations', 'map' => [ @@ -394,10 +395,9 @@ class ConfigurablePanel extends AbstractModifier 'sortOrder' => 20, 'columnsHeader' => false, 'columnsHeaderAfterRender' => true, - 'modalWithGrid' => 'ns=' . $this->formName . ', index=' + 'modalWithGrid' => 'ns=' . static::FORM_NAME . ', index=' . static::ASSOCIATED_PRODUCT_MODAL, - 'gridWithProducts' => 'ns=' . $this->associatedListingPrefix - . static::ASSOCIATED_PRODUCT_LISTING + 'gridWithProducts' => 'ns=' . static::ASSOCIATED_PRODUCT_LISTING . ', index=' . static::ASSOCIATED_PRODUCT_LISTING, ], ], @@ -439,10 +439,6 @@ class ConfigurablePanel extends AbstractModifier 'elementTmpl' => 'Magento_ConfigurableProduct/components/file-uploader', 'fileInputName' => 'image', 'isMultipleFiles' => false, - 'imports' => [ - 'thumbnailUrl' => '${$.provider}:${$.parentScope}.thumbnail_image', - 'thumbnail' => '${$.provider}:${$.parentScope}.thumbnail' - ], 'uploaderConfig' => [ 'url' => $this->urlBuilder->addSessionParam()->getUrl( 'catalog/product_gallery/upload' diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/attributes_values.phtml b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/attributes_values.phtml index 0dfcf167bda4d1061b690d9469f1b754fa7b550a..a684ccef60f15e1ffb38b8c5a5556ea653fe6edf 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/attributes_values.phtml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/attributes_values.phtml @@ -9,9 +9,13 @@ /* @var $block \Magento\ConfigurableProduct\Block\Adminhtml\Product\Steps\AttributeValues */ ?> <div data-bind="scope: '<?= /* @noEscape */ $block->getComponentName()?>'"> - <h2 class="steps-wizard-title"><?= /* @noEscape */ __('Step 2: Attribute Values') ?></h2> + <h2 class="steps-wizard-title"><?php echo $block->escapeHtml( + __('Step 2: Attribute Values') + ); ?></h2> <div class="steps-wizard-info"> - <span><?= $block->escapeHtml(__('Select from the following attribute values for this product. Each unique combination of values creates a unique product SKU.')) ?></span> + <span><?php echo $block->escapeHtml( + __('Select values from each attribute to include in this product. Each unique combination of values creates a unigue product SKU.') + );?></span> </div> <div data-bind="foreach: attributes, sortableList: attributes"> @@ -25,7 +29,9 @@ <div class="attribute-entity-title" data-bind="text: label"></div> <div class="attribute-options-block"> (<span class="attribute-length" data-bind="text: $data.options().length"></span> - <?= /* @noEscape */ __('Options') ?>) + <?php echo $block->escapeHtml( + __('Options') + ); ?>) </div> </div> @@ -34,19 +40,25 @@ class="action-select-all action-tertiary" data-bind="click: $parent.selectAllAttributes" title="<?= $block->escapeHtml(__('Select All')) ?>"> - <span><?= /* @noEscape */ __('Select All') ?></span> + <span><?php echo $block->escapeHtml( + __('Select All') + ); ?></span> </button> <button type="button" class="action-deselect-all action-tertiary" data-bind="click: $parent.deSelectAllAttributes" title="<?= $block->escapeHtml(__('Deselect All')) ?>"> - <span><?= /* @noEscape */ __('Deselect All') ?></span> + <span><?php echo $block->escapeHtml( + __('Deselect All') + ); ?></span> </button> <button type="button" class="action-remove-all action-tertiary" data-bind="click: $parent.removeAttribute.bind($parent)" title="<?= $block->escapeHtml(__('Remove Attribute')) ?>"> - <span><?= /* @noEscape */ __('Remove Attribute') ?></span> + <span><?php echo $block->escapeHtml( + __('Remove Attribute') + ); ?></span> </button> </div> </div> @@ -74,14 +86,18 @@ title="<?= $block->escapeHtml(__('Save Option')) ?>" data-action="save" data-bind="click: $parents[1].saveOption.bind($parent)"> - <span><?= /* @noEscape */ __('Save Option') ?></span> + <span><?php echo $block->escapeHtml( + __('Save Option') + ); ?></span> </button> <button type="button" class="action-remove" title="<?= $block->escapeHtml(__('Remove Option')) ?>" data-action="remove" data-bind="click: $parents[1].removeOption.bind($parent)"> - <span><?= /* @noEscape */ __('Remove Option') ?></span> + <span><?php echo $block->escapeHtml( + _('Remove Option') + ); ?></span> </button> </div> </li> @@ -90,8 +106,10 @@ <button class="action-create-new action-tertiary" type="button" data-action="addOption" - data-bind="click: $parent.createOption"> - <span><?= /* @escapeNotVerified */ __('Create New Value') ?></span> + data-bind="click: $parent.createOption, visible: canCreateOption"> + <span><?php echo $block->escapeHtml( + __('Create New Value') + ); ?></span> </button> </div> </div> diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/bulk.phtml b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/bulk.phtml index c3e410ac833ddff6cd933100526a9c6caeeb367d..24bfcabcacea23446cc716f8f2c72e6344f84fd5 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/bulk.phtml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/bulk.phtml @@ -10,547 +10,592 @@ ?> <div data-bind="scope: '<?= /* @noEscape */ $block->getComponentName()?>'" data-role="bulk-step"> - <h2 class="steps-wizard-title"><?= /* @noEscape */ __('Step 3: Bulk Images, Price and Quantity') ?></h2> + <h2 class="steps-wizard-title"><?php echo $block->escapeHtml(__('Step 3: Bulk Images, Price and Quantity')); ?></h2> <div class="steps-wizard-info"> - <?= /* @noEscape */ __('Based on your selections <span class="new-products-count" data-bind="text:countVariations"></span> - new products will be created. Use this step to customize images and price for your new products.') ?> + <?php /* @escapeNotVerified */ echo __('Based on your selections %1 new products will be created. Use this step to customize images and price for your new products.', '<span class="new-products-count" data-bind="text:countVariations"></span>') ?> </div> <div data-bind="with: sections().images" class="steps-wizard-section"> <div data-role="section"> - <div class="steps-wizard-section-title"> - <span><?= /* @noEscape */ __('Images') ?></span> - </div> + <div class="steps-wizard-section-title"> + <span><?php echo $block->escapeHtml( + __('Images') + ); ?></span> + </div> - <ul class="steps-wizard-section-list"> - <li> - <div class="admin__field admin__field-option"> - <input type="radio" - id="apply-single-set-radio" - class="admin__control-radio" - value="single" - data-bind="checked:type"> - <label for="apply-single-set-radio" class="admin__field-label"> - <span><?= /* @noEscape */ __('Apply single set of images to all SKUs') ?></span> - </label> - </div> - </li> - <li> - <div class="admin__field admin__field-option"> - <input type="radio" - id="apply-unique-images-radio" - class="admin__control-radio" - value="each" - data-bind="checked:type"> - <label for="apply-unique-images-radio" class="admin__field-label"> - <span><?= /* @noEscape */ __('Apply unique images by attribute to each SKU') ?></span> - </label> - </div> - </li> - <li> - <div class="admin__field admin__field-option"> - <input type="radio" - id="skip-images-uploading-radio" - class="admin__control-radio" - value="none" - checked - data-bind="checked:type"> - <label for="skip-images-uploading-radio" class="admin__field-label"> - <span><?= /* @noEscape */ __('Skip image uploading at this time') ?></span> - </label> - </div> - </li> - </ul> - - <div data-role="step-gallery-single" - class="attribute-image-selector" - data-bind="visible: type() == 'single'"> - <div data-role="gallery" - class="gallery" - data-images="[]" - data-types="<?php echo $block->escapeHtml( - $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($block->getImageTypes()) - ) ?>" - > - <div class="image image-placeholder"> - <div data-role="uploader" class="uploader"> - <div class="image-browse"> - <span><?= /* @noEscape */ __('Browse Files...') ?></span> - <input type="file" - id="" - name="image" - class="admin__control-file" - multiple="multiple" - data-url="<?= /* @noEscape */ $block->getUrl('catalog/product_gallery/upload') ?>" /> - </div> + <ul class="steps-wizard-section-list"> + <li> + <div class="admin__field admin__field-option"> + <input type="radio" + id="apply-single-set-radio" + class="admin__control-radio" + value="single" + data-bind="checked:type"> + <label for="apply-single-set-radio" class="admin__field-label"> + <span><?php echo $block->escapeHtml( + __('Apply single set of images to all SKUs') + ); ?></span> + </label> </div> - <div class="product-image-wrapper"> - <p class="image-placeholder-text"><?= /* @noEscape */ __('Browse to find or drag image here') ?></p> + </li> + <li> + <div class="admin__field admin__field-option"> + <input type="radio" + id="apply-unique-images-radio" + class="admin__control-radio" + value="each" + data-bind="checked:type"> + <label for="apply-unique-images-radio" class="admin__field-label"> + <span><?php echo $block->escapeHtml(__('Apply unique images by attribute to each SKU')) ?></span> + </label> </div> - </div> - - <?php foreach ($block->getImageTypes() as $typeData): - ?> - <input name="<?php echo $block->escapeHtml($typeData['name']) ?>" - class="image-<?php echo $block->escapeHtml($typeData['code']) ?>" - type="hidden" - value="<?php echo $block->escapeHtml($typeData['value']) ?>"/> - <?php - endforeach; - ?> + </li> + <li> + <div class="admin__field admin__field-option"> + <input type="radio" + id="skip-images-uploading-radio" + class="admin__control-radio" + value="none" + checked + data-bind="checked:type"> + <label for="skip-images-uploading-radio" class="admin__field-label"> + <span><?php echo $block->escapeHtml(__('Skip image uploading at this time')) ?></span> + </label> + </div> + </li> + </ul> - <script data-template="uploader" type="text/x-magento-template"> - <div id="<%- data.id %>" class="file-row"> - <span class="file-info"><%- data.name %> (<%- data.size %>)</span> - <div class="progressbar-container"> - <div class="progressbar upload-progress" style="width: 0%;"></div> + <div data-role="step-gallery-single" + class="attribute-image-selector" + data-bind="visible: type() == 'single'"> + <div data-role="gallery" + class="gallery" + data-images="[]" + data-types="<?php echo $block->escapeHtml( + $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($block->getImageTypes()) + ) ?>" + > + <div class="image image-placeholder"> + <div data-role="uploader" class="uploader"> + <div class="image-browse"> + <span><?php echo $block->escapeHtml(__('Browse Files...')) ?></span> + <input type="file" + id="" + name="image" + class="admin__control-file" + multiple="multiple" + data-url="<?= /* @noEscape */ $block->getUrl('catalog/product_gallery/upload') ?>" /> + </div> </div> - <div class="spinner"> - <span></span><span></span><span></span><span></span> - <span></span><span></span><span></span><span></span> + <div class="product-image-wrapper"> + <p class="image-placeholder-text"><?php echo $block->escapeHtml(__('Browse to find or drag image here')) ?></p> </div> </div> - </script> - - <script data-template="gallery-content" type="text/x-magento-template"> - <div class="image item <% if (data.disabled == 1) { %>hidden-for-front<% } %>" - data-role="image"> - <input type="hidden" - name="product[media_gallery][images][<%- data.file_id %>][position]" - value="<%- data.position %>"/> - <input type="hidden" - name="product[media_gallery][images][<%- data.file_id %>][file]" - value="<%- data.file %>"/> - <input type="hidden" - name="product[media_gallery][images][<%- data.file_id %>][value_id]" - value="<%- data.value_id %>"/> - <input type="hidden" - name="product[media_gallery][images][<%- data.file_id %>][label]" - value="<%- data.label %>"/> - <input type="hidden" - name="product[media_gallery][images][<%- data.file_id %>][disabled]" - value="<%- data.disabled %>"/> - <input type="hidden" - name="product[media_gallery][images][<%- data.file_id %>][removed]"/> - <div class="product-image-wrapper"> - <img class="product-image" data-role="image-element" src="<%- data.url %>" alt="<%- data.label %>"/> - <div class="actions"> - <button type="button" - class="action-remove" - data-role="delete-button" - title="<?= $block->escapeHtml(__('Remove image')) ?>"> - <span><?= /* @noEscape */ __('Remove image') ?></span> - </button> - <div class="draggable-handle"></div> + + <?php foreach ($block->getImageTypes() as $typeData): + ?> + <input name="<?php echo $block->escapeHtml($typeData['name']) ?>" + class="image-<?php echo $block->escapeHtml($typeData['code']) ?>" + type="hidden" + value="<?php echo $block->escapeHtml($typeData['value']) ?>"/> + <?php + endforeach; + ?> + + <script data-template="uploader" type="text/x-magento-template"> + <div id="<%- data.id %>" class="file-row"> + <span class="file-info"><%- data.name %> (<%- data.size %>)</span> + <div class="progressbar-container"> + <div class="progressbar upload-progress" style="width: 0%;"></div> </div> - <div class="image-fade"><span><?= /* @noEscape */ __('Hidden') ?></span></div> - </div> - <div class="item-description"> - <div class="item-title" data-role="img-title"><%- data.label %></div> - <div class="item-size"> - <span data-role="image-dimens"></span>, <span data-role="image-size"><%- data.sizeLabel %></span> + <div class="spinner"> + <span></span><span></span><span></span><span></span> + <span></span><span></span><span></span><span></span> </div> </div> - <ul class="item-roles" data-role="roles-labels"> - <?php - foreach ($block->getMediaAttributes() as $attribute): - ?> - <li data-role-code="<?php echo $block->escapeHtml( - $attribute->getAttributeCode() - ) ?>" class="item-role item-role-<?php echo $block->escapeHtml( - $attribute->getAttributeCode() - ) ?>"> - <?php /* @noEscape */ echo $attribute->getFrontendLabel() ?> - </li> + </script> + + <script data-template="gallery-content" type="text/x-magento-template"> + <div class="image item <% if (data.disabled == 1) { %>hidden-for-front<% } %>" + data-role="image"> + <input type="hidden" + name="product[media_gallery][images][<%- data.file_id %>][position]" + value="<%- data.position %>"/> + <input type="hidden" + name="product[media_gallery][images][<%- data.file_id %>][file]" + value="<%- data.file %>"/> + <input type="hidden" + name="product[media_gallery][images][<%- data.file_id %>][value_id]" + value="<%- data.value_id %>"/> + <input type="hidden" + name="product[media_gallery][images][<%- data.file_id %>][label]" + value="<%- data.label %>"/> + <input type="hidden" + name="product[media_gallery][images][<%- data.file_id %>][disabled]" + value="<%- data.disabled %>"/> + <input type="hidden" + name="product[media_gallery][images][<%- data.file_id %>][removed]"/> + <div class="product-image-wrapper"> + <img class="product-image" data-role="image-element" src="<%- data.url %>" alt="<%- data.label %>"/> + <div class="actions"> + <button type="button" + class="action-remove" + data-role="delete-button" + title="<?= $block->escapeHtml(__('Remove image')) ?>"> + <span><?php echo $block->escapeHtml(__('Remove image')) ?></span> + </button> + <div class="draggable-handle"></div> + </div> + <div class="image-fade"><span><?php echo $block->escapeHtml(__('Hidden')) ?></span></div> + </div> + <div class="item-description"> + <div class="item-title" data-role="img-title"><%- data.label %></div> + <div class="item-size"> + <span data-role="image-dimens"></span>, <span data-role="image-size"><%- data.sizeLabel %></span> + </div> + </div> + <ul class="item-roles" data-role="roles-labels"> <?php - endforeach; - ?> - </ul> - </div> - </script> + foreach ($block->getMediaAttributes() as $attribute): + ?> + <li data-role-code="<?php echo $block->escapeHtml( + $attribute->getAttributeCode() + ) ?>" class="item-role item-role-<?php echo $block->escapeHtml( + $attribute->getAttributeCode() + ) ?>"> + <?php /* @noEscape */ echo $attribute->getFrontendLabel() ?> + </li> + <?php + endforeach; + ?> + </ul> + </div> + </script> - <script data-template="image" type="text/x-magento-template"> - <div class="image"> - <div class="product-image-wrapper"> - <img class="product-image" - data-role="image-element" - src="<%- data.url %>" - data-position="<%- data.position %>" - alt="<%- data.label %>" /> - - <div class="actions"> - <button type="button" - class="action-remove" - data-role="delete-button" - title="<?= $block->escapeHtml(__('Remove image')) ?>"> - <span><?= /* @noEscape */ __('Remove image') ?></span> - </button> - - <div class="draggable-handle"></div> - </div> + <script data-template="image" type="text/x-magento-template"> + <div class="image"> + <div class="product-image-wrapper"> + <img class="product-image" + data-role="image-element" + src="<%- data.url %>" + data-position="<%- data.position %>" + alt="<%- data.label %>" /> + + <div class="actions"> + <button type="button" + class="action-remove" + data-role="delete-button" + title="<?= $block->escapeHtml(__('Remove image')) ?>"> + <span><?php echo $block->escapeHtml(__('Remove image')) ?></span> + </button> + + <div class="draggable-handle"></div> + </div> - <div class="image-fade"><span><?= /* @noEscape */ __('Hidden') ?></span></div> + <div class="image-fade"><span><?php echo $block->escapeHtml(__('Hidden')) ?></span></div> + </div> + <!--<ul class="item-roles"> + <li class="item-role item-role-base">Base</li> + </ul>--> </div> - <!--<ul class="item-roles"> - <li class="item-role item-role-base">Base</li> - </ul>--> - </div> - </script> + </script> - <script data-role="img-dialog-container-tmpl" type="text/x-magento-template"> - <div class="image-panel ui-tabs-panel ui-widget-content ui-corner-bottom" data-role="dialog"> - </div> - </script> + <script data-role="img-dialog-container-tmpl" type="text/x-magento-template"> + <div class="image-panel ui-tabs-panel ui-widget-content ui-corner-bottom" data-role="dialog"> + </div> + </script> - <script class="dialog-template" type="text/x-magento-template" data-title="Image Options"> - <div class="image-panel-preview"> - <img src="<%- data.url %>" alt="<%- data.label %>" /> - </div> - <div class="image-panel-controls"> - <strong class="image-name"><%- data.label %></strong> + <script class="dialog-template" type="text/x-magento-template" data-title="Image Options"> + <div class="image-panel-preview"> + <img src="<%- data.url %>" alt="<%- data.label %>" /> + </div> + <div class="image-panel-controls"> + <strong class="image-name"><%- data.label %></strong> - <fieldset class="admin__fieldset fieldset-image-panel"> - <div class="admin__field field-image-description"> - <label class="admin__field-label" for="image-description"> - <span><?php /* @escapeNotVerified */ echo __('Alt Text')?></span> - </label> + <fieldset class="admin__fieldset fieldset-image-panel"> + <div class="admin__field field-image-description"> + <label class="admin__field-label" for="image-description"> + <span><?php echo $block->escapeHtml(__('Alt Text')) ?></span> + </label> - <div class="admin__field-control"> + <div class="admin__field-control"> <textarea data-role="image-description" rows="3" class="admin__control-textarea" name="product[media_gallery][images][<%- data.file_id %>][label]" - ><%- data.label %></textarea> + ><%- data.label %></textarea> + </div> </div> - </div> - <div class="admin__field field-image-role"> - <label class="admin__field-label"> - <span><?php /* @noEscape */ echo __('Role')?></span> - </label> - <div class="admin__field-control"> - <ul class="multiselect-alt"> - <?php - foreach ($block->getMediaAttributes() as $attribute) : - ?> - <li class="item"> - <label> - <input class="image-type" - data-role="type-selector" - type="checkbox" - value="<?php echo $block->escapeHtml( - $attribute->getAttributeCode() - ) ?>" - /> - <?php /* @noEscape */ echo $attribute->getFrontendLabel()?> - </label> - </li> + <div class="admin__field field-image-role"> + <label class="admin__field-label"> + <span><?php echo $block->escapeHtml( + __('Role') + ); ?></span> + </label> + <div class="admin__field-control"> + <ul class="multiselect-alt"> <?php - endforeach; - ?> - </ul> + foreach ($block->getMediaAttributes() as $attribute) : + ?> + <li class="item"> + <label> + <input class="image-type" + data-role="type-selector" + type="checkbox" + value="<?php echo $block->escapeHtml( + $attribute->getAttributeCode() + ) ?>" + /> + <?php echo $block->escapeHtml( + $attribute->getFrontendLabel() + ); ?> + </label> + </li> + <?php + endforeach; + ?> + </ul> + </div> </div> - </div> - <div class="admin__field admin__field-inline field-image-size" data-role="size"> - <label class="admin__field-label"> - <span><?php /* @noEscape */ echo __('Image Size') ?></span> - </label> - <div class="admin__field-value" data-message="<?php /* @noEscape */ echo __('{size}') ?>"></div> - </div> + <div class="admin__field admin__field-inline field-image-size" data-role="size"> + <label class="admin__field-label"> + <span><?php echo $block->escapeHtml( + __('Image Size') + ); ?></span> + </label> + <div class="admin__field-value" data-message="<?php echo $block->escapeHtml( + __('{size}') + );?>"></div> + </div> - <div class="admin__field admin__field-inline field-image-resolution" data-role="resolution"> - <label class="admin__field-label"> - <span><?php /* @noEscape */ echo __('Image Resolution') ?></span> - </label> - <div class="admin__field-value" data-message="<?php /* @noEscape */ echo __('{width}^{height} px') ?>"></div> - </div> + <div class="admin__field admin__field-inline field-image-resolution" data-role="resolution"> + <label class="admin__field-label"> + <span><?php echo $block->escapeHtml( + __('Image Resolution') + ); ?></span> + </label> + <div class="admin__field-value" data-message="<?php echo $block->escapeHtml( + __('{width}^{height} px') + );?>"></div> + </div> - <div class="admin__field field-image-hide"> - <div class="admin__field-control"> - <div class="admin__field admin__field-option"> - <input type="checkbox" - id="hide-from-product-page" - data-role="visibility-trigger" - value="1" - class="admin__control-checkbox" - name="product[media_gallery][images][<%- data.file_id %>][disabled]" - <% if (data.disabled == 1) { %>checked="checked"<% } %> /> - - <label for="hide-from-product-page" class="admin__field-label"> - <?php /* @noEscape */ echo __('Hide from Product Page')?> - </label> + <div class="admin__field field-image-hide"> + <div class="admin__field-control"> + <div class="admin__field admin__field-option"> + <input type="checkbox" + id="hide-from-product-page" + data-role="visibility-trigger" + value="1" + class="admin__control-checkbox" + name="product[media_gallery][images][<%- data.file_id %>][disabled]" + <% if (data.disabled == 1) { %>checked="checked"<% } %> /> + + <label for="hide-from-product-page" class="admin__field-label"> + <?php echo $block->escapeHtml( + __('Hide from Product Page') + ); ?> + </label> + </div> </div> </div> - </div> - </fieldset> - </div> - </script> + </fieldset> + </div> + </script> + </div> </div> - </div> - <div data-role="step-gallery-each" class="attribute-image-selector" data-bind="visible: type() == 'each'"> - <fieldset class="admin__fieldset bulk-attribute-values"> - <div class="admin__field _required"> - <label class="admin__field-label" for="apply-images-attributes"> - <span><?= /* @noEscape */ __('Select attribute')?></span> - </label> - <div class="admin__field-control"> - <select - id="apply-images-attributes" - class="admin__control-select" - data-bind=" + <div data-role="step-gallery-each" class="attribute-image-selector" data-bind="visible: type() == 'each'"> + <fieldset class="admin__fieldset bulk-attribute-values"> + <div class="admin__field _required"> + <label class="admin__field-label" for="apply-images-attributes"> + <span><?php echo $block->escapeHtml( + __('Select attribute') + ); ?></span> + </label> + <div class="admin__field-control"> + <select + id="apply-images-attributes" + class="admin__control-select" + data-bind=" options: $parent.attributes, optionsText: 'label', value: attribute, - optionsCaption: '<?= /* @noEscape */ __("Select")?>' + optionsCaption: '<?php echo $block->escapeHtml( + __("Select") + ); ?>' "> - </select> - </div> - </div> - </fieldset> - - <ul class="items attributes-selector-list" data-bind="if:attribute, visible: attribute"> - <!-- ko foreach: {data: attribute().chosen, afterRender: $parent.bindGalleries} --> - <li class="item" data-bind="attr:{'data-role':'step-gallery-option-' + id}"> - <label class="attribute-label"> - <span data-bind="text:label"></span> - </label> - - <div data-role="gallery" - class="gallery" - data-images="[]" - data-types="<?php /* @noEscape */ echo $block->escapeHtml( - $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($block->getImageTypes()) - ) ?>" - > - <div class="image image-placeholder"> - <div data-role="uploader" class="uploader"> - <div class="image-browse"> - <span><?= /* @noEscape */ __('Browse Files...') ?></span> - <input type="file" name="image" multiple="multiple" - data-url="<?= /* @noEscape */ $block->getUrl('catalog/product_gallery/upload') ?>" /> - </div> - </div> - <div class="product-image-wrapper"> - <p class="image-placeholder-text"><?= /* @noEscape */ __('Browse to find or drag image here') ?></p> - </div> - <div class="spinner"> - <span></span><span></span><span></span><span></span> - <span></span><span></span><span></span><span></span> - </div> + </select> </div> + </div> + </fieldset> - <?php foreach ($block->getImageTypes() as $typeData): - ?> - <input name="<?php echo $block->escapeHtml($typeData['name']) ?>" - class="image-<?php echo $block->escapeHtml($typeData['code']) ?>" - type="hidden" - value="<?php echo $block->escapeHtml($typeData['value']) ?>"/> - <?php - endforeach; - ?> + <ul class="items attributes-selector-list" data-bind="if:attribute, visible: attribute"> + <!-- ko foreach: {data: attribute().chosen, afterRender: $parent.bindGalleries} --> + <li class="item" data-bind="attr:{'data-role':'step-gallery-option-' + id}"> + <label class="attribute-label"> + <span data-bind="text:label"></span> + </label> - <script data-template="uploader" type="text/x-magento-template"> - <div id="<%- data.id %>" class="file-row"> - <span class="file-info"><%- data.name %> (<%- data.size %>)</span> - <div class="progressbar-container"> - <div class="progressbar upload-progress" style="width: 0%;"></div> + <div data-role="gallery" + class="gallery" + data-images="[]" + data-types="<?php echo $block->escapeHtml( + $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($block->getImageTypes()) + ) ?>" + > + <div class="image image-placeholder"> + <div data-role="uploader" class="uploader"> + <div class="image-browse"> + <span><?php echo $block->escapeHtml( + __('Browse Files...') + ); ?></span> + <input type="file" name="image" multiple="multiple" + data-url="<?= /* @noEscape */ $block->getUrl('catalog/product_gallery/upload') ?>" /> + </div> + </div> + <div class="product-image-wrapper"> + <p class="image-placeholder-text"><?php echo $block->escapeHtml( + __('Browse to find or drag image here') + ); ?></p> </div> <div class="spinner"> <span></span><span></span><span></span><span></span> <span></span><span></span><span></span><span></span> </div> </div> - </script> - - <script data-template="gallery-content" type="text/x-magento-template"> - <div class="image item <% if (data.disabled == 1) { %>hidden-for-front<% } %>" - data-role="image"> - <input type="hidden" - name="product[media_gallery][images][<%- data.file_id %>][position]" - value="<%- data.position %>" class="position"/> - <input type="hidden" - name="product[media_gallery][images][<%- data.file_id %>][file]" - value="<%- data.file %>"/> - <input type="hidden" - name="product[media_gallery][images][<%- data.file_id %>][value_id]" - value="<%- data.value_id %>"/> - <input type="hidden" - name="product[media_gallery][images][<%- data.file_id %>][label]" - value="<%- data.label %>"/> - <input type="hidden" - name="product[media_gallery][images][<%- data.file_id %>][disabled]" - value="<%- data.disabled %>"/> - <input type="hidden" - name="product[media_gallery][images][<%- data.file_id %>][removed]" - value="" - class="is-removed"/> - <div class="product-image-wrapper"> - <img class="product-image" data-role="image-element" src="<%- data.url %>" alt="<%- data.label %>"/> - <div class="actions"> - <button type="button" - class="action-remove" - data-role="delete-button" - title="<?= $block->escapeHtml(__('Remove image')) ?>"> - <span><?php /* @noEscape */ echo __('Remove image') ?></span> - </button> - <div class="draggable-handle"></div> + + <?php foreach ($block->getImageTypes() as $typeData): + ?> + <input name="<?php echo $block->escapeHtml($typeData['name']) ?>" + class="image-<?php echo $block->escapeHtml($typeData['code']) ?>" + type="hidden" + value="<?php echo $block->escapeHtml($typeData['value']) ?>"/> + <?php + endforeach; + ?> + + <script data-template="uploader" type="text/x-magento-template"> + <div id="<%- data.id %>" class="file-row"> + <span class="file-info"><%- data.name %> (<%- data.size %>)</span> + <div class="progressbar-container"> + <div class="progressbar upload-progress" style="width: 0%;"></div> </div> - <div class="image-fade"><span><?= /* @noEscape */ __('Hidden') ?></span></div> - </div> - <div class="item-description"> - <div class="item-title" data-role="img-title"><%- data.label %></div> - <div class="item-size"> - <span data-role="image-dimens"></span>, <span data-role="image-size"><%- data.sizeLabel %></span> + <div class="spinner"> + <span></span><span></span><span></span><span></span> + <span></span><span></span><span></span><span></span> </div> </div> - <ul class="item-roles" data-role="roles-labels"> - <?php - foreach ($block->getMediaAttributes() as $attribute): - ?> - <li data-role-code="<?php echo $block->escapeHtml( - $attribute->getAttributeCode() - ) ?>" class="item-role item-role-<?php echo $block->escapeHtml( - $attribute->getAttributeCode() - ) ?>"> - <?php echo $block->escapeHtml($attribute->getFrontendLabel()) ?> - </li> + </script> + + <script data-template="gallery-content" type="text/x-magento-template"> + <div class="image item <% if (data.disabled == 1) { %>hidden-for-front<% } %>" + data-role="image"> + <input type="hidden" + name="product[media_gallery][images][<%- data.file_id %>][position]" + value="<%- data.position %>" class="position"/> + <input type="hidden" + name="product[media_gallery][images][<%- data.file_id %>][file]" + value="<%- data.file %>"/> + <input type="hidden" + name="product[media_gallery][images][<%- data.file_id %>][value_id]" + value="<%- data.value_id %>"/> + <input type="hidden" + name="product[media_gallery][images][<%- data.file_id %>][label]" + value="<%- data.label %>"/> + <input type="hidden" + name="product[media_gallery][images][<%- data.file_id %>][disabled]" + value="<%- data.disabled %>"/> + <input type="hidden" + name="product[media_gallery][images][<%- data.file_id %>][removed]" + value="" + class="is-removed"/> + <div class="product-image-wrapper"> + <img class="product-image" data-role="image-element" src="<%- data.url %>" alt="<%- data.label %>"/> + <div class="actions"> + <button type="button" + class="action-remove" + data-role="delete-button" + title="<?= $block->escapeHtml(__('Remove image')) ?>"> + <span><?php echo $block->escapeHtml( + __('Remove image') + ); ?></span> + </button> + <div class="draggable-handle"></div> + </div> + <div class="image-fade"><span><?php echo $block->escapeHtml( + __('Hidden') + ); ?></span></div> + </div> + <div class="item-description"> + <div class="item-title" data-role="img-title"><%- data.label %></div> + <div class="item-size"> + <span data-role="image-dimens"></span>, <span data-role="image-size"><%- data.sizeLabel %></span> + </div> + </div> + <ul class="item-roles" data-role="roles-labels"> <?php - endforeach; - ?> - </ul> - </div> - </script> - - <script data-template="image" type="text/x-magento-template"> - <div class="image"> - <div class="product-image-wrapper"> - <img class="product-image" - src="<%- data.url %>" - data-role="image-element" - data-position="<%- data.position %>" - alt="<%- data.label %>" /> - <div class="actions"> - <button type="button" - class="action-remove" - data-role="delete-button" - title="<?= $block->escapeHtml(__('Remove image')) ?>"> - <span><?= /* @noEscape */ __('Remove image') ?></span> - </button> - <div class="draggable-handle"></div> + foreach ($block->getMediaAttributes() as $attribute): + ?> + <li data-role-code="<?php echo $block->escapeHtml( + $attribute->getAttributeCode() + ) ?>" class="item-role item-role-<?php echo $block->escapeHtml( + $attribute->getAttributeCode() + ) ?>"> + <?php echo $block->escapeHtml($attribute->getFrontendLabel()) ?> + </li> + <?php + endforeach; + ?> + </ul> + </div> + </script> + + <script data-template="image" type="text/x-magento-template"> + <div class="image"> + <div class="product-image-wrapper"> + <img class="product-image" + src="<%- data.url %>" + data-role="image-element" + data-position="<%- data.position %>" + alt="<%- data.label %>" /> + <div class="actions"> + <button type="button" + class="action-remove" + data-role="delete-button" + title="<?= $block->escapeHtml(__('Remove image')) ?>"> + <span><?php echo $block->escapeHtml(__('Remove image')) ?></span> + </button> + <div class="draggable-handle"></div> + </div> + <div class="image-fade"><span><?php echo $block->escapeHtml(__('Hidden')) ?></span></div> </div> - <div class="image-fade"><span><?= /* @noEscape */ __('Hidden') ?></span></div> + <!--<ul class="item-roles"> + <li class="item-role item-role-base">Base</li> + </ul>--> </div> - <!--<ul class="item-roles"> - <li class="item-role item-role-base">Base</li> - </ul>--> - </div> - </script> - - <script data-role="img-dialog-container-tmpl" type="text/x-magento-template"> - <div class="image-panel ui-tabs-panel ui-widget-content ui-corner-bottom" data-role="dialog"> - </div> - </script> + </script> - <script class="dialog-template" type="text/x-magento-template" data-title="Image Options"> - <div class="image-panel-preview"> - <img src="<%- data.url %>" alt="<%- data.label %>" /> - </div> - <div class="image-panel-controls"> - <strong class="image-name"><%- data.label %></strong> - - <fieldset class="admin__fieldset fieldset-image-panel"> - <div class="admin__field field-image-description"> - <label class="admin__field-label" for="image-description"> - <span><?php /* @noEscape */ echo __('Alt Text')?></span> - </label> + <script data-role="img-dialog-container-tmpl" type="text/x-magento-template"> + <div class="image-panel ui-tabs-panel ui-widget-content ui-corner-bottom" data-role="dialog"> + </div> + </script> - <div class="admin__field-control"> + <script class="dialog-template" type="text/x-magento-template" data-title="Image Options"> + <div class="image-panel-preview"> + <img src="<%- data.url %>" alt="<%- data.label %>" /> + </div> + <div class="image-panel-controls"> + <strong class="image-name"><%- data.label %></strong> + + <fieldset class="admin__fieldset fieldset-image-panel"> + <div class="admin__field field-image-description"> + <label class="admin__field-label" for="image-description"> + <span><?php echo $block->escapeHtml( + __('Alt Text') + );?></span> + </label> + + <div class="admin__field-control"> <textarea data-role="image-description" rows="3" class="admin__control-textarea" name="product[media_gallery][images][<%- data.file_id %>][label]" - ><%- data.label %></textarea> + ><%- data.label %></textarea> + </div> </div> - </div> - <div class="admin__field field-image-role"> - <label class="admin__field-label"> - <span><?php /* @noEscape */ echo __('Role')?></span> - </label> - <div class="admin__field-control"> - <ul class="multiselect-alt"> - <?php - foreach ($block->getMediaAttributes() as $attribute) : - ?> - <li class="item"> - <label> - <input class="image-type" - data-role="type-selector" - type="checkbox" - value="<?php echo $block->escapeHtml( - $attribute->getAttributeCode() - ) ?>" - /> - <?php echo $block->escapeHtml( - $attribute->getFrontendLabel() - ) ?> - </label> - </li> + <div class="admin__field field-image-role"> + <label class="admin__field-label"> + <span><?php echo $block->escapeHtml( + __('Role') + );?></span> + </label> + <div class="admin__field-control"> + <ul class="multiselect-alt"> <?php - endforeach; - ?> - </ul> + foreach ($block->getMediaAttributes() as $attribute) : + ?> + <li class="item"> + <label> + <input class="image-type" + data-role="type-selector" + type="checkbox" + value="<?php echo $block->escapeHtml( + $attribute->getAttributeCode() + ) ?>" + /> + <?php echo $block->escapeHtml( + $attribute->getFrontendLabel() + ) ?> + </label> + </li> + <?php + endforeach; + ?> + </ul> + </div> </div> - </div> - <div class="admin__field admin__field-inline field-image-size" data-role="size"> - <label class="admin__field-label"> - <span><?php /* @noEscape */ echo __('Image Size') ?></span> - </label> - <div class="admin__field-value" data-message="<?php /* @noEscape */ echo __('{size}') ?>"></div> - </div> + <div class="admin__field admin__field-inline field-image-size" data-role="size"> + <label class="admin__field-label"> + <span><?php echo $block->escapeHtml( + __('Image Size') + ); ?></span> + </label> + <div class="admin__field-value" data-message="<?php echo $block->escapeHtml( + __('{size}') + ); ?>"></div> + </div> - <div class="admin__field admin__field-inline field-image-resolution" data-role="resolution"> - <label class="admin__field-label"> - <span><?php /* @noEscape */ echo __('Image Resolution') ?></span> - </label> - <div class="admin__field-value" data-message="<?php /* @noEscape */ echo __('{width}^{height} px') ?>"></div> - </div> + <div class="admin__field admin__field-inline field-image-resolution" data-role="resolution"> + <label class="admin__field-label"> + <span><?php echo $block->escapeHtml( + __('Image Resolution') + ); ?></span> + </label> + <div class="admin__field-value" data-message="<?php echo $block->escapeHtml( + __('{width}^{height} px') + ); ?>"></div> + </div> - <div class="admin__field field-image-hide"> - <div class="admin__field-control"> - <div class="admin__field admin__field-option"> - <input type="checkbox" - id="hide-from-product-page" - data-role="visibility-trigger" - value="1" - class="admin__control-checkbox" - name="product[media_gallery][images][<%- data.file_id %>][disabled]" - <% if (data.disabled == 1) { %>checked="checked"<% } %> /> - - <label for="hide-from-product-page" class="admin__field-label"> - <?php /* @noEscape */ echo __('Hide from Product Page')?> - </label> + <div class="admin__field field-image-hide"> + <div class="admin__field-control"> + <div class="admin__field admin__field-option"> + <input type="checkbox" + id="hide-from-product-page" + data-role="visibility-trigger" + value="1" + class="admin__control-checkbox" + name="product[media_gallery][images][<%- data.file_id %>][disabled]" + <% if (data.disabled == 1) { %>checked="checked"<% } %> /> + + <label for="hide-from-product-page" class="admin__field-label"> + <?php echo $block->escapeHtml( + __('Hide from Product Page') + ); ?> + </label> + </div> </div> </div> - </div> - </fieldset> - </div> - </script> - </div> - </li> - <!-- /ko --> - </ul> + </fieldset> + </div> + </script> + </div> + </li> + <!-- /ko --> + </ul> + </div> </div> </div> -</div> <div data-bind="with: sections().price" class="steps-wizard-section"> <div data-role="section"> <div class="steps-wizard-section-title"> - <span><?php /* @noEscape */ echo __('Price') ?></span> + <span><?php echo $block->escapeHtml( + __('Price') + ); ?></span> </div> <ul class="steps-wizard-section-list"> <li> @@ -562,7 +607,9 @@ data-bind="checked:type" /> <label for="apply-single-price-radio" class="admin__field-label"> - <span><?php /* @noEscape */ echo __('Apply single price to all SKUs') ?></span> + <span><?php echo $block->escapeHtml( + __('Apply single price to all SKUs') + ); ?></span> </label> </div> </li> @@ -575,7 +622,9 @@ data-bind="checked:type" /> <label for="apply-unique-prices-radio" class="admin__field-label"> - <span><?php /* @noEscape */ echo __('Apply unique prices by attribute to each SKU') ?></span> + <span><?php echo $block->escapeHtml( + __('Apply unique prices by attribute to each SKU') + ); ?></span> </label> </div> </li> @@ -588,33 +637,39 @@ checked data-bind="checked:type" /> <label for="skip-pricing-radio" class="admin__field-label"> - <span><?php /* @noEscape */ echo __('Skip price at this time') ?></span> + <span><?php echo $block->escapeHtml( + __('Skip price at this time') + ); ?></span> </label> </div> </li> </ul> <form data-role="attributes-values-form"> - <fieldset class="admin__fieldset bulk-attribute-values" data-bind="visible: type() == 'single'"> - <div class="admin__field _required"> - <label for="apply-single-price-input" class="admin__field-label"> - <span><?php /* @noEscape */ echo __('Price') ?></span> - </label> - <div class="admin__field-control"> - <div class="currency-addon"> - <input class="admin__control-text required-entry validate-zero-or-greater" type="text" - data-bind="value:value, uniqueName: true" id="apply-single-price-input"/> - <span class="currency-symbol" data-bind="text:currencySymbol"></span> + <fieldset class="admin__fieldset bulk-attribute-values" data-bind="visible: type() == 'single'"> + <div class="admin__field _required"> + <label for="apply-single-price-input" class="admin__field-label"> + <span><?php echo $block->escapeHtml( + __('Price') + ); ?></span> + </label> + <div class="admin__field-control"> + <div class="currency-addon"> + <input class="admin__control-text required-entry validate-zero-or-greater" type="text" + data-bind="value:value, uniqueName: true" id="apply-single-price-input"/> + <span class="currency-symbol" data-bind="text:currencySymbol"></span> + </div> </div> </div> - </div> - </fieldset> + </fieldset> </form> <div data-bind="visible: type() == 'each'"> <fieldset class="admin__fieldset bulk-attribute-values"> <div class="admin__field _required"> <label for="select-each-price" class="admin__field-label"> - <span><?php /* @noEscape */ echo __('Select attribute') ?></span> + <span><?php echo $block->escapeHtml( + __('Select attribute') + ); ?></span> </label> <div class="admin__field-control"> <select id="select-each-price" class="admin__control-select" data-bind=" @@ -653,7 +708,7 @@ <div data-bind="with: sections().quantity" class="steps-wizard-section"> <div data-role="section"> <div class="steps-wizard-section-title"> - <span><?php /* @noEscape */ echo __('Quantity') ?></span> + <span><?php echo $block->escapeHtml(__('Quantity')) ?></span> </div> <ul class="steps-wizard-section-list"> <li> @@ -664,7 +719,7 @@ value="single" data-bind="checked: type" /> <label for="apply-single-inventory-radio" class="admin__field-label"> - <span><?php /* @noEscape */ echo __('Apply single quantity to each SKUs') ?></span> + <span><?php echo $block->escapeHtml(__('Apply single quantity to each SKUs')) ?></span> </label> </div> </li> @@ -676,7 +731,7 @@ value="each" data-bind="checked: type" /> <label for="apply-unique-inventory-radio" class="admin__field-label"> - <span><?php /* @noEscape */ echo __('Apply unique quantity by attribute to each SKU') ?></span> + <span><?php echo $block->escapeHtml(__('Apply unique quantity by attribute to each SKU')) ?></span> </label> </div> </li> @@ -689,33 +744,33 @@ checked data-bind="checked: type" /> <label for="skip-inventory-radio" class="admin__field-label"> - <span><?php /* @noEscape */ echo __('Skip quantity at this time') ?></span> + <span><?php echo $block->escapeHtml(__('Skip quantity at this time')) ?></span> </label> </div> </li> </ul> <form data-role="attributes-values-form"> - <fieldset class="admin__fieldset bulk-attribute-values" data-bind="visible: type() == 'single'"> - <div class="admin__field _required"> - <label for="apply-single-inventory-input" class="admin__field-label"> - <span><?php /* @noEscape */ echo __('Quantity') ?></span> - </label> - <div class="admin__field-control"> - <input type="text" - id="apply-single-inventory-input" - class="admin__control-text required-entry validate-zero-or-greater" - data-bind="value: value, uniqueName: true" /> + <fieldset class="admin__fieldset bulk-attribute-values" data-bind="visible: type() == 'single'"> + <div class="admin__field _required"> + <label for="apply-single-inventory-input" class="admin__field-label"> + <span><?php echo $block->escapeHtml(__('Quantity')) ?></span> + </label> + <div class="admin__field-control"> + <input type="text" + id="apply-single-inventory-input" + class="admin__control-text required-entry validate-zero-or-greater" + data-bind="value: value, uniqueName: true" /> + </div> </div> - </div> - </fieldset> + </fieldset> </form> <div data-bind="visible: type() == 'each'"> <fieldset class="admin__fieldset bulk-attribute-values"> <div class="admin__field _required"> <label for="apply-single-price-input-qty" class="admin__field-label"> - <span><?php /* @noEscape */ echo __('Select attribute') ?></span> + <span><?php echo $block->escapeHtml(__('Select attribute')) ?></span> </label> <div class="admin__field-control"> <select id="apply-single-price-input-qty" class="admin__control-select" data-bind=" @@ -727,26 +782,26 @@ </div> </fieldset> <form data-role="attributes-values-form"> - <fieldset class="admin__fieldset bulk-attribute-values" data-bind="if:attribute"> - <!-- ko foreach: attribute().chosen --> - <div class="admin__field _required"> - <label data-bind="attr: {for: 'apply-qty-input-' + $index()}" class="admin__field-label"> - <span data-bind="text:label"></span> - </label> - <div class="admin__field-control"> - <input id="apply-single-price-input-value" - class="admin__control-text required-entry validate-zero-or-greater" type="text" - data-bind="value:sections()[$parent.label], uniqueName: true, + <fieldset class="admin__fieldset bulk-attribute-values" data-bind="if:attribute"> + <!-- ko foreach: attribute().chosen --> + <div class="admin__field _required"> + <label data-bind="attr: {for: 'apply-qty-input-' + $index()}" class="admin__field-label"> + <span data-bind="text:label"></span> + </label> + <div class="admin__field-control"> + <input id="apply-single-price-input-value" + class="admin__control-text required-entry validate-zero-or-greater" type="text" + data-bind="value:sections()[$parent.label], uniqueName: true, attr: {id: 'apply-qty-input-' + $index()}"/> + </div> </div> - </div> - <!-- /ko --> - </fieldset> + <!-- /ko --> + </fieldset> </form> </div> </div> </div> -</form> + </form> </div> <script type="text/x-magento-init"> diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/select_attributes.phtml b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/select_attributes.phtml index 7028eadb72c848ae6c21ac6c797afe6705d52e9a..ffb27ccd3c85561dfd377f7dd4cb6301339e70ab 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/select_attributes.phtml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/select_attributes.phtml @@ -12,9 +12,13 @@ <div class="select-attributes-actions" data-type="skipKO"> <?= /* @noEscape */ $block->getAddNewAttributeButton(); ?> </div> - <h2 class="steps-wizard-title"><?= /* @noEscape */ __('Step 1: Select Attributes') ?></h2> + <h2 class="steps-wizard-title"><?php echo $block->escapeHtml( + __('Step 1: Select Attributes') + ); ?></h2> <div class="selected-attributes" data-bind="scope: '<?= /* @noEscape */ $block->getComponentName()?>'"> - <?= /* @noEscape */ __('Selected Attributes:') ?> + <?php echo $block->escapeHtml( + __('Selected Attributes:') + ); ?> <span data-bind="text: selectedAttributes() || '--'"></span> </div> </div> diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/summary.phtml b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/summary.phtml index e5ab81c99cc19fd9434babddc0c6a2df847c4f54..37bde42041b6dc10b0cff20137890730fd68c092 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/summary.phtml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/attribute/steps/summary.phtml @@ -9,34 +9,36 @@ /* @var $block \Magento\ConfigurableProduct\Block\Adminhtml\Product\Steps\Summary */ ?> <div data-bind="scope: '<?= /* @noEscape */ $block->getComponentName()?>'"> - <h2 class="steps-wizard-title"><?= /* @noEscape */ __('Step 4: Summary') ?></h2> + <h2 class="steps-wizard-title"><?php echo $block->escapeHtml( + __('Step 4: Summary') + ); ?></h2> <div class="admin__data-grid-wrap admin__data-grid-wrap-static"> <!-- ko if: gridNew().length --> - <!-- ko template: {name: getGridTemplate(), data: { - grid: gridNew, - id: getGridId(), - title: $t('New Product Review'), - note: $t('Here are the products you\'re about to create.') - }} --><!-- /ko --> + <!-- ko template: {name: getGridTemplate(), data: { + grid: gridNew, + id: getGridId(), + title: $t('New Product Review'), + note: $t('Here are the products you\'re about to create.') + }} --><!-- /ko --> <!-- /ko --> <!-- ko if: gridExisting().length --> - <!-- ko template: {name: getGridTemplate(), data: { - grid: gridExisting, - id: getGridId(), - title: $t('Associated Products'), - note: $t('You created these products for this configuration.') - }} --><!-- /ko --> + <!-- ko template: {name: getGridTemplate(), data: { + grid: gridExisting, + id: getGridId(), + title: $t('Associated Products'), + note: $t('You created these products for this configuration.') + }} --><!-- /ko --> <!-- /ko --> <!-- ko if: gridDeleted().length --> - <!-- ko template: {name: getGridTemplate(), data: { - grid: gridDeleted, - id: getGridId(), - title: $t('Disassociated Products'), - note: $t('These products are not associated.') - }} --><!-- /ko --> + <!-- ko template: {name: getGridTemplate(), data: { + grid: gridDeleted, + id: getGridId(), + title: $t('Disassociated Products'), + note: $t('These products are not associated.') + }} --><!-- /ko --> <!-- /ko --> </div> </div> diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/wizard.phtml b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/wizard.phtml index 0736fa20fd21e6cf07512e665ce79c3d40c8ceb0..930a264ea8952623bb6f1e5e45a42516e12a9c1c 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/wizard.phtml +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/templates/catalog/product/edit/super/wizard.phtml @@ -26,7 +26,7 @@ $currencySymbol = $block->getCurrencySymbol(); "components": { "<?= /* @noEscape */ $block->getData('config/form') ?>.<?= /* @noEscape */ $block->getModal() ?>": { "component": "Magento_ConfigurableProduct/js/components/modal-configurable", - "options": {"type": "slide", "title": "<?= /* @escapeNotVerified */ __('Create Product Configurations') ?>"}, + "options": {"type": "slide", "title": "<?php echo $block->escapeHtml(__('Create Product Configurations')); ?>"}, "formName": "<?= /* @noEscape */ $block->getForm() ?>", "isTemplate": false, "stepWizard": "<?= /* @noEscape */ $block->getData('config/nameStepWizard') ?>", @@ -47,7 +47,7 @@ $currencySymbol = $block->getCurrencySymbol(); "formName": "<?= /* @noEscape */ $block->getForm() ?>", "attributeSetHandler": "<?= /* @noEscape */ $block->getForm() ?>.configurable_attribute_set_handler_modal", "wizardModalButtonName": "<?= /* @noEscape */ $block->getForm() ?>.configurable.configurable_products_button_set.create_configurable_products_button", - "wizardModalButtonTitle": "<?= /* @noEscape */ __('Edit Configurations') ?>", + "wizardModalButtonTitle": "<?php echo $block->escapeHtml(__('Edit Configurations')); ?>", "productAttributes": <?= /* @noEscape */ $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($attributes) ?>, "productUrl": "<?= /* @noEscape */ $block->getUrl('catalog/product/edit', ['id' => '%id%']) ?>", "variations": <?= /* @noEscape */ $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($productMatrix) ?>, diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/associated-product-insert-listing.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/associated-product-insert-listing.js index 0c2847683474f813a72d884e5fbb6d002f94400f..ecc960bdb9ea59f09903dea3a118f65642993e8e 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/associated-product-insert-listing.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/associated-product-insert-listing.js @@ -24,7 +24,8 @@ define([ productsProvider: '${ $.productsProvider }', productsColumns: '${ $.productsColumns }', productsMassAction: '${ $.productsMassAction }', - modalWithGrid: '${ $.modalWithGrid }' + modalWithGrid: '${ $.modalWithGrid }', + productsFilters: '${ $.productsFilters }' }, exports: { externalProviderParams: '${ $.externalProvider }:params' @@ -58,7 +59,9 @@ define([ * @returns {Array} */ getUsedProductIds: function () { - return this.source.get(this.dataScopeAssociatedProduct); + var usedProductsIds = this.source.get(this.dataScopeAssociatedProduct); + + return usedProductsIds.slice(); }, /** @@ -72,6 +75,7 @@ define([ if (this.gridInitialized) { this.paramsUpdated = false; + this.productsFilters().clear(); this._setFilters(this.externalProviderParams); this._setVisibilityMassActionColumn(); } @@ -142,11 +146,13 @@ define([ usedProductIds, attributes; + params = _.omit(params); + if (!this.paramsUpdated) { this.gridInitialized = true; this.paramsUpdated = true; - attrCodes = this._getAttributesCodes(), + attrCodes = this._getAttributesCodes(); usedProductIds = this.getUsedProductIds(); if (this.currentProductId) { @@ -173,6 +179,8 @@ define([ })); params.filters = attributes; + } else { + params.filters = {}; } params['attributes_codes'] = attrCodes; diff --git a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js index 46c0443b16a069e5d68d1519d0782ac349e9d4d1..7614f41250af2c128c58d28d7528b333d61e0623 100644 --- a/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js +++ b/app/code/Magento/ConfigurableProduct/view/adminhtml/web/js/components/dynamic-rows-configurable.js @@ -113,7 +113,7 @@ define([ var tmpArray; this.reRender = false; - tmpArray = this.unionInsertData(); + tmpArray = this.getUnionInsertData(); tmpArray.splice(index, 1); if (!tmpArray.length) { @@ -130,7 +130,7 @@ define([ generateAssociatedProducts: function () { var productsIds = []; - this.unionInsertData().each(function (data) { + this.getUnionInsertData().each(function (data) { if (data.id !== null) { productsIds.push(data.id); } @@ -153,6 +153,22 @@ define([ return this; }, + /** + * Get union insert data from source + * + * @returns {Array} + */ + getUnionInsertData: function () { + var source = this.source.get(this.dataScope + '.' + this.index), + result = []; + + _.each(source, function (data) { + result.push(data); + }); + + return result; + }, + /** * Process union insert data. * @@ -217,7 +233,7 @@ define([ return; } - tmpArray = this.unionInsertData(); + tmpArray = this.getUnionInsertData(); changes = this._checkGridData(data); this.cacheGridData = data; @@ -241,7 +257,7 @@ define([ * @param {Object} data */ processingChangeDataFromGrid: function (data) { - var tmpArray = this.unionInsertData(), + var tmpArray = this.getUnionInsertData(), mappedData = this.mappingValue(data.product); mappedData[this.canEditField] = 0; @@ -295,7 +311,7 @@ define([ * @param {Object} data */ processingInsertDataFromWizard: function (data) { - var tmpArray = this.unionInsertData(), + var tmpArray = this.getUnionInsertData(), productIdsToDelete = this.source.get(this.dataScopeAssociatedProduct), index, product = {}; @@ -466,7 +482,7 @@ define([ * @param {Number} rowIndex */ toggleStatusProduct: function (rowIndex) { - var tmpArray = this.unionInsertData(), + var tmpArray = this.getUnionInsertData(), status = parseInt(tmpArray[rowIndex].status, 10); if (status === 1) { diff --git a/app/code/Magento/Customer/Model/ResourceModel/Grid/Collection.php b/app/code/Magento/Customer/Model/ResourceModel/Grid/Collection.php new file mode 100644 index 0000000000000000000000000000000000000000..d31e3c2930522ed610c9e23f4fbcaf4e2e81d0a9 --- /dev/null +++ b/app/code/Magento/Customer/Model/ResourceModel/Grid/Collection.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Customer\Model\ResourceModel\Grid; + +use Magento\Framework\Data\Collection\Db\FetchStrategyInterface as FetchStrategy; +use Magento\Framework\Data\Collection\EntityFactoryInterface as EntityFactory; +use Magento\Framework\Event\ManagerInterface as EventManager; +use Psr\Log\LoggerInterface as Logger; + +class Collection extends \Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult +{ + /** + * Initialize dependencies. + * + * @param EntityFactory $entityFactory + * @param Logger $logger + * @param FetchStrategy $fetchStrategy + * @param EventManager $eventManager + * @param string $mainTable + * @param string $resourceModel + */ + public function __construct( + EntityFactory $entityFactory, + Logger $logger, + FetchStrategy $fetchStrategy, + EventManager $eventManager, + $mainTable = 'customer_grid_flat', + $resourceModel = '\Magento\Customer\Model\ResourceModel\Customer' + ) { + parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $mainTable, $resourceModel); + } +} diff --git a/app/code/Magento/Customer/etc/di.xml b/app/code/Magento/Customer/etc/di.xml index f5c66d78c5b8114ba535c41730d940edf9828424..647ec87efca25a1e583df18d3d469f586996b2c2 100644 --- a/app/code/Magento/Customer/etc/di.xml +++ b/app/code/Magento/Customer/etc/di.xml @@ -180,12 +180,6 @@ <argument name="entitySnapshot" xsi:type="object">EavVersionControlSnapshot</argument> </arguments> </type> - <virtualType name="Magento\Customer\Model\ResourceModel\Grid\Collection" type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult"> - <arguments> - <argument name="mainTable" xsi:type="string">customer_grid_flat</argument> - <argument name="resourceModel" xsi:type="string">Magento\Customer\Model\ResourceModel\Customer</argument> - </arguments> - </virtualType> <type name="Magento\Framework\View\Element\UiComponent\DataProvider\CollectionFactory"> <arguments> <argument name="collections" xsi:type="array"> diff --git a/app/code/Magento/Directory/etc/adminhtml/system.xml b/app/code/Magento/Directory/etc/adminhtml/system.xml index a22bef73a275a75400edcd35c4ee3f84f8ec7ef9..5e61820f49c60429b965533f664ef36f307552c8 100644 --- a/app/code/Magento/Directory/etc/adminhtml/system.xml +++ b/app/code/Magento/Directory/etc/adminhtml/system.xml @@ -13,7 +13,7 @@ <resource>Magento_Backend::currency</resource> <group id="options" translate="label" sortOrder="30" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Currency Options</label> - <field id="base" translate="label comment" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="0"> + <field id="base" translate="label comment" type="select" sortOrder="1" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Base Currency</label> <frontend_model>Magento\Directory\Block\Adminhtml\Frontend\Currency\Base</frontend_model> <source_model>Magento\Config\Model\Config\Source\Locale\Currency</source_model> diff --git a/app/code/Magento/Integration/Controller/Adminhtml/Integration/TokensExchange.php b/app/code/Magento/Integration/Controller/Adminhtml/Integration/TokensExchange.php index 799420efcc0d59c265c7298dcc1630e144bfbce7..2251ed525db604133ae17ece56080d3ebc62dba7 100644 --- a/app/code/Magento/Integration/Controller/Adminhtml/Integration/TokensExchange.php +++ b/app/code/Magento/Integration/Controller/Adminhtml/Integration/TokensExchange.php @@ -53,10 +53,16 @@ class TokensExchange extends \Magento\Integration\Controller\Adminhtml\Integrati $this->_setActivationInProcessMsg($isReauthorize, $integration->getName()); $this->_view->renderLayout(); $popupContent = $this->_response->getBody(); + $consumer = $this->_oauthService->loadConsumer($integration->getConsumerId()); + if (!$consumer->getId()) { + throw new \Magento\Framework\Oauth\Exception( + __('A consumer with ID %1 does not exist', $integration->getConsumerId()) + ); + } /** Initialize response body */ $result = [ IntegrationModel::IDENTITY_LINK_URL => $integration->getIdentityLinkUrl(), - IntegrationModel::CONSUMER_ID => $integration->getConsumerId(), + 'oauth_consumer_key' => $consumer->getKey(), 'popup_content' => $popupContent, ]; $this->getResponse()->representJson($this->jsonHelper->jsonEncode($result)); diff --git a/app/code/Magento/Integration/Model/OauthService.php b/app/code/Magento/Integration/Model/OauthService.php index 9ce2df70a547b5029307d9b89e4cdb90fb03d164..16dbf5aa04b1013b62d3572f7092696b8eec0800 100644 --- a/app/code/Magento/Integration/Model/OauthService.php +++ b/app/code/Magento/Integration/Model/OauthService.php @@ -192,7 +192,7 @@ class OauthService implements \Magento\Integration\Api\OauthServiceInterface public function postToConsumer($consumerId, $endpointUrl) { try { - $consumer = $this->_consumerFactory->create()->load($consumerId); + $consumer = $this->loadConsumer($consumerId); if (!$consumer->getId()) { throw new \Magento\Framework\Oauth\Exception( __('A consumer with ID %1 does not exist', $consumerId) diff --git a/app/code/Magento/Integration/Model/ResourceModel/Oauth/Consumer.php b/app/code/Magento/Integration/Model/ResourceModel/Oauth/Consumer.php index 2fcd1910b1bccad50b36fb878e44c70076f7f1f8..9b677099e49e72b23df6925abeae88c9017fd0fc 100644 --- a/app/code/Magento/Integration/Model/ResourceModel/Oauth/Consumer.php +++ b/app/code/Magento/Integration/Model/ResourceModel/Oauth/Consumer.php @@ -37,8 +37,8 @@ class Consumer extends \Magento\Framework\Model\ResourceModel\Db\AbstractDb public function _afterDelete(\Magento\Framework\Model\AbstractModel $object) { $connection = $this->getConnection(); - $connection->delete($this->getTable('oauth_nonce'), ['consumer_id' => $object->getId()]); - $connection->delete($this->getTable('oauth_token'), ['consumer_id' => $object->getId()]); + $connection->delete($this->getTable('oauth_nonce'), ['consumer_id = ?' => (int)$object->getId()]); + $connection->delete($this->getTable('oauth_token'), ['consumer_id = ?' => (int)$object->getId()]); return parent::_afterDelete($object); } diff --git a/app/code/Magento/Integration/Test/Unit/Controller/Adminhtml/Integration/TokensDialogTest.php b/app/code/Magento/Integration/Test/Unit/Controller/Adminhtml/Integration/TokensDialogTest.php index fc28ff0f63dd52d34ded0e5ac415add915902d5d..7f6912c5d3270ecf5da2f702f66d1bb3956e09b9 100644 --- a/app/code/Magento/Integration/Test/Unit/Controller/Adminhtml/Integration/TokensDialogTest.php +++ b/app/code/Magento/Integration/Test/Unit/Controller/Adminhtml/Integration/TokensDialogTest.php @@ -84,6 +84,9 @@ class TokensDialogTest extends \Magento\Integration\Test\Unit\Controller\Adminht $this->_oauthSvcMock->expects($this->once())->method('deleteIntegrationToken'); $this->_oauthSvcMock->expects($this->once())->method('postToConsumer'); + $consumerMock = $this->getMock(\Magento\Integration\Model\Oauth\Consumer::class, [], [], '' , false); + $consumerMock->expects($this->once())->method('getId')->willReturn(1); + $this->_oauthSvcMock->expects($this->once())->method('loadConsumer')->willReturn($consumerMock); $this->_messageManager->expects($this->once())->method('addNotice'); $this->_messageManager->expects($this->never())->method('addError'); diff --git a/app/code/Magento/Integration/view/adminhtml/web/js/integration.js b/app/code/Magento/Integration/view/adminhtml/web/js/integration.js index 40aa90c281f1166a23547f4fb7d91e644f1c329f..776339f15c2d72425f53fa802629f4c2e15a4e2f 100644 --- a/app/code/Magento/Integration/view/adminhtml/web/js/integration.js +++ b/app/code/Magento/Integration/view/adminhtml/web/js/integration.js @@ -133,11 +133,11 @@ define([ TOP: screen.height - 510 - 300 }, - invokePopup: function (identityCallbackUrl, consumerId, jqInfoDialog) { + invokePopup: function (identityCallbackUrl, consumerKey, jqInfoDialog) { // Callback should be invoked only once. Reset callback flag on subsequent invocations. IdentityLogin.isCalledBack = false; IdentityLogin.jqInfoDialog = jqInfoDialog; - var param = $.param({"consumer_id": consumerId, "success_call_back": IdentityLogin.successCallbackUrl}); + var param = $.param({"oauth_consumer_key": consumerKey, "success_call_back": IdentityLogin.successCallbackUrl}); IdentityLogin.win = window.open(identityCallbackUrl + '?' + param, '', 'top=' + IdentityLogin.Constants.TOP + ', left=' + IdentityLogin.Constants.LEFT + @@ -205,7 +205,7 @@ define([ } var identityLinkUrl = null, - consumerId = null, + consumerKey = null, popupHtml = null, popup = $('#integration-popup-container'); @@ -215,15 +215,15 @@ define([ result; identityLinkUrl = resultObj['identity_link_url']; - consumerId = resultObj['consumer_id']; + consumerKey = resultObj['oauth_consumer_key']; popupHtml = resultObj['popup_content']; } catch (e) { //This is expected if result is not json. Do nothing. } - if (identityLinkUrl && consumerId && popupHtml) { - IdentityLogin.invokePopup(identityLinkUrl, consumerId, popup); + if (identityLinkUrl && consumerKey && popupHtml) { + IdentityLogin.invokePopup(identityLinkUrl, consumerKey, popup); } else { popupHtml = result; } diff --git a/app/code/Magento/ProductVideo/view/adminhtml/templates/helper/gallery.phtml b/app/code/Magento/ProductVideo/view/adminhtml/templates/helper/gallery.phtml index f57ba1ce79e1ed0680ae4bfd83a02f770494679c..806b4a75d377efa73cc41ceb7ae5faf698f8a639 100755 --- a/app/code/Magento/ProductVideo/view/adminhtml/templates/helper/gallery.phtml +++ b/app/code/Magento/ProductVideo/view/adminhtml/templates/helper/gallery.phtml @@ -37,7 +37,7 @@ $elementToggleCode = $element->getToggleCode() ? $element->getToggleCode() : 'to data-types="<?php echo $block->escapeHtml( $this->helper('Magento\Framework\Json\Helper\Data')->jsonEncode($block->getImageTypes()) ) ?>" - > +> <?php if (!$block->getElement()->getReadonly()): @@ -47,7 +47,9 @@ $elementToggleCode = $element->getToggleCode() ? $element->getToggleCode() : 'to ?> <div class="product-image-wrapper"> <p class="image-placeholder-text"> - <?php /* @noEscape */ echo __('Browse to find or drag image here'); ?> + <?php echo $block->escapeHtml( + __('Browse to find or drag image here') + ); ?> </p> </div> </div> @@ -141,32 +143,42 @@ $elementToggleCode = $element->getToggleCode() ? $element->getToggleCode() : 'to class="action-remove" data-role="delete-button" title="<% if (data.media_type == 'external-video') {%> - <?php /* @noEscape */echo __('Delete video') ?> + <?php echo $block->escapeHtml( + __('Delete video') + ); ?> <%} else {%> - <?php /* @noEscape */ echo __('Delete image') ?> + <?php echo $block->escapeHtml( + __('Delete image') + ); ?> <%}%>"> <span> <% if (data.media_type == 'external-video') { %> - <?php /* @noEscape */ echo __('Delete video') ?> + <?php echo $block->escapeHtml( + __('Delete video') + ); ?> <% } else {%> - <?php /* @noEscape */ echo __('Delete image') ?> + <?php echo $block->escapeHtml( + __('Delete image') + ); ?> <%} %> </span> </button> <div class="draggable-handle"></div> </div> - <div class="image-fade"><span><?php /* @noEscape */ echo __('Hidden') ?></span></div> + <div class="image-fade"><span><?php echo $block->escapeHtml( + __('Hidden') + ); ?></span></div> </div> <div class="item-description"> - <% if (data.media_type !== 'external-video') {%> + <% if (data.media_type !== 'external-video') {%> <div class="item-title" data-role="img-title"><%- data.label %></div> <div class="item-size"> - <span data-role="image-dimens"></span>, <span data-role="image-size"><%- data.sizeLabel %></span> - </div> - <% } else { %> + <span data-role="image-dimens"></span>, <span data-role="image-size"><%- data.sizeLabel %></span> + </div> + <% } else { %> <div class="item-title" data-role="img-title"><%- data.video_title %></div> - <% } %> + <% } %> </div> <ul class="item-roles" data-role="roles-labels"> @@ -188,114 +200,126 @@ $elementToggleCode = $element->getToggleCode() ? $element->getToggleCode() : 'to </script> <script data-role="img-dialog-container-tmpl" type="text/x-magento-template"> - <div class="image-panel" data-role="dialog"> - </div> + <div class="image-panel" data-role="dialog"> + </div> </script> <script data-role="img-dialog-tmpl" type="text/x-magento-template"> - <div class="image-panel-preview"> - <img src="<%- data.url %>" alt="<%- data.label %>" /> - </div> - <div class="image-panel-controls"> - <strong class="image-name"><%- data.label %></strong> + <div class="image-panel-preview"> + <img src="<%- data.url %>" alt="<%- data.label %>" /> + </div> + <div class="image-panel-controls"> + <strong class="image-name"><%- data.label %></strong> - <fieldset class="admin__fieldset fieldset-image-panel"> - <div class="admin__field field-image-description"> - <label class="admin__field-label" for="image-description"> - <span><?php /* @escapeNotVerified */ echo __('Alt Text')?></span> - </label> + <fieldset class="admin__fieldset fieldset-image-panel"> + <div class="admin__field field-image-description"> + <label class="admin__field-label" for="image-description"> + <span><?php /* @escapeNotVerified */ echo __('Alt Text')?></span> + </label> - <div class="admin__field-control"> + <div class="admin__field-control"> <textarea data-role="image-description" rows="3" class="admin__control-textarea" name="<?php /* @escapeNotVerified */ echo $elementName ?>[<%- data.file_id %>][label]"><%- data.label %></textarea> - </div> </div> + </div> - <div class="admin__field field-image-role"> - <label class="admin__field-label"> - <span><?php /* @noEscape */ echo __('Role')?></span> - </label> - <div class="admin__field-control"> - <ul class="multiselect-alt"> - <?php - foreach ($block->getMediaAttributes() as $attribute) : - ?> - <li class="item"> - <label> - <input class="image-type" - data-role="type-selector" - data-form-part="<?php /* @escapeNotVerified */ echo $formName ?>" - type="checkbox" - value="<?php echo $block->escapeHtml( - $attribute->getAttributeCode() - ) ?>" - /> - <?php /* @escapeNotVerified */ echo $block->escapeHtml( - $attribute->getFrontendLabel() - ) ?> - </label> - </li> - <?php - endforeach; + <div class="admin__field field-image-role"> + <label class="admin__field-label"> + <span><?php echo $block->escapeHtml( + __('Role') + ); ?></span> + </label> + <div class="admin__field-control"> + <ul class="multiselect-alt"> + <?php + foreach ($block->getMediaAttributes() as $attribute) : ?> - </ul> - </div> + <li class="item"> + <label> + <input class="image-type" + data-role="type-selector" + data-form-part="<?php /* @escapeNotVerified */ echo $formName ?>" + type="checkbox" + value="<?php echo $block->escapeHtml( + $attribute->getAttributeCode() + ) ?>" + /> + <?php /* @escapeNotVerified */ echo $block->escapeHtml( + $attribute->getFrontendLabel() + ) ?> + </label> + </li> + <?php + endforeach; + ?> + </ul> </div> + </div> - <div class="admin__field admin__field-inline field-image-size" data-role="size"> - <label class="admin__field-label"> - <span><?php /* @escapeNotVerified */ echo __('Image Size') ?></span> - </label> - <div class="admin__field-value" data-message="<?php /* @escapeNotVerified */ echo __('{size}') ?>"></div> - </div> + <div class="admin__field admin__field-inline field-image-size" data-role="size"> + <label class="admin__field-label"> + <span><?php /* @escapeNotVerified */ echo __('Image Size') ?></span> + </label> + <div class="admin__field-value" data-message="<?php /* @escapeNotVerified */ echo __('{size}') ?>"></div> + </div> - <div class="admin__field admin__field-inline field-image-resolution" data-role="resolution"> - <label class="admin__field-label"> - <span><?php /* @escapeNotVerified */ echo __('Image Resolution') ?></span> - </label> - <div class="admin__field-value" data-message="<?php /* @escapeNotVerified */ echo __('{width}^{height} px') ?>"></div> - </div> + <div class="admin__field admin__field-inline field-image-resolution" data-role="resolution"> + <label class="admin__field-label"> + <span><?php /* @escapeNotVerified */ echo __('Image Resolution') ?></span> + </label> + <div class="admin__field-value" data-message="<?php /* @escapeNotVerified */ echo __('{width}^{height} px') ?>"></div> + </div> - <div class="admin__field field-image-hide"> - <div class="admin__field-control"> - <div class="admin__field admin__field-option"> - <input type="checkbox" - id="hide-from-product-page" - data-role="visibility-trigger" - data-form-part="<?php /* @escapeNotVerified */ echo $formName ?>" - value="1" - class="admin__control-checkbox" - name="<?php /* @escapeNotVerified */ echo $elementName ?>[<%- data.file_id %>][disabled]" - <% if (data.disabled == 1) { %>checked="checked"<% } %> /> + <div class="admin__field field-image-hide"> + <div class="admin__field-control"> + <div class="admin__field admin__field-option"> + <input type="checkbox" + id="hide-from-product-page" + data-role="visibility-trigger" + data-form-part="<?php /* @escapeNotVerified */ echo $formName ?>" + value="1" + class="admin__control-checkbox" + name="<?php /* @escapeNotVerified */ echo $elementName ?>[<%- data.file_id %>][disabled]" + <% if (data.disabled == 1) { %>checked="checked"<% } %> /> - <label for="hide-from-product-page" class="admin__field-label"> - <?php /* @noEscape */ echo __('Hide from Product Page')?> - </label> - </div> + <label for="hide-from-product-page" class="admin__field-label"> + <?php echo $block->escapeHtml( + __('Hide from Product Page') + ); ?> + </label> </div> </div> - </fieldset> - </div> + </div> + </fieldset> + </div> </script> <div id="<?php /* @noEscape */ echo $block->getNewVideoBlockName();?>" style="display:none"> <?php /* @escapeNotVerified */ echo $block->getFormHtml();?> <div id="video-player-preview-location" class="video-player-sidebar"> <div class="video-player-container"></div> <div class="video-information title"> - <label><?php /* @noEscape */ echo __('Title:') ?> </label><span></span> + <label><?php echo $block->escapeHtml( + __('Title:') + ); ?> </label><span></span> </div> <div class="video-information uploaded"> - <label><?php /* @noEscape */ echo __('Uploaded:') ?> </label><span></span> + <label><?php echo $block->escapeHtml( + __('Uploaded:') + ); ?> </label><span></span> </div> <div class="video-information uploader"> - <label><?php /* @noEscape */ echo __('Uploader:') ?> </label><span></span> + <label><?php echo $block->escapeHtml( + __('Uploader:') + ); ?> </label><span></span> </div> <div class="video-information duration"> - <label><?php /* @noEscape */ echo __('Duration:') ?> </label><span></span> + <label><?php echo $block->escapeHtml( + __('Duration:') + ); ?> </label><span></span> </div> </div> </div> @@ -305,4 +329,3 @@ $elementToggleCode = $element->getToggleCode() ? $element->getToggleCode() : 'to <script> jQuery('body').trigger('contentUpdated'); </script> - diff --git a/app/code/Magento/Quote/Model/Cart/TotalsConverter.php b/app/code/Magento/Quote/Model/Cart/TotalsConverter.php index f0f61ea2439ac97105eff0b1b0525cedd631e3df..f196493e27bc405aed53ee50106154443de9eb60 100644 --- a/app/code/Magento/Quote/Model/Cart/TotalsConverter.php +++ b/app/code/Magento/Quote/Model/Cart/TotalsConverter.php @@ -27,7 +27,6 @@ class TotalsConverter $this->factory = $factory; } - /** * @param \Magento\Quote\Model\Quote\Address\Total[] $addressTotals * @return \Magento\Quote\Api\Data\TotalSegmentInterface[] @@ -44,7 +43,7 @@ class TotalsConverter TotalSegmentInterface::AREA => $addressTotal->getArea(), ]; if (is_object($addressTotal->getTitle())) { - $pureData[TotalSegmentInterface::TITLE] = $addressTotal->getTitle()->getText(); + $pureData[TotalSegmentInterface::TITLE] = $addressTotal->getTitle()->render(); } /** @var \Magento\Quote\Model\Cart\TotalSegment $total */ $total = $this->factory->create(); diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/Collection.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/Collection.php new file mode 100644 index 0000000000000000000000000000000000000000..d5c0689c140225ebcf3e743602e48a432b0bf3f4 --- /dev/null +++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Grid/Collection.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Model\ResourceModel\Order\Creditmemo\Grid; + +use Magento\Framework\Data\Collection\Db\FetchStrategyInterface as FetchStrategy; +use Magento\Framework\Data\Collection\EntityFactoryInterface as EntityFactory; +use Magento\Framework\Event\ManagerInterface as EventManager; +use Psr\Log\LoggerInterface as Logger; + +class Collection extends \Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult +{ + /** + * Initialize dependencies. + * + * @param EntityFactory $entityFactory + * @param Logger $logger + * @param FetchStrategy $fetchStrategy + * @param EventManager $eventManager + * @param string $mainTable + * @param string $resourceModel + */ + public function __construct( + EntityFactory $entityFactory, + Logger $logger, + FetchStrategy $fetchStrategy, + EventManager $eventManager, + $mainTable = 'sales_creditmemo_grid', + $resourceModel = '\Magento\Sales\Model\ResourceModel\Order\Creditmemo' + ) { + parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $mainTable, $resourceModel); + } +} diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/Collection.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/Collection.php new file mode 100644 index 0000000000000000000000000000000000000000..4455879910ac83ddade0510937a61584773606ee --- /dev/null +++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Creditmemo/Order/Grid/Collection.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Model\ResourceModel\Order\Creditmemo\Order\Grid; + +use Magento\Framework\Data\Collection\Db\FetchStrategyInterface as FetchStrategy; +use Magento\Framework\Data\Collection\EntityFactoryInterface as EntityFactory; +use Magento\Framework\Event\ManagerInterface as EventManager; +use Psr\Log\LoggerInterface as Logger; + +class Collection extends \Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult +{ + /** + * Initialize dependencies. + * + * @param EntityFactory $entityFactory + * @param Logger $logger + * @param FetchStrategy $fetchStrategy + * @param EventManager $eventManager + * @param string $mainTable + * @param string $resourceModel + */ + public function __construct( + EntityFactory $entityFactory, + Logger $logger, + FetchStrategy $fetchStrategy, + EventManager $eventManager, + $mainTable = 'sales_creditmemo_grid', + $resourceModel = '\Magento\Sales\Model\ResourceModel\Order\Creditmemo' + ) { + parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $mainTable, $resourceModel); + } +} diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Invoice/Grid/Collection.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Invoice/Grid/Collection.php new file mode 100644 index 0000000000000000000000000000000000000000..97a8cda9ab1eb2b3e64a73682dd4971189a2ccb6 --- /dev/null +++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Invoice/Grid/Collection.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Model\ResourceModel\Order\Invoice\Grid; + +use Magento\Framework\Data\Collection\Db\FetchStrategyInterface as FetchStrategy; +use Magento\Framework\Data\Collection\EntityFactoryInterface as EntityFactory; +use Magento\Framework\Event\ManagerInterface as EventManager; +use Psr\Log\LoggerInterface as Logger; + +class Collection extends \Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult +{ + /** + * Initialize dependencies. + * + * @param EntityFactory $entityFactory + * @param Logger $logger + * @param FetchStrategy $fetchStrategy + * @param EventManager $eventManager + * @param string $mainTable + * @param string $resourceModel + */ + public function __construct( + EntityFactory $entityFactory, + Logger $logger, + FetchStrategy $fetchStrategy, + EventManager $eventManager, + $mainTable = 'sales_invoice_grid', + $resourceModel = '\Magento\Sales\Model\ResourceModel\Order\Invoice' + ) { + parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $mainTable, $resourceModel); + } +} diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Invoice/Orders/Grid/Collection.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Invoice/Orders/Grid/Collection.php new file mode 100644 index 0000000000000000000000000000000000000000..ae4788c4daea365854e698c25a3041d089d528eb --- /dev/null +++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Invoice/Orders/Grid/Collection.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Model\ResourceModel\Order\Invoice\Orders\Grid; + +use Magento\Framework\Data\Collection\Db\FetchStrategyInterface as FetchStrategy; +use Magento\Framework\Data\Collection\EntityFactoryInterface as EntityFactory; +use Magento\Framework\Event\ManagerInterface as EventManager; +use Psr\Log\LoggerInterface as Logger; + +class Collection extends \Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult +{ + /** + * Initialize dependencies. + * + * @param EntityFactory $entityFactory + * @param Logger $logger + * @param FetchStrategy $fetchStrategy + * @param EventManager $eventManager + * @param string $mainTable + * @param string $resourceModel + */ + public function __construct( + EntityFactory $entityFactory, + Logger $logger, + FetchStrategy $fetchStrategy, + EventManager $eventManager, + $mainTable = 'sales_invoice_grid', + $resourceModel = '\Magento\Sales\Model\ResourceModel\Order\Invoice' + ) { + parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $mainTable, $resourceModel); + } +} diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Shipment/Grid/Collection.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Shipment/Grid/Collection.php new file mode 100644 index 0000000000000000000000000000000000000000..f3141f521623fdb35e0f5e921636bdb68ae9e2cb --- /dev/null +++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Shipment/Grid/Collection.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Model\ResourceModel\Order\Shipment\Grid; + +use Magento\Framework\Data\Collection\Db\FetchStrategyInterface as FetchStrategy; +use Magento\Framework\Data\Collection\EntityFactoryInterface as EntityFactory; +use Magento\Framework\Event\ManagerInterface as EventManager; +use Psr\Log\LoggerInterface as Logger; + +class Collection extends \Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult +{ + /** + * Initialize dependencies. + * + * @param EntityFactory $entityFactory + * @param Logger $logger + * @param FetchStrategy $fetchStrategy + * @param EventManager $eventManager + * @param string $mainTable + * @param string $resourceModel + */ + public function __construct( + EntityFactory $entityFactory, + Logger $logger, + FetchStrategy $fetchStrategy, + EventManager $eventManager, + $mainTable = 'sales_shipment_grid', + $resourceModel = '\Magento\Sales\Model\ResourceModel\Order\Shipment' + ) { + parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $mainTable, $resourceModel); + } +} diff --git a/app/code/Magento/Sales/Model/ResourceModel/Order/Shipment/Order/Grid/Collection.php b/app/code/Magento/Sales/Model/ResourceModel/Order/Shipment/Order/Grid/Collection.php new file mode 100644 index 0000000000000000000000000000000000000000..941b510a7f6320fe978a50904ef0cc74b99e85c5 --- /dev/null +++ b/app/code/Magento/Sales/Model/ResourceModel/Order/Shipment/Order/Grid/Collection.php @@ -0,0 +1,36 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Sales\Model\ResourceModel\Order\Shipment\Order\Grid; + +use Magento\Framework\Data\Collection\Db\FetchStrategyInterface as FetchStrategy; +use Magento\Framework\Data\Collection\EntityFactoryInterface as EntityFactory; +use Magento\Framework\Event\ManagerInterface as EventManager; +use Psr\Log\LoggerInterface as Logger; + +class Collection extends \Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult +{ + /** + * Initialize dependencies. + * + * @param EntityFactory $entityFactory + * @param Logger $logger + * @param FetchStrategy $fetchStrategy + * @param EventManager $eventManager + * @param string $mainTable + * @param string $resourceModel + */ + public function __construct( + EntityFactory $entityFactory, + Logger $logger, + FetchStrategy $fetchStrategy, + EventManager $eventManager, + $mainTable = 'sales_shipment_grid', + $resourceModel = '\Magento\Sales\Model\ResourceModel\Order\Shipment' + ) { + parent::__construct($entityFactory, $logger, $fetchStrategy, $eventManager, $mainTable, $resourceModel); + } +} diff --git a/app/code/Magento/Sales/etc/di.xml b/app/code/Magento/Sales/etc/di.xml index 32c1a17c90dfefc4a75e7c21abda71fb0ac3d2eb..209e46c3240b675f32622f3547331856bf87a1eb 100644 --- a/app/code/Magento/Sales/etc/di.xml +++ b/app/code/Magento/Sales/etc/di.xml @@ -780,42 +780,6 @@ <argument name="state" xsi:type="object">Magento\Framework\App\State\Proxy</argument> </arguments> </type> - <virtualType name="Magento\Sales\Model\ResourceModel\Order\Invoice\Grid\Collection" type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult"> - <arguments> - <argument name="mainTable" xsi:type="string">sales_invoice_grid</argument> - <argument name="resourceModel" xsi:type="string">Magento\Sales\Model\ResourceModel\Order\Invoice</argument> - </arguments> - </virtualType> - <virtualType name="Magento\Sales\Model\ResourceModel\Order\Shipment\Grid\Collection" type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult"> - <arguments> - <argument name="mainTable" xsi:type="string">sales_shipment_grid</argument> - <argument name="resourceModel" xsi:type="string">Magento\Sales\Model\ResourceModel\Order\Shipment</argument> - </arguments> - </virtualType> - <virtualType name="Magento\Sales\Model\ResourceModel\Order\Creditmemo\Grid\Collection" type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult"> - <arguments> - <argument name="mainTable" xsi:type="string">sales_creditmemo_grid</argument> - <argument name="resourceModel" xsi:type="string">Magento\Sales\Model\ResourceModel\Order\Creditmemo</argument> - </arguments> - </virtualType> - <virtualType name="Magento\Sales\Model\ResourceModel\Order\Invoice\Orders\Grid\Collection" type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult"> - <arguments> - <argument name="mainTable" xsi:type="string">sales_invoice_grid</argument> - <argument name="resourceModel" xsi:type="string">Magento\Sales\Model\ResourceModel\Order\Invoice</argument> - </arguments> - </virtualType> - <virtualType name="Magento\Sales\Model\ResourceModel\Order\Shipment\Order\Grid\Collection" type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult"> - <arguments> - <argument name="mainTable" xsi:type="string">sales_shipment_grid</argument> - <argument name="resourceModel" xsi:type="string">Magento\Sales\Model\ResourceModel\Order\Shipment</argument> - </arguments> - </virtualType> - <virtualType name="Magento\Sales\Model\ResourceModel\Order\Creditmemo\Order\Grid\Collection" type="Magento\Framework\View\Element\UiComponent\DataProvider\SearchResult"> - <arguments> - <argument name="mainTable" xsi:type="string">sales_creditmemo_grid</argument> - <argument name="resourceModel" xsi:type="string">Magento\Sales\Model\ResourceModel\Order\Creditmemo</argument> - </arguments> - </virtualType> <virtualType name="orderMetadata" type="Magento\Sales\Model\ResourceModel\Metadata"> <arguments> <argument name="resourceClassName" xsi:type="string">Magento\Sales\Model\ResourceModel\Order</argument> diff --git a/app/code/Magento/Tax/Model/Config/Price/IncludePrice.php b/app/code/Magento/Tax/Model/Config/Price/IncludePrice.php index 3a3c9b2b3bc680d628237abe167cdc74719749ac..40030a70e62b8ed7c833b945d6e91382b3949bb4 100644 --- a/app/code/Magento/Tax/Model/Config/Price/IncludePrice.php +++ b/app/code/Magento/Tax/Model/Config/Price/IncludePrice.php @@ -8,11 +8,13 @@ namespace Magento\Tax\Model\Config\Price; class IncludePrice extends \Magento\Framework\App\Config\Value { /** - * @return void + * @return $this */ public function afterSave() { - parent::afterSave(); + $result = parent::afterSave(); $this->_cacheManager->clean(['checkout_quote']); + + return $result; } } diff --git a/app/code/Magento/Theme/view/base/requirejs-config.js b/app/code/Magento/Theme/view/base/requirejs-config.js index 6d71b3b36d13f792b4e557b0a7a3a89e5b9755e9..abe587777dd9c0f0b786faffcb09686d3f6378a4 100644 --- a/app/code/Magento/Theme/view/base/requirejs-config.js +++ b/app/code/Magento/Theme/view/base/requirejs-config.js @@ -51,7 +51,14 @@ var config = { }, "deps": [ "jquery/jquery-migrate" - ] + ], + "config": { + "mixins": { + "jquery/jstree/jquery.jstree": { + "mage/backend/jstree-mixin": true + } + } + } }; require(['jquery'], function ($) { diff --git a/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js b/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js index 6d7c937f62ee051f7994ab7a54b4464bfa2f4d02..b3db5d11b98a51bc166082a10ae351949f317d9c 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js +++ b/app/code/Magento/Ui/view/base/web/js/form/element/wysiwyg.js @@ -2,6 +2,7 @@ * Copyright © 2016 Magento. All rights reserved. * See COPYING.txt for license details. */ + define([ 'Magento_Ui/js/lib/view/utils/async', 'underscore', diff --git a/app/code/Magento/Ui/view/base/web/templates/form/components/single/radio.html b/app/code/Magento/Ui/view/base/web/templates/form/components/single/radio.html index 0cd5828e6ce5c9d2ad20357326e4cfd92ea10d99..0328957c8f6efa6df49c990f9f23571b02e7efba 100644 --- a/app/code/Magento/Ui/view/base/web/templates/form/components/single/radio.html +++ b/app/code/Magento/Ui/view/base/web/templates/form/components/single/radio.html @@ -12,7 +12,7 @@ ko-focused="focused" ko-value="value" keyboard="keyboard" - attr="id: uid, name: inputName"/> + attr="id: uid, name: inputName, 'data-index': index"/> <label class="admin__field-label" text="description" attr="for: uid"/> </div> diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Cart/Item.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Cart/Item.php index ee78eb61c5572f132017810cf6ed54d81f1eee78..cb46e728191bffb5a770a2809019fb2833f9f0d3 100644 --- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Cart/Item.php +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Fixture/Cart/Item.php @@ -53,7 +53,7 @@ class Item extends \Magento\Catalog\Test\Fixture\Cart\Item $bundleOptions = $bundleSelection['bundle_options'][$attributeKey]; $value = $bundleSelectionAttribute[$optionKey]->getName(); $qty = $bundleOptions['assigned_products'][$optionKey]['data']['selection_qty']; - $price = $product->getPriceType() == 'Dynamic' + $price = $product->getPriceType() == 'Yes' ? number_format($bundleSelectionAttribute[$optionKey]->getPrice(), 2) : number_format($bundleOptions['assigned_products'][$optionKey]['data']['selection_price_value'], 2); $optionData = [ diff --git a/dev/tests/functional/tests/app/Magento/Bundle/Test/Handler/BundleProduct/Curl.php b/dev/tests/functional/tests/app/Magento/Bundle/Test/Handler/BundleProduct/Curl.php index 28fb86de9ffeb2e193177b9eda6282710bb43135..4a4aea603cf8619d0d12335f496b1e6a9e50fd33 100644 --- a/dev/tests/functional/tests/app/Magento/Bundle/Test/Handler/BundleProduct/Curl.php +++ b/dev/tests/functional/tests/app/Magento/Bundle/Test/Handler/BundleProduct/Curl.php @@ -98,7 +98,7 @@ class Curl extends ProductCurl implements BundleProductInterface parent::prepareProductDetails(); if (!isset($this->fields['product']['price_type'])) { - $this->fields['product']['price_type'] = 'Dynamic'; + $this->fields['product']['price_type'] = 'Yes'; } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/AttributeForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/AttributeForm.php index 5568040980de8c3a3b3660ceb77f10a04d54ce17..ad4d946f850347d987870594aa4201df27970381 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/AttributeForm.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/AttributeForm.php @@ -6,25 +6,15 @@ namespace Magento\Catalog\Test\Block\Adminhtml\Product\Attribute; -use Magento\Backend\Test\Block\Widget\FormTabs; -use Magento\Backend\Test\Block\Widget\Tab; -use Magento\Mtf\Client\Element; +use Magento\Ui\Test\Block\Adminhtml\FormSections; use Magento\Mtf\Client\Element\SimpleElement; -use Magento\Mtf\Client\Locator; use Magento\Mtf\Fixture\FixtureInterface; /** * Edit attribute form on catalog product edit page. */ -class AttributeForm extends FormTabs +class AttributeForm extends FormSections { - /** - * Iframe locator. - * - * @var string - */ - protected $iFrame = '#create_new_attribute_container'; - /** * Save button selector. * @@ -32,24 +22,6 @@ class AttributeForm extends FormTabs */ protected $saveButton = '#save'; - /** - * Attribute to determine whether tab is opened. - * - * @var string - */ - protected $isTabOpened = '.opened '; - - /** - * Initialize block. Switch to frame. - * - * @return void - */ - protected function init() - { - parent::init(); - $this->browser->switchToFrame(new Locator($this->iFrame)); - } - /** * Fill the attribute form. * @@ -67,28 +39,6 @@ class AttributeForm extends FormTabs } ); parent::fill($fixture, $element); - $this->browser->switchToFrame(); - } - - /** - * Open tab. - * - * @param string $tabName - * @return Tab - */ - public function openTab($tabName) - { - $selector = $this->getTabs()[$tabName]['selector']; - $strategy = isset($this->getTabs()[$tabName]['strategy']) - ? $this->getTabs()[$tabName]['strategy'] - : Locator::SELECTOR_CSS; - - $isTabOpened = $this->_rootElement->find($this->isTabOpened . $selector, $strategy); - if (!$isTabOpened->isVisible()) { - $this->_rootElement->find($selector, $strategy)->click(); - } - - return $this; } /** diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/AttributeForm.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/AttributeForm.xml index 5c5cf01bd9b907c70381ff9ecd2b729f046e73b4..bd1354d51a28cd1277714aab54849dae53de9c05 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/AttributeForm.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/AttributeForm.xml @@ -5,10 +5,10 @@ * See COPYING.txt for license details. */ --> -<tabs> +<sections> <properties> - <class>\Magento\Backend\Test\Block\Widget\Tab</class> - <selector>#edit_form</selector> + <class>\Magento\Ui\Test\Block\Adminhtml\Section</class> + <selector>.product_form_product_form_add_attribute_modal_create_new_attribute_modal_product_attribute_add_form</selector> <strategy>css selector</strategy> <fields> <frontend_label> @@ -18,36 +18,32 @@ <input>select</input> </frontend_input> <is_required> - <input>select</input> + <input>switcher</input> </is_required> <options> <class>\Magento\Catalog\Test\Block\Adminhtml\Product\Attribute\Edit\Options</class> - <selector>#manage-options-panel</selector> + <selector>[data-index="attribute_options_select_container"]</selector> <strategy>css selector</strategy> </options> </fields> </properties> <advanced-properties> - <class>\Magento\Backend\Test\Block\Widget\Tab</class> - <selector>[data-target="#advanced_fieldset-content"]</selector> + <class>\Magento\Ui\Test\Block\Adminhtml\Section</class> + <selector>[data-index="advanced_fieldset"]</selector> <strategy>css selector</strategy> <fields> - <attribute_code> - </attribute_code> + <attribute_code/> <is_global> <input>select</input> </is_global> - <default_value> - <selector>[name^='default_value_']</selector> - </default_value> <is_unique> - <input>select</input> + <input>switcher</input> </is_unique> </fields> </advanced-properties> <manage-labels> - <class>\Magento\Backend\Test\Block\Widget\Tab</class> - <selector>[data-target="#manage-titles-content"]</selector> + <class>\Magento\Ui\Test\Block\Adminhtml\Section</class> + <selector>[data-index="manage-titles"]</selector> <strategy>css selector</strategy> <fields> <manage_frontend_label> @@ -56,40 +52,40 @@ </fields> </manage-labels> <frontend-properties> - <class>\Magento\Backend\Test\Block\Widget\Tab</class> - <selector>[data-target="#front_fieldset-content"]</selector> + <class>\Magento\Ui\Test\Block\Adminhtml\Section</class> + <selector>[data-index="front_fieldset"]</selector> <strategy>css selector</strategy> <fields> <is_searchable> - <input>select</input> + <input>switcher</input> </is_searchable> <is_visible_in_advanced_search> - <input>select</input> + <input>switcher</input> </is_visible_in_advanced_search> <is_comparable> - <input>select</input> + <input>switcher</input> </is_comparable> <is_filterable> <input>select</input> </is_filterable> <is_filterable_in_search> - <input>select</input> + <input>switcher</input> </is_filterable_in_search> <is_used_for_promo_rules> - <input>select</input> + <input>switcher</input> </is_used_for_promo_rules> <is_html_allowed_on_front> - <input>select</input> + <input>switcher</input> </is_html_allowed_on_front> <is_visible_on_front> - <input>select</input> + <input>switcher</input> </is_visible_on_front> <used_in_product_listing> - <input>select</input> + <input>switcher</input> </used_in_product_listing> <used_for_sort_by> - <input>select</input> + <input>switcher</input> </used_for_sort_by> </fields> </frontend-properties> -</tabs> +</sections> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/CustomAttribute.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/CustomAttribute.php index 926d04335665cf35ffb7e6c23786bcfd13a56319..91d722f8ef4eb3e3404214a5827c74b76bb48eb3 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/CustomAttribute.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/CustomAttribute.php @@ -19,7 +19,7 @@ class CustomAttribute extends SimpleElement * * @var string */ - protected $inputSelector = '.control [name]:not([type="hidden"]), table'; + protected $inputSelector = '[name="product[%s]"]'; /** * Attribute class to element type reference. @@ -27,11 +27,12 @@ class CustomAttribute extends SimpleElement * @var array */ protected $classReference = [ - 'input-text' => null, + 'admin__control-text' => null, 'textarea' => null, 'hasDatepicker' => 'datepicker', - 'select' => 'select', - 'multiselect' => 'multiselect', + 'admin__control-select' => 'select', + 'admin__control-multiselect' => 'multiselect', + 'admin__actions-switch-checkbox' => 'switcher' ]; /** @@ -43,10 +44,11 @@ class CustomAttribute extends SimpleElement public function setValue($data) { $this->eventManager->dispatchEvent(['set_value'], [__METHOD__, $this->getAbsoluteSelector()]); - $element = $this->getElementByClass($this->getElementClass()); + $code = isset($data['code']) ? $data['code'] : $this->getAttributeCode($this->getAbsoluteSelector()); + $element = $this->getElementByClass($this->getElementClass($code)); $value = is_array($data) ? $data['value'] : $data; if ($value !== null) { - $this->find($this->inputSelector, Locator::SELECTOR_CSS, $element)->setValue($value); + $this->find(sprintf($this->inputSelector, $code), Locator::SELECTOR_CSS, $element)->setValue($value); } } @@ -58,8 +60,9 @@ class CustomAttribute extends SimpleElement public function getValue() { $this->eventManager->dispatchEvent(['get_value'], [__METHOD__, $this->getAbsoluteSelector()]); - $inputType = $this->getElementByClass($this->getElementClass()); - return $this->find($this->inputSelector, Locator::SELECTOR_CSS, $inputType)->getValue(); + $code = $this->getAttributeCode($this->getAbsoluteSelector()); + $inputType = $this->getElementByClass($this->getElementClass($code)); + return $this->find(sprintf($this->inputSelector, $code), Locator::SELECTOR_CSS, $inputType)->getValue(); } /** @@ -68,7 +71,7 @@ class CustomAttribute extends SimpleElement * @param string $class * @return string */ - protected function getElementByClass($class) + private function getElementByClass($class) { $element = null; foreach ($this->classReference as $key => $reference) { @@ -82,10 +85,25 @@ class CustomAttribute extends SimpleElement /** * Get element class. * + * @param string $code * @return string */ - protected function getElementClass() + private function getElementClass($code) { - return $this->find($this->inputSelector, Locator::SELECTOR_CSS)->getAttribute('class'); + return $this->find(sprintf($this->inputSelector, $code), Locator::SELECTOR_CSS)->getAttribute('class'); + } + + /** + * Get attribute code. + * + * @param string $attributeSelector + * @return string + */ + private function getAttributeCode($attributeSelector) + { + preg_match('/data-index="(.*)"/', $attributeSelector, $matches); + $code = !empty($matches[1]) ? $matches[1] : ''; + + return $code; } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Edit/Options.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Edit/Options.php index 657166f1e184928c0cde9ac35c2bf35be7827f76..8c1f41f907e4889a7f9769ddcfe2d0f3da2502e6 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Edit/Options.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Attribute/Edit/Options.php @@ -20,14 +20,14 @@ class Options extends SimpleElement * * @var string */ - protected $addOption = '#add_new_option_button'; + protected $addOption = 'button[data-action="add_new_row"]'; /** * Option form selector. * * @var string */ - protected $option = '.ui-sortable tr'; + protected $option = '[data-index="attribute_options_select"] tbody tr'; /** * Set value. diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/Attributes.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/Attributes.php index 4070630c913262ef332937834b506c5d50fc87b9..68bf3fe0d5069fd3eee1a3f6c480e70c7f4f3d68 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/Attributes.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/Attributes.php @@ -6,8 +6,6 @@ namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Section; -use Magento\Mtf\Client\Locator; -use Magento\Catalog\Test\Block\Adminhtml\Product\Attribute\Edit; use Magento\Ui\Test\Block\Adminhtml\Section; /** @@ -15,27 +13,6 @@ use Magento\Ui\Test\Block\Adminhtml\Section; */ class Attributes extends Section { - /** - * Attribute Search locator the Product page. - * - * @var string - */ - protected $attributeSearch = "//div[contains(@data-role, 'product-details')]//*[@data-toggle='dropdown']/span"; - - /** - * Selector for 'New Attribute' button. - * - * @var string - */ - protected $newAttributeButton = '[id^="create_attribute"]'; - - /** - * Selector for search input field. - * - * @var string - */ - protected $searchAttribute = "//input[@data-role='product-attribute-search']"; - /** * Fixture mapping. * @@ -51,33 +28,4 @@ class Attributes extends Section } return parent::dataMapping($fields, $parent); } - - /** - * Click on 'New Attribute' button. - * - * @param string $tabName - * @return void - */ - public function addNewAttribute($tabName) - { - $element = $this->_rootElement; - $selector = sprintf($this->attributeSearch, $tabName); - $element->waitUntil( - function () use ($element, $selector) { - return $element->find($selector, Locator::SELECTOR_XPATH)->isVisible() ? true : null; - } - ); - $addAttributeToggle = $element->find($selector, Locator::SELECTOR_XPATH); - $addAttributeToggle->click(); - if (!$addAttributeToggle->find($this->newAttributeButton)->isVisible()) { - $element->find($this->searchAttribute, Locator::SELECTOR_XPATH)->click(); - $this->browser->waitUntil( - function () { - $element = $this->browser->find($this->searchAttribute, Locator::SELECTOR_XPATH); - return $element->isVisible() == true ? true : null; - } - ); - } - $element->find($this->newAttributeButton)->click(); - } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/Attributes/Grid.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/Attributes/Grid.php new file mode 100644 index 0000000000000000000000000000000000000000..c10d6c2a18fa7f591496a6f98dd2a70f1662bb5b --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/Attributes/Grid.php @@ -0,0 +1,26 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Section\Attributes; + +use Magento\Ui\Test\Block\Adminhtml\DataGrid; + +/** + * Product attributes grid. + */ +class Grid extends DataGrid +{ + /** + * Grid fields map + * + * @var array + */ + protected $filters = [ + 'label' => [ + 'selector' => '[name="frontend_label"]', + ] + ]; +} diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/Options/Type/DropDown.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/Options/Type/DropDown.php index 1e433a329ec42cc136c1eefc2b984294792c7670..0dfb865d05aae09ee9e18e8278d58ee01b10bb01 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/Options/Type/DropDown.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/Options/Type/DropDown.php @@ -21,13 +21,6 @@ class DropDown extends AbstractOptions */ protected $addValueButton = '[data-action="add_new_row"]'; - /** - * Title column locator. - * - * @var string - */ - protected $optionTitle = '[data-name="title"]'; - /** * Fill the form. * @@ -37,7 +30,6 @@ class DropDown extends AbstractOptions */ public function fillOptions(array $fields, SimpleElement $element = null) { - $this->_rootElement->find($this->optionTitle)->click(); $this->_rootElement->find($this->addValueButton)->click(); return parent::fillOptions($fields, $element); diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/ProductDetails.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/ProductDetails.php index 49c2c786d9afe9663f5cfc7ea08fbe449fd86c52..e0c1df99391052cd9681611eec895db60f790168 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/ProductDetails.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Edit/Section/ProductDetails.php @@ -6,7 +6,6 @@ namespace Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Section; -use Magento\Catalog\Test\Fixture\Category; use Magento\Ui\Test\Block\Adminhtml\Section; use Magento\Mtf\Client\Element\SimpleElement; @@ -21,6 +20,7 @@ class ProductDetails extends Section * @var string */ protected $categoryIds = '.admin__field[data-index="category_ids"]'; + /** * Locator for following sibling of category element. * @@ -28,6 +28,22 @@ class ProductDetails extends Section */ protected $newCategoryRootElement = '.product_form_product_form_create_category_modal'; + /** + * Fixture mapping. + * + * @param array|null $fields + * @param string|null $parent + * @return array + */ + protected function dataMapping(array $fields = null, $parent = null) + { + if (isset($fields['custom_attribute'])) { + $this->placeholders = ['attribute_code' => $fields['custom_attribute']['value']['code']]; + $this->applyPlaceholders(); + } + return parent::dataMapping($fields, $parent); + } + /** * Fill data to fields on section. * diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/FormPageActions.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/FormPageActions.php index 3306bd4f870c6eaf1b8e811db9bf760ae1d47c21..decc7996a7e1e7e97c46fb5d711deb7005dd4bcc 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/FormPageActions.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/FormPageActions.php @@ -51,6 +51,13 @@ class FormPageActions extends ParentFormPageActions */ protected $saveButton = '[data-ui-id="save-button"]'; + /** + * "Add Attribute" button. + * + * @var string + */ + private $addAttribute = '[data-ui-id="addattribute-button"]'; + /** * Click on "Save" button. * @@ -105,4 +112,14 @@ class FormPageActions extends ParentFormPageActions $this->_rootElement->find($this->toggleButton, Locator::SELECTOR_CSS)->click(); $this->_rootElement->find(sprintf($this->saveTypeItem, static::SAVE_CLOSE), Locator::SELECTOR_CSS)->click(); } + + /** + * Click "Add Attribute" button. + * + * @return void + */ + public function addNewAttribute() + { + $this->_rootElement->find($this->addAttribute)->click(); + } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Modal/AddAttribute.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Modal/AddAttribute.php new file mode 100644 index 0000000000000000000000000000000000000000..c30ee5ee9442809a38229bd3a9148fd1123b3b82 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Modal/AddAttribute.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Catalog\Test\Block\Adminhtml\Product\Modal; + +use Magento\Ui\Test\Block\Adminhtml\FormSections; + +/** + * Add new attribute modal. + */ +class AddAttribute extends FormSections +{ + /** + * Selector for "Create New Attribute" button. + * + * @var string + */ + private $createNewAttribute = 'button[data-index="add_new_attribute_button"]'; + + /** + * Click on "Create new attribute" button. + * + * @return void + */ + public function createNewAttribute() + { + $this->_rootElement->find($this->createNewAttribute)->click(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Modal/NewAttribute.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Modal/NewAttribute.php new file mode 100644 index 0000000000000000000000000000000000000000..59e999bf791ad9d453ee6fa2b6e7afa3faa58c76 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/Modal/NewAttribute.php @@ -0,0 +1,32 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Catalog\Test\Block\Adminhtml\Product\Modal; + +use Magento\Ui\Test\Block\Adminhtml\FormSections; + +/** + * Product new attribute modal. + */ +class NewAttribute extends FormSections +{ + /** + * Selector for "Save" button. + * + * @var string + */ + private $save = 'button#save'; + + /** + * Click "Save Attribute" button on attribute form. + * + * @return void + */ + public function saveAttribute() + { + $this->_rootElement->find($this->save)->click(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.php index b0f2b27042b03c54285163f3a03be28ec9dc19eb..24a2a2f7b8c8c1562bbf02180d65ca09a7b602aa 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.php @@ -11,13 +11,9 @@ use Magento\Catalog\Test\Block\Adminhtml\Product\Attribute\AttributeForm; use Magento\Catalog\Test\Block\Adminhtml\Product\Attribute\CustomAttribute; use Magento\Catalog\Test\Fixture\CatalogProductAttribute; use Magento\Mtf\Client\Element\SimpleElement; -use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Section\Attributes; -use Magento\Mtf\Client\Element; use Magento\Mtf\Client\Locator; use Magento\Mtf\Fixture\FixtureInterface; -use Magento\Mtf\Fixture\InjectableFixture; -use Magento\Catalog\Test\Fixture\Category; -use Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Section\Attributes\Search; +use Magento\Ui\Test\Block\Adminhtml\DataGrid; /** * Product form on backend product page. @@ -32,11 +28,11 @@ class ProductForm extends FormSections protected $attribute = './/*[contains(@class,"label")]/span[text()="%s"]'; /** - * Attribute Search locator the Product page. + * Attributes Search modal locator. * * @var string */ - protected $attributeSearch = '#product-attribute-search-container'; + protected $attributeSearch = '.product_form_product_form_add_attribute_modal'; /** * Custom Section locator. @@ -50,28 +46,21 @@ class ProductForm extends FormSections * * @var string */ - protected $attributeBlock = '#attribute-%s-container'; + protected $attributeBlock = '[data-index="%s"]'; /** - * Magento loader. - * - * @var string - */ - protected $loader = '[data-role="loader"]'; - - /** - * New attribute form selector. + * Magento form loader. * * @var string */ - protected $newAttributeForm = '#create_new_attribute'; + protected $spinner = '[data-role="spinner"]'; /** - * Magento form loader. + * New Attribute modal locator. * * @var string */ - protected $spinner = '[data-role="spinner"]'; + protected $newAttributeModal = '.product_form_product_form_add_attribute_modal_create_new_attribute_modal'; /** * Fill the product form. @@ -104,34 +93,11 @@ class ProductForm extends FormSections $sections['product-details']['category_ids']['value'] = $category->getName(); } $this->fillContainers($sections, $element); - - if ($product->hasData('custom_attribute')) { - $this->createCustomAttribute($product); - } } return $this; } - /** - * Create custom attribute. - * - * @param InjectableFixture $product - * @param string $tabName - * @return void - */ - protected function createCustomAttribute(InjectableFixture $product, $tabName = 'product-details') - { - $attribute = $product->getDataFieldConfig('custom_attribute')['source']->getAttribute(); - $this->openSection('product-details'); - if (!$this->checkAttributeLabel($attribute)) { - /** @var \Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Section\ProductDetails $section */ - $section = $this->openSection($tabName); - $section->addNewAttribute($tabName); - $this->getAttributeForm()->fill($attribute); - } - } - /** * Open section or click on button to open modal window. * @@ -176,28 +142,15 @@ class ProductForm extends FormSections } /** - * Call method that checking present attribute in search result. - * - * @param CatalogProductAttribute $productAttribute - * @return bool - */ - public function checkAttributeInSearchAttributeForm(CatalogProductAttribute $productAttribute) - { - $this->waitPageToLoad(); - return $this->getAttributesSearchForm()->isExistAttributeInSearchResult($productAttribute); - } - - /** - * Get attributes search form. + * Get attributes search grid. * - * @return Search + * @return DataGrid */ - protected function getAttributesSearchForm() + public function getAttributesSearchGrid() { - return $this->_rootElement->find( - $this->attributeSearch, - Locator::SELECTOR_CSS, - 'Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Section\Attributes\Search' + return $this->blockFactory->create( + '\Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Section\Attributes\Grid', + ['element' => $this->browser->find($this->attributeSearch)] ); } @@ -210,8 +163,7 @@ class ProductForm extends FormSections public function isCustomSectionVisible($sectionName) { $sectionName = strtolower($sectionName); - $selector = sprintf($this->customSection, $sectionName); - $this->waitForElementVisible($selector); + $selector = sprintf($this->attributeBlock, $sectionName); return $this->_rootElement->find($selector)->isVisible(); } @@ -228,31 +180,6 @@ class ProductForm extends FormSections $this->_rootElement->find(sprintf($this->customSection, $sectionName))->click(); } - /** - * Click "Save" button on attribute form. - * - * @return void - */ - public function saveAttributeForm() - { - $this->getAttributeForm()->saveAttributeForm(); - - $browser = $this->browser; - $element = $this->newAttributeForm; - $loader = $this->loader; - $this->_rootElement->waitUntil( - function () use ($browser, $element) { - return $browser->find($element)->isVisible() == false ? true : null; - } - ); - - $this->_rootElement->waitUntil( - function () use ($browser, $loader) { - return $browser->find($loader)->isVisible() == false ? true : null; - } - ); - } - /** * Get Attribute Form. * @@ -262,7 +189,7 @@ class ProductForm extends FormSections { return $this->blockFactory->create( 'Magento\Catalog\Test\Block\Adminhtml\Product\Attribute\AttributeForm', - ['element' => $this->browser->find('body')] + ['element' => $this->browser->find($this->newAttributeModal)] ); } @@ -280,23 +207,4 @@ class ProductForm extends FormSections 'Magento\Catalog\Test\Block\Adminhtml\Product\Attribute\CustomAttribute' ); } - - /** - * Click "Add Attribute" button from specific section. - * - * @param string $sectionName - * @throws \Exception - */ - public function addNewAttribute($sectionName = 'product-details') - { - $section = $this->getSection($sectionName); - if ($section instanceof Attributes) { - $this->openSection($sectionName); - $section->addNewAttribute($sectionName); - } else { - throw new \Exception( - "$sectionName hasn't 'Add attribute' button or is not instance of ProductSection class." - ); - } - } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml index eb7766dcc327b9590e89361a28fd4e9c6bc5861a..b98cdb8c848f3d6a55cda58f45ae066814a4657e 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Block/Adminhtml/Product/ProductForm.xml @@ -19,10 +19,6 @@ <selector>[data-index="attribute_set_id"]</selector> <class>Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Section\ProductDetails\AttributeSet</class> </attribute_set_id> - <attribute_id> - <selector>#product-attribute-search-container</selector> - <class>Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Section\Attributes\Search</class> - </attribute_id> <tax_class_id> <input>select</input> </tax_class_id> @@ -44,7 +40,7 @@ </quantity_and_stock_status> <custom_attribute> <class>Magento\Catalog\Test\Block\Adminhtml\Product\Attribute\CustomAttribute</class> - <selector>#attribute-%attribute_code%-container</selector> + <selector>[data-index="%attribute_code%"]</selector> </custom_attribute> <visibility> <input>select</input> @@ -132,6 +128,17 @@ <short_description /> </fields> </content> + <attributes> + <class>\Magento\Catalog\Test\Block\Adminhtml\Product\Edit\Section\Attributes</class> + <selector>[data-index="attributes"]</selector> + <strategy>css selector</strategy> + <fields> + <custom_attribute> + <class>Magento\Catalog\Test\Block\Adminhtml\Product\Attribute\CustomAttribute</class> + <selector>[data-index="%attribute_code%"]</selector> + </custom_attribute> + </fields> + </attributes> <gallery> <class>\Magento\Ui\Test\Block\Adminhtml\Section</class> <selector>[data-index='block_gallery']</selector> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAddedProductAttributeOnProductForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAddedProductAttributeOnProductForm.php index d3d8f790b225738d1714481f0712c0f7833f00fc..6116c66f06478cfca0831360d1546f25adcf6e0b 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAddedProductAttributeOnProductForm.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertAddedProductAttributeOnProductForm.php @@ -7,20 +7,23 @@ namespace Magento\Catalog\Test\Constraint; use Magento\Catalog\Test\Fixture\CatalogAttributeSet; -use Magento\Catalog\Test\Fixture\CatalogProductSimple; use Magento\Mtf\Fixture\InjectableFixture; use Magento\Mtf\Fixture\FixtureFactory; use Magento\Mtf\Constraint\AbstractConstraint; use Magento\Catalog\Test\Fixture\CatalogProductAttribute; use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit; use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex; -use Magento\Mtf\ObjectManager; /** * Check attribute on product form. */ class AssertAddedProductAttributeOnProductForm extends AbstractConstraint { + /** + * Attributes section. + */ + const ATTRIBUTES = 'attributes'; + /** * Fixture factory. * @@ -89,7 +92,9 @@ class AssertAddedProductAttributeOnProductForm extends AbstractConstraint $catalogProductAttribute = ($productAttributeOriginal !== null) ? array_merge($productAttributeOriginal->getData(), $attribute->getData()) : $attribute->getData(); - + if ($catalogProductEdit->getProductForm()->isSectionVisible(self::ATTRIBUTES)) { + $catalogProductEdit->getProductForm()->openSection(self::ATTRIBUTES); + } \PHPUnit_Framework_Assert::assertTrue( $catalogProductEdit->getProductForm()->checkAttributeLabel($catalogProductAttribute), "Product Attribute is absent on Product form." diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInSearchOnProductForm.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInSearchOnProductForm.php index 6ff16c2a96ad8255f2ef6dce1ee3bd071c03511d..63fa283baa4ea0a2929e09a34444b614c00f7c59 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInSearchOnProductForm.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeAbsenceInSearchOnProductForm.php @@ -31,9 +31,13 @@ class AssertProductAttributeAbsenceInSearchOnProductForm extends AbstractConstra ) { $productGrid->open(); $productGrid->getGridPageActionBlock()->addProduct('simple'); + $newProductPage->getFormPageActions()->addNewAttribute(); + $filter = [ + 'label' => $productAttribute->getFrontendLabel(), + ]; \PHPUnit_Framework_Assert::assertFalse( - $newProductPage->getProductForm()->checkAttributeInSearchAttributeForm($productAttribute), - "Product attribute found in Attribute Search form." + $newProductPage->getProductForm()->getAttributesSearchGrid()->isRowVisible($filter), + 'Attribute \'' . $productAttribute->getFrontendLabel() . '\' is found in Attributes grid.' ); } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeInGrid.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeInGrid.php index d23e92007df57e375cfef4dd130b63ca623a0a39..a1da3f696cca633b38a79b9220db4c84ef785b90 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeInGrid.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeInGrid.php @@ -11,8 +11,7 @@ use Magento\Catalog\Test\Page\Adminhtml\CatalogProductAttributeIndex; use Magento\Mtf\Constraint\AbstractConstraint; /** - * Class AssertProductAttributeInGrid - * Assert that created product attribute is found in grid + * Assert that created product attribute is found in grid. */ class AssertProductAttributeInGrid extends AbstractConstraint { diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsRequired.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsRequired.php index 403664ac3b82c693b38b14a6887bcf21ed809091..4f80e101e73ae6f9959796589dacfccb72fc24aa 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsRequired.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsRequired.php @@ -39,10 +39,13 @@ class AssertProductAttributeIsRequired extends AbstractConstraint ) { $catalogProductIndex->open()->getProductGrid()->searchAndOpen(['sku' => $product->getSku()]); $productForm = $catalogProductEdit->getProductForm(); + if (!$productForm->checkAttributeLabel($attribute)) { + $productForm->openSection('attributes'); + } $productForm->getAttributeElement($attribute)->setValue(''); $catalogProductEdit->getFormPageActions()->save(); - $failedAttributes = $productForm->getRequireNoticeAttributes($product); - $actualMessage = $failedAttributes['product-details'][$attribute->getFrontendLabel()]; + $failedFields = $productForm->getRequireNoticeFields($product); + $actualMessage = $failedFields['attributes'][$attribute->getFrontendLabel()]; \PHPUnit_Framework_Assert::assertEquals( self::REQUIRE_MESSAGE, diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsUnique.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsUnique.php index 46cdf8fe2cab0d06cfe978f34001a3507b75571a..3c11b613ea3f0dcda3173815850a59f5ad95d75b 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsUnique.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Constraint/AssertProductAttributeIsUnique.php @@ -58,31 +58,16 @@ class AssertProductAttributeIsUnique extends AbstractConstraint $productForm = $catalogProductEdit->getProductForm(); $productForm->fill($simpleProduct); $catalogProductEdit->getFormPageActions()->save(); - $failedAttributes = $productForm->getRequireNoticeAttributes($simpleProduct); + $actualErrorMessage = $catalogProductEdit->getMessagesBlock()->getErrorMessage(); $attributeLabel = $attribute->getFrontendLabel(); - $actualMessage = $this->getActualMessage($failedAttributes, $attributeLabel); \PHPUnit_Framework_Assert::assertEquals( sprintf(self::UNIQUE_MESSAGE, $attributeLabel), - $actualMessage, + $actualErrorMessage, 'JS error notice on product edit page is not equal to expected.' ); } - /** - * Get actual message. - * - * @param array $errors - * @param string $attributeLabel - * @return mixed - */ - protected function getActualMessage(array $errors, $attributeLabel) - { - return isset($errors['product-details'][$attributeLabel]) - ? $errors['product-details'][$attributeLabel] - : null; - } - /** * Create simple product fixture. * diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml index ef25f951e1f7b644d86a936d1a8fa0534d5098ad..d2a53d1eb757a64323dbb64db2a49531ca655348 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Fixture/CatalogProductSimple.xml @@ -73,7 +73,7 @@ <field name="id" group="null" /> <field name="type_id" /> <field name="attribute_set_id" group="product-details" source="Magento\Catalog\Test\Fixture\Product\AttributeSetId" /> - <field name="custom_attribute" group="product-details" source="Magento\Catalog\Test\Fixture\CatalogProductSimple\CustomAttribute" /> + <field name="custom_attribute" source="Magento\Catalog\Test\Fixture\CatalogProductSimple\CustomAttribute" /> <field name="custom_options" is_required="0" group="customer-options" source="Magento\Catalog\Test\Fixture\Product\CustomOptions" repository="Magento\Catalog\Test\Repository\Product\CustomOptions" /> <field name="website_ids" group="websites" /> <field name="is_returnable" is_required="0" group="product-details" /> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductEdit.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductEdit.xml index 1736cebd10e8e7ef5674fec29edfce7860986bf0..dc6b1e8213628f54597d2db52c9eb8b5a2b1fe66 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductEdit.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Page/Adminhtml/CatalogProductEdit.xml @@ -9,6 +9,8 @@ <page name="CatalogProductEdit" area="Adminhtml" mca="catalog/product/edit" module="Magento_Catalog"> <block name="messagesBlock" class="Magento\Backend\Test\Block\Messages" locator="#messages .messages" strategy="css selector"/> <block name="formPageActions" class="Magento\Catalog\Test\Block\Adminhtml\Product\FormPageActions" locator=".page-main-actions" strategy="css selector"/> + <block name="addAttributeModal" class="Magento\Catalog\Test\Block\Adminhtml\Product\Modal\AddAttribute" locator=".product_form_product_form_add_attribute_modal" strategy="css selector"/> + <block name="newAttributeModal" class="Magento\Catalog\Test\Block\Adminhtml\Product\Modal\NewAttribute" locator=".product_form_product_form_add_attribute_modal_create_new_attribute_modal" strategy="css selector"/> <block name="productForm" class="Magento\Catalog\Test\Block\Adminhtml\Product\ProductForm" locator="[id='page:main-container']" strategy="css selector"/> </page> </config> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductAttribute.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductAttribute.xml index 2134b0c13ef23838c1fc1193a41676a954d3e2d0..8ebc57837ec8f4f0e1d12e15db0ab17afb50cb5c 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductAttribute.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductAttribute.xml @@ -35,8 +35,8 @@ <dataset name="tax_class_id"> <field name="attribute_id" xsi:type="number">172</field> - <field name="frontend_label" xsi:type="string">Tax Class</field> - <field name="attribute_code" xsi:type="string">tax_class_id</field> + <field name="frontend_label" xsi:type="string">Tax Class%isolation%</field> + <field name="attribute_code" xsi:type="string">tax_class_id%isolation%</field> <field name="frontend_input" xsi:type="string">Dropdown</field> <field name="is_required" xsi:type="string">No</field> <field name="options" xsi:type="array"> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductVirtual.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductVirtual.xml index 910d475e83a2051de6bc0eac0793400067c3b146..164053ada95253eeddf8b9e67f804634b967f18f 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductVirtual.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/Repository/CatalogProductVirtual.xml @@ -26,6 +26,7 @@ <item name="qty" xsi:type="string">666</item> <item name="is_in_stock" xsi:type="string">In Stock</item> </field> + <field name="product_has_weight" xsi:type="string">This item has no weight</field> <field name="price" xsi:type="array"> <item name="value" xsi:type="string">10</item> </field> @@ -44,6 +45,7 @@ <field name="tax_class_id" xsi:type="array"> <item name="dataset" xsi:type="string">taxable_goods</item> </field> + <field name="product_has_weight" xsi:type="string">This item has no weight</field> <field name="website_ids" xsi:type="array"> <item name="0" xsi:type="string">Main Website</item> </field> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/AddToCartCrossSellTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/AddToCartCrossSellTest.xml index f5086b3d40287af985578f62febb070f27dea64e..1e816de3b17fb74e7352777acc12c15faeb5583b 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/AddToCartCrossSellTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/AddToCartCrossSellTest.xml @@ -10,9 +10,9 @@ <variation name="AddToCartCrossSellTestVariation1" method="test"> <data name="tag" xsi:type="string">test_type:acceptance_test, test_type:extended_acceptance_test</data> <data name="products" xsi:type="string">simple1::catalogProductSimple::product_with_category,simple2::catalogProductSimple::product_with_category,config1::configurableProduct::two_options_with_fixed_price</data> - <data name="promotedProducts" xsi:type="string">simple1:simple2,config1;simple2:config1</data> - <data name="navigateProductsOrder" xsi:type="string">simple1,simple2,config1</data> - <data name="productsToVerify" xsi:type="string">simple1:simple2,config1;simple2:config1;config1:</data> + <data name="promotedProducts" xsi:type="string">simple1:simple2,config1;config1:simple2</data> + <data name="navigateProductsOrder" xsi:type="string">simple1,config1,simple2</data> + <data name="productsToVerify" xsi:type="string">simple1:simple2,config1;config1:simple2;simple2:</data> </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/NavigateUpSellProductsTest.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/NavigateUpSellProductsTest.xml index 85bc8146d8649b84a573fa6c7625e9d74a0ab8d5..32c0f51f4f10663219ef4d8e2f5ada6a66ec6691 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/NavigateUpSellProductsTest.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/NavigateUpSellProductsTest.xml @@ -10,9 +10,9 @@ <variation name="NavigateUpSellProductsTestVariation1" method="test"> <data name="tag" xsi:type="string">test_type:acceptance_test, test_type:extended_acceptance_test</data> <data name="products" xsi:type="string">simple1::catalogProductSimple::product_with_category,simple2::catalogProductSimple::product_with_category,config1::configurableProduct::two_options_with_fixed_price</data> - <data name="promotedProducts" xsi:type="string">simple1:simple2,config1;simple2:config1</data> - <data name="navigateProductsOrder" xsi:type="string">simple1,simple2,config1</data> - <data name="productsToVerify" xsi:type="string">simple1:simple2,config1;simple2:config1;config1:</data> + <data name="promotedProducts" xsi:type="string">simple1:simple2,config1;config1:simple2</data> + <data name="navigateProductsOrder" xsi:type="string">simple1,config1,simple2</data> + <data name="productsToVerify" xsi:type="string">simple1:simple2,config1;config1:simple2;simple2:</data> </variation> </testCase> </config> diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/ProductTypeSwitchingOnUpdateTest.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/ProductTypeSwitchingOnUpdateTest.php index 4b99c2bb8940e2a4908f41e00590c4470e7111da..55814088db48197c6b247518b042ca59ba38310a 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/ProductTypeSwitchingOnUpdateTest.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestCase/Product/ProductTypeSwitchingOnUpdateTest.php @@ -8,7 +8,7 @@ namespace Magento\Catalog\Test\TestCase\Product; use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit; use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex; -use Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Variations\Config; +use Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Section\Variations\Config; use Magento\Downloadable\Test\Block\Adminhtml\Catalog\Product\Edit\Section\Downloadable; use Magento\Mtf\Fixture\FixtureFactory; use Magento\Mtf\TestCase\Injectable; diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/AddNewAttributeFromProductPageStep.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/AddNewAttributeFromProductPageStep.php index fbf36b230f2bd929592f3b91109dacd5ac5c5b97..10ec591099f9b474e9b64a1abb1e47b9ca452fb3 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/AddNewAttributeFromProductPageStep.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/AddNewAttributeFromProductPageStep.php @@ -21,22 +21,13 @@ class AddNewAttributeFromProductPageStep implements TestStepInterface */ protected $catalogProductEdit; - /** - * Tab name for adding attribute. - * - * @var string - */ - protected $tabName; - /** * @constructor * @param CatalogProductEdit $catalogProductEdit - * @param string $tabName */ - public function __construct(CatalogProductEdit $catalogProductEdit, $tabName) + public function __construct(CatalogProductEdit $catalogProductEdit) { $this->catalogProductEdit = $catalogProductEdit; - $this->tabName = $tabName; } /** @@ -46,7 +37,8 @@ class AddNewAttributeFromProductPageStep implements TestStepInterface */ public function run() { - $productForm = $this->catalogProductEdit->getProductForm(); - $productForm->addNewAttribute($this->tabName); + $productForm = $this->catalogProductEdit->getFormPageActions(); + $productForm->addNewAttribute(); + $this->catalogProductEdit->getAddAttributeModal()->createNewAttribute(); } } diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/SaveAttributeOnProductPageStep.php b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/SaveAttributeOnProductPageStep.php index 48c94b86e7a8edf88f79ef3df9fffac9557437af..c01b09a684ce683325d651e12c2e08a1133f52f1 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/SaveAttributeOnProductPageStep.php +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/TestStep/SaveAttributeOnProductPageStep.php @@ -16,13 +16,6 @@ use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit; */ class SaveAttributeOnProductPageStep implements TestStepInterface { - /** - * Catalog product edit page. - * - * @var CatalogProductEdit - */ - protected $catalogProductEdit; - /** * Product attribute fixture. * @@ -37,30 +30,37 @@ class SaveAttributeOnProductPageStep implements TestStepInterface */ protected $objectManager; + /** + * Catalog product edit page. + * + * @var CatalogProductEdit + */ + protected $catalogProductEdit; + /** * @constructor - * @param CatalogProductEdit $catalogProductEdit * @param CatalogProductAttribute $attribute * @param ObjectManager $objectManager + * @param CatalogProductEdit $catalogProductEdit */ public function __construct( - CatalogProductEdit $catalogProductEdit, CatalogProductAttribute $attribute, - ObjectManager $objectManager + ObjectManager $objectManager, + CatalogProductEdit $catalogProductEdit ) { - $this->catalogProductEdit = $catalogProductEdit; $this->attribute = $attribute; $this->objectManager = $objectManager; + $this->catalogProductEdit = $catalogProductEdit; } /** - * Click "Save" button on attribute form on product page. + * Click "Save" button on attribute form. * - * @return array + * @return void */ public function run() { - $this->catalogProductEdit->getProductForm()->saveAttributeForm(); + $this->catalogProductEdit->getNewAttributeModal()->saveAttribute(); } /** diff --git a/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/testcase.xml index f9cf350993613862ff92b789b8c94397cf9d17f1..40e9a20adf3b33069c3e7fa7804921afea16ebc8 100644 --- a/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/testcase.xml +++ b/dev/tests/functional/tests/app/Magento/Catalog/Test/etc/testcase.xml @@ -8,9 +8,7 @@ <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/Magento/Mtf/TestCase/etc/testcase.xsd"> <scenario name="CreateProductAttributeEntityFromProductPageTest" firstStep="openProductOnBackend"> <step name="openProductOnBackend" module="Magento_Catalog" next="addNewAttributeFromProductPage"/> - <step name="addNewAttributeFromProductPage" module="Magento_Catalog" next="fillAttributeFormOnProductPage"> - <item name="tabName" value="product-details"/> - </step> + <step name="addNewAttributeFromProductPage" module="Magento_Catalog" next="fillAttributeFormOnProductPage"/> <step name="fillAttributeFormOnProductPage" module="Magento_Catalog" next="saveAttributeOnProductPage"/> <step name="saveAttributeOnProductPage" module="Magento_Catalog" next="setDefaultAttributeValue"/> <step name="setDefaultAttributeValue" module="Magento_Catalog" next="saveProduct"/> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/AffectedAttributeSet.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/AffectedAttributeSet.php index 7d731915be33026f11ff96b2fb41d3fa8b398d46..d7fcc85e65f7fbfda4f51e2e08c35e5e876c842b 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/AffectedAttributeSet.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/AffectedAttributeSet.php @@ -13,27 +13,26 @@ use Magento\Mtf\Client\Element\SimpleElement; use Magento\Mtf\Block\Form as ParentForm; /** - * Class AffectedAttributeSet - * Choose affected attribute set dialog popup window + * Choose affected attribute set dialog popup window. */ class AffectedAttributeSet extends ParentForm { /** - * 'Confirm' button locator + * 'Confirm' button locator. * * @var string */ - protected $confirmButton = '[data-role=action]'; + protected $confirmButton = '[data-index="confirm_button"]'; /** - * Locator buttons new name attribute set + * Add configurable attributes to the New Attribute Set. * * @var string */ - protected $affectedAttributeSetNew = '#new-affected-attribute-set'; + protected $affectedAttributeSetNew = 'input[data-index="affectedAttributeSetNew"]'; /** - * Fill popup form + * Fill popup form. * * @param FixtureInterface $product * @param SimpleElement|null $element [optional] @@ -55,7 +54,7 @@ class AffectedAttributeSet extends ParentForm } /** - * Click confirm button + * Click confirm button. * * @return void */ diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/AffectedAttributeSet.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/AffectedAttributeSet.xml index f5eeb1b659895e53b116864c1cdf753a3a78f4ab..69884c2660f9b3a5f0cd54d3d546be8651d140d0 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/AffectedAttributeSet.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/AffectedAttributeSet.xml @@ -8,7 +8,7 @@ <mapping strict="0"> <fields> <new_attribute_set_name> - <selector>[name='new-attribute-set-name']</selector> + <selector>.new-attribute-set-name input</selector> </new_attribute_set_name> </fields> </mapping> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/NewConfigurableAttributeForm.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/NewConfigurableAttributeForm.php new file mode 100644 index 0000000000000000000000000000000000000000..a09c9b4dd6e00a73132295a89f17b71d5ccac68c --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/NewConfigurableAttributeForm.php @@ -0,0 +1,92 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit; + +use Magento\Ui\Test\Block\Adminhtml\FormSections; +use Magento\Mtf\Client\Element\SimpleElement; +use Magento\Mtf\Client\Locator; +use Magento\Mtf\Fixture\FixtureInterface; + +/** + * New attribute form on configurable product page. + */ +class NewConfigurableAttributeForm extends FormSections +{ + /** + * Iframe locator. + * + * @var string + */ + protected $iFrame = '#create_new_attribute_container'; + + /** + * Save button selector. + * + * @var string + */ + protected $saveButton = '#save'; + + /** + * Attribute to check whether section is opened. + * + * @var string + */ + private $isSectionOpened = 'active'; + + /** + * Fill the attribute form. + * + * @param FixtureInterface $fixture + * @param SimpleElement|null $element + * @return $this + */ + public function fill(FixtureInterface $fixture, SimpleElement $element = null) + { + $this->browser->switchToFrame(new Locator($this->iFrame)); + $browser = $this->browser; + $selector = $this->saveButton; + $this->browser->waitUntil( + function () use ($browser, $selector) { + return $browser->find($selector)->isVisible() ? true : null; + } + ); + parent::fill($fixture, $element); + $this->browser->switchToFrame(); + } + + /** + * Open section. + * + * @param string $sectionName + * @return FormSections + */ + public function openSection($sectionName) + { + $selector = $this->getContainerElement($sectionName)->getLocator()['value']; + $strategy = null !== $this->getContainerElement($sectionName)->getLocator()['using'] + ? $this->getContainerElement($sectionName)->getLocator()['using'] + : Locator::SELECTOR_CSS; + $sectionClass = $this->_rootElement->find($selector, $strategy)->getAttribute('class'); + if (strpos($sectionClass, $this->isSectionOpened) === false) { + $this->_rootElement->find($selector, $strategy)->click(); + } + + return $this; + } + + /** + * Click on "Save" button. + * + * @return void + */ + public function saveAttributeForm() + { + $this->browser->switchToFrame(new Locator($this->iFrame)); + $this->browser->find($this->saveButton)->click(); + $this->browser->switchToFrame(); + } +} diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/NewConfigurableAttributeForm.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/NewConfigurableAttributeForm.xml new file mode 100644 index 0000000000000000000000000000000000000000..e211a7882463d1039ec444500ccfa8cf6ccda7fe --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/NewConfigurableAttributeForm.xml @@ -0,0 +1,95 @@ +<?xml version="1.0" ?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<sections> + <properties> + <class>\Magento\Ui\Test\Block\Adminhtml\Section</class> + <selector>#edit_form</selector> + <strategy>css selector</strategy> + <fields> + <frontend_label> + <selector>[name^='frontend_label']</selector> + </frontend_label> + <frontend_input> + <input>select</input> + </frontend_input> + <is_required> + <input>select</input> + </is_required> + <options> + <class>\Magento\Catalog\Test\Block\Adminhtml\Product\Attribute\Edit\Options</class> + <selector>#manage-options-panel</selector> + <strategy>css selector</strategy> + </options> + </fields> + </properties> + <advanced-properties> + <class>\Magento\Ui\Test\Block\Adminhtml\Section</class> + <selector>[data-target="#advanced_fieldset-content"]</selector> + <strategy>css selector</strategy> + <fields> + <attribute_code> + </attribute_code> + <is_global> + <input>select</input> + </is_global> + <default_value> + <selector>[name^='default_value_']</selector> + </default_value> + <is_unique> + <input>select</input> + </is_unique> + </fields> + </advanced-properties> + <manage-labels> + <class>\Magento\Ui\Test\Block\Adminhtml\Section</class> + <selector>[data-target="#manage-titles-content"]</selector> + <strategy>css selector</strategy> + <fields> + <manage_frontend_label> + <selector>[name^='frontend_label']</selector> + </manage_frontend_label> + </fields> + </manage-labels> + <frontend-properties> + <class>\Magento\Backend\Test\Block\Widget\Tab</class> + <selector>[data-target="#front_fieldset-content"]</selector> + <strategy>css selector</strategy> + <fields> + <is_searchable> + <input>select</input> + </is_searchable> + <is_visible_in_advanced_search> + <input>select</input> + </is_visible_in_advanced_search> + <is_comparable> + <input>select</input> + </is_comparable> + <is_filterable> + <input>select</input> + </is_filterable> + <is_filterable_in_search> + <input>select</input> + </is_filterable_in_search> + <is_used_for_promo_rules> + <input>select</input> + </is_used_for_promo_rules> + <is_html_allowed_on_front> + <input>select</input> + </is_html_allowed_on_front> + <is_visible_on_front> + <input>select</input> + </is_visible_on_front> + <used_in_product_listing> + <input>select</input> + </used_in_product_listing> + <used_for_sort_by> + <input>select</input> + </used_for_sort_by> + </fields> + </frontend-properties> +</sections> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config.php similarity index 83% rename from dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config.php rename to dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config.php index 805fe65d1ebec7e1406713d013a6722a2cc1420b..6fa06e0736c34caafbf3f960e07d0a46dd32f4c5 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config.php @@ -4,21 +4,21 @@ * See COPYING.txt for license details. */ -namespace Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Variations; +namespace Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Section\Variations; use Magento\Backend\Test\Block\Template; -use Magento\Backend\Test\Block\Widget\Tab; +use Magento\Ui\Test\Block\Adminhtml\Section; use Magento\Mtf\Client\Element; use Magento\Mtf\Client\Element\SimpleElement; use Magento\Mtf\Client\Locator; /** - * Adminhtml catalog super product configurable tab. + * Adminhtml catalog super product configurable section. */ -class Config extends Tab +class Config extends Section { /** @var string */ - protected $createConfigurationsButton = '[data-action=open-steps-wizard]'; + protected $createConfigurationsButton = '[data-index="create_configurable_products_button"] > span'; /** * Selector for trigger show/hide "Variations" tab. @@ -46,7 +46,7 @@ class Config extends Tab * * @var string */ - protected $variationsMatrix = '[data-role="product-variations-matrix"]'; + protected $variationsMatrix = 'div[data-index="configurable-matrix"]'; /** * Selector for template block. @@ -62,6 +62,13 @@ class Config extends Tab */ protected $variationsContent = '#product_info_tabs_super_config_content'; + /** + * Locator for Configurations section. + * + * @var string + */ + private $configurationsSection = '[data-index="configurable"]'; + /** * Fill variations fieldset. * @@ -77,7 +84,6 @@ class Config extends Tab ? $fields['configurable_attributes_data']['value'] : []; - $this->showContent(); $attributesValue = isset($fields['configurable_attributes_data']['source']) ? $fields['configurable_attributes_data']['source']->getAttributesData() : []; @@ -94,20 +100,6 @@ class Config extends Tab return $this; } - /** - * Show "Variations" tab content. - * - * @return void - */ - public function showContent() - { - $content = $this->_rootElement->find($this->variationsTabContent); - if (!$content->isVisible()) { - $this->_rootElement->find($this->variationsTabTrigger)->click(); - $this->waitForElementVisible($this->variationsTabContent); - } - } - /** * Click 'Create Configurations' button. * @@ -115,6 +107,7 @@ class Config extends Tab */ public function createConfigurations() { + $this->_rootElement->find($this->configurationsSection)->hover(); $this->_rootElement->find($this->createConfigurationsButton)->click(); } @@ -132,12 +125,12 @@ class Config extends Tab /** * Get block of attributes. * - * @return \Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Variations\Config\Attribute + * @return \Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Section\Variations\Config\Attribute */ public function getAttributeBlock() { return $this->blockFactory->create( - 'Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Variations\Config\Attribute', + 'Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Section\Variations\Config\Attribute', ['element' => $this->_rootElement] ); } @@ -145,12 +138,12 @@ class Config extends Tab /** * Get block of variations. * - * @return \Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Variations\Config\Matrix + * @return \Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Section\Variations\Config\Matrix */ public function getVariationsBlock() { return $this->blockFactory->create( - 'Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Variations\Config\Matrix', + 'Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Section\Variations\Config\Matrix', ['element' => $this->_rootElement->find($this->variationsMatrix)] ); } @@ -180,8 +173,6 @@ class Config extends Tab public function getFieldsData($fields = null, SimpleElement $element = null) { $data = []; - - $this->showContent(); $data['matrix'] = $this->getVariationsBlock()->getVariationsData(); return ['configurable_attributes_data' => $data]; diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Attribute.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Attribute.php similarity index 93% rename from dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Attribute.php rename to dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Attribute.php index 0459c4d67ecb8643b9498fa37decd3e9e0981bb3..9b91ecbbc15e9f747e52e20878cfd24b40d4d47c 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Attribute.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Attribute.php @@ -4,9 +4,9 @@ * See COPYING.txt for license details. */ -namespace Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Variations\Config; +namespace Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Section\Variations\Config; -use Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Variations\Config\Attribute\AttributeSelector; +use Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Section\Variations\Config\Attribute\AttributeSelector; use Magento\Mtf\Block\Form; use Magento\Mtf\Client\Element\SimpleElement; use Magento\Mtf\Client\Locator; @@ -152,6 +152,13 @@ class Attribute extends Form */ protected $templateBlock = './ancestor::body'; + /** + * List of selected attributes + * + * @var string + */ + private $selectedAttributes = 'span[data-bind*="selectedAttributes"]'; + /** * Fill attributes * @@ -170,7 +177,11 @@ class Attribute extends Form //select attributes $this->getAttributesGrid()->resetFilter(); - $this->getAttributesGrid()->deselectAttributes(); + $attributesList = $this->browser->find($this->selectedAttributes)->getText(); + if ($attributesList != '--') { + $this->getAttributesGrid()->deselectAttributes(); + } + if ($this->_rootElement->find('[class$=no-data]')->isVisible()) { return; } @@ -214,8 +225,9 @@ class Attribute extends Form ); $this->browser->find($this->createNewVariationSet)->click(); - $this->getEditAttributeForm()->fill($attributeFixture); - $this->getEditAttributeForm()->saveAttributeForm(); + $newAttributeForm = $this->getNewAttributeForm(); + $newAttributeForm->fill($attributeFixture); + $newAttributeForm->saveAttributeForm(); $this->waitBlock($this->newAttributeFrame); } @@ -322,14 +334,14 @@ class Attribute extends Form } /** - * Get attribute form block + * Get new attribute form block. * - * @return \Magento\Catalog\Test\Block\Adminhtml\Product\Attribute\AttributeForm + * @return \Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\NewConfigurableAttributeForm */ - protected function getEditAttributeForm() + protected function getNewAttributeForm() { return $this->blockFactory->create( - 'Magento\Catalog\Test\Block\Adminhtml\Product\Attribute\AttributeForm', + 'Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\NewConfigurableAttributeForm', ['element' => $this->browser->find($this->newAttribute)] ); } @@ -344,7 +356,7 @@ class Attribute extends Form return $this->_rootElement->find( $this->variationSearchBlock, Locator::SELECTOR_CSS, - 'Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Variations\Config\Attribute' + 'Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Section\Variations\Config\Attribute' . '\AttributeSelector' ); } diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Attribute.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Attribute.xml similarity index 100% rename from dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Attribute.xml rename to dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Attribute.xml diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Attribute/AttributeSelector.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Attribute/AttributeSelector.php similarity index 94% rename from dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Attribute/AttributeSelector.php rename to dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Attribute/AttributeSelector.php index d62e39beb7396285fdc0c8460f8ada8705c3cac6..5a6ebf949ec08cfc30a6597779ef9f49c35302d0 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Attribute/AttributeSelector.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Attribute/AttributeSelector.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ -namespace Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Variations\Config\Attribute; +namespace Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Section\Variations\Config\Attribute; use Magento\Mtf\Client\Element\SuggestElement; diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Attribute/ToggleDropdown.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Attribute/ToggleDropdown.php similarity index 97% rename from dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Attribute/ToggleDropdown.php rename to dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Attribute/ToggleDropdown.php index e1c6d9ca30164257dbd0bc0eace33ef3bf3f54de..ea0f83671d20bd13ce9cb0744a9adb9070bff0c8 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Attribute/ToggleDropdown.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Attribute/ToggleDropdown.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ -namespace Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Variations\Config\Attribute; +namespace Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Section\Variations\Config\Attribute; use Magento\Mtf\Client\Element\SimpleElement; use Magento\Mtf\Client\Locator; diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Matrix.php similarity index 79% rename from dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php rename to dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Matrix.php index 231ce9ae6b500c3f1e2490b6d7f571a982153fae..ed8cbc800b2e672008347881a5bd18e1e674135f 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Matrix.php @@ -4,7 +4,7 @@ * See COPYING.txt for license details. */ -namespace Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Variations\Config; +namespace Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Section\Variations\Config; use Magento\Mtf\Client\ElementInterface; use Magento\Mtf\Client\Locator; @@ -13,66 +13,59 @@ use Magento\Mtf\Block\Form; use Magento\Mtf\Client\Element\SimpleElement; /** - * Class Matrix - * Matrix row form + * Matrix row form. */ class Matrix extends Form { /** - * Mapping for get optional fields + * Mapping for get optional fields. * * @var array */ protected $mappingGetFields = [ 'name' => [ - 'selector' => 'td[data-column="name"] > a', + 'selector' => 'td[data-index="name_container"] a', 'strategy' => Locator::SELECTOR_CSS, ], 'sku' => [ - 'selector' => 'td[data-column="sku"]', + 'selector' => 'td[data-index="sku_container"] span[data-index="sku_text"]', 'strategy' => Locator::SELECTOR_CSS, ], 'price' => [ - 'selector' => 'td[data-column="price"]', + 'selector' => 'td[data-index="price_container"] span[data-index="price_text"]', 'strategy' => Locator::SELECTOR_CSS, ], - 'quantity_and_stock_status' => [ - 'composite' => 1, - 'fields' => [ - 'qty' => [ - 'selector' => 'td[data-column="qty"]', - 'strategy' => Locator::SELECTOR_CSS, - ], - ], + 'qty' => [ + 'selector' => 'td[data-index="quantity_container"] span[data-index="quantity_text"]', + 'strategy' => Locator::SELECTOR_CSS, ], 'weight' => [ - 'selector' => 'td[data-column="weight"]', + 'selector' => 'td[data-index="price_weight"] span[data-index="weight_text"]', 'strategy' => Locator::SELECTOR_CSS, ], ]; /** - * Selector for variation row by number + * Selector for variation row by number. * * @var string */ - protected $variationRowByNumber = './/tr[@data-role="row"][%d]'; + protected $variationRowByNumber = './/tr[@class="data-row" or @class="data-row _odd-row"][%d]'; /** - * Selector for variation row + * Selector for variation row. * * @var string */ - protected $variationRow = 'tr[data-role="row"]'; + protected $variationRow = './/tr[contains(@class, "data-row")]'; - // @codingStandardsIgnoreStart /** - * Selector for row on product grid by product id + * Selector for row on product grid by product id. * * @var string */ - protected $associatedProductGrid = 'div[data-grid-id="associated-products-container"]'; - // @codingStandardsIgnoreEnd + protected $associatedProductGrid = + '[data-bind*="configurable_associated_product_listing.configurable_associated_product_listing"]'; /** * Selector for template block. @@ -86,14 +79,14 @@ class Matrix extends Form * * @var string */ - protected $deleteVariation = '[data-bind*="removeProduct"]'; + protected $deleteVariation = '[data-bind*="deleteRecord"]'; /** * Choose a different Product button selector. * * @var string */ - protected $chooseProduct = '[data-bind*="showGrid"]'; + protected $chooseProduct = '[data-bind*="openModalWithGrid"]'; /** * Action menu @@ -152,7 +145,7 @@ class Matrix extends Form public function getVariationsData() { $data = []; - $variationRows = $this->_rootElement->getElements($this->variationRow); + $variationRows = $this->_rootElement->getElements($this->variationRow, Locator::SELECTOR_XPATH); foreach ($variationRows as $key => $variationRow) { /** @var SimpleElement $variationRow */ @@ -200,7 +193,7 @@ class Matrix extends Form public function deleteVariations() { - $variations = $this->_rootElement->getElements($this->variationRow); + $variations = $this->_rootElement->getElements($this->variationRow, Locator::SELECTOR_XPATH); foreach (array_reverse($variations) as $variation) { $variation->find($this->actionMenu)->hover(); $variation->find($this->actionMenu)->click(); diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Matrix.xml similarity index 71% rename from dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.xml rename to dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Matrix.xml index ea25b923bafc55125e207da2908134169cbba12c..f2525ca789ddf64513391d186275229c0f5f27fb 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Tab/Variations/Config/Matrix.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/Edit/Section/Variations/Config/Matrix.xml @@ -16,11 +16,9 @@ <price> <selector>[name$="[price]"]</selector> </price> - <quantity_and_stock_status composite="1"> - <qty> - <selector>[name$="[quantity_and_stock_status][qty]"]</selector> - </qty> - </quantity_and_stock_status> + <qty> + <selector>[name$="[qty]"]</selector> + </qty> <weight> <selector>[name$="[weight]"]</selector> </weight> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/FormPageActions.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/FormPageActions.php index 01bcd91da8c03dd90f69aa29ea7b04f1179e9f7c..11c66f128b5b28504042b99e56f4948a77f2fac5 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/FormPageActions.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/FormPageActions.php @@ -21,7 +21,7 @@ class FormPageActions extends \Magento\Catalog\Test\Block\Adminhtml\Product\Form * * @var string */ - protected $affectedAttributeSetForm = '//div[@data-role="affected-attribute-set-selector"]/ancestor::*[@data-role="modal"]'; + protected $affectedAttributeSetForm = '.product_form_product_form_configurable_attribute_set_handler_modal [data-role="focusable-scope"]'; // @codingStandardsIgnoreEnd /** @@ -48,7 +48,7 @@ class FormPageActions extends \Magento\Catalog\Test\Block\Adminhtml\Product\Form { return $this->blockFactory->create( '\Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\AffectedAttributeSet', - ['element' => $this->browser->find($this->affectedAttributeSetForm, Locator::SELECTOR_XPATH)] + ['element' => $this->browser->find($this->affectedAttributeSetForm)] ); } } diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/ProductForm.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/ProductForm.php index b8a51d8231d81bc2b3f68ac4745934d2ab29556c..80ea10808de0add0bce44d07402c9f98a137a0d1 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/ProductForm.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/ProductForm.php @@ -35,7 +35,6 @@ class ProductForm extends \Magento\Catalog\Test\Block\Adminhtml\Product\ProductF return $this->fillContainers($sections, $element); } - /** * Create data array for filling tabs. * Skip Advanced Price tab @@ -45,10 +44,10 @@ class ProductForm extends \Magento\Catalog\Test\Block\Adminhtml\Product\ProductF */ protected function getFixtureFieldsByContainers(InjectableFixture $fixture) { - $tabs = parent::getFixtureFieldsByContainers($fixture); - if (isset($tabs['advanced-pricing'])) { - unset($tabs['advanced-pricing']); + $sections = parent::getFixtureFieldsByContainers($fixture); + if (isset($sections['advanced-pricing'])) { + unset($sections['advanced-pricing']); } - return $tabs; + return $sections; } } diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/ProductForm.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/ProductForm.xml index 7d13ef869364bbbc77168a6beefb77898a88a238..788105979cb2223906bfa98c3a6220cd21efab02 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/ProductForm.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Block/Adminhtml/Product/ProductForm.xml @@ -7,15 +7,15 @@ --> <sections> <variations> - <class>\Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Variations\Config</class> - <selector>[data-index='product-details']</selector> + <class>\Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Section\Variations\Config</class> + <selector>[data-index="configurable"]</selector> <strategy>css selector</strategy> <fields> <attributes_data> - <selector>#super_config-wrapper</selector> + <selector>[data-index="configurable"] fieldset</selector> </attributes_data> <matrix> - <selector>#product-variations-matrix</selector> + <selector>[data-index="configurable-matrix"]</selector> </matrix> </fields> </variations> diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeAbsenceInVariationsSearch.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeAbsenceInVariationsSearch.php index 5a27cc69211bb0d91b61fd8597cca86003b72295..2763563c86df599d69dd70d176393d27ed03a248 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeAbsenceInVariationsSearch.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeAbsenceInVariationsSearch.php @@ -6,8 +6,8 @@ namespace Magento\ConfigurableProduct\Test\Constraint; -use Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Variations\Config as VariationsTab; -use Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Variations\Config\Attribute as AttributeBlock; +use Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Section\Variations\Config as VariationsTab; +use Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Section\Variations\Config\Attribute as AttributeBlock; use Magento\Catalog\Test\Fixture\CatalogProductAttribute; use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex; use Magento\Catalog\Test\Page\Adminhtml\CatalogProductNew; @@ -44,8 +44,7 @@ class AssertProductAttributeAbsenceInVariationsSearch extends AbstractConstraint /** @var VariationsTab $variationsTab */ $newProductPage->getProductForm()->fill($assertProduct); - $variationsTab = $newProductPage->getProductForm()->getTab(self::TAB_VARIATIONS); - $variationsTab->showContent(); + $variationsTab = $newProductPage->getProductForm()->getSection(self::TAB_VARIATIONS); $variationsTab->createConfigurations(); $attributesGrid = $variationsTab->getAttributeBlock()->getAttributesGrid(); \PHPUnit_Framework_Assert::assertFalse( diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeIsConfigurable.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeIsConfigurable.php index 383d76a2367e47c3b63108305b8dca5e84350c1e..251af2e1893a67b8de3dd99d7cfc4e310035afc6 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeIsConfigurable.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/Constraint/AssertProductAttributeIsConfigurable.php @@ -9,7 +9,7 @@ namespace Magento\ConfigurableProduct\Test\Constraint; use Magento\Catalog\Test\Fixture\CatalogProductAttribute; use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex; use Magento\Catalog\Test\Page\Adminhtml\CatalogProductNew; -use Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Variations\Config as TabVariation; +use Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Section\Variations\Config as SectionVariation; use Magento\ConfigurableProduct\Test\Fixture\ConfigurableProduct; use Magento\Mtf\Constraint\AbstractConstraint; @@ -36,11 +36,11 @@ class AssertProductAttributeIsConfigurable extends AbstractConstraint $productGrid->getGridPageActionBlock()->addProduct('configurable'); $productBlockForm = $newProductPage->getProductForm(); $productBlockForm->fill($assertProduct); - $productBlockForm->openTab('variations'); - /** @var \Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Tab\Variations\Config $variationsTab */ - $variationsTab = $productBlockForm->getTab('variations'); - $variationsTab->createConfigurations(); - $attributesGrid = $variationsTab->getAttributeBlock()->getAttributesGrid(); + $productBlockForm->openSection('variations'); + /** @var SectionVariation $variationsSection */ + $variationsSection = $productBlockForm->getSection('variations'); + $variationsSection->createConfigurations(); + $attributesGrid = $variationsSection->getAttributeBlock()->getAttributesGrid(); \PHPUnit_Framework_Assert::assertTrue( $attributesGrid->isRowVisible(['frontend_label' => $attribute->getFrontendLabel()]), "Product attribute is absent on the product page." diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.php index dd7ca68f9b6fcea8e9b82b0d86d283757f3c183f..c800c8b1bfef5ca7a73f53ef6c76709dd886abfd 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestCase/CreateConfigurableProductEntityTest.php @@ -45,21 +45,21 @@ class CreateConfigurableProductEntityTest extends Injectable /* end tags */ /** - * Product page with a grid + * Product page with a grid. * * @var CatalogProductIndex */ protected $productIndex; /** - * Page to create a product + * Page to create a product. * * @var CatalogProductNew */ protected $productNew; /** - * Injection data + * Injection data. * * @param CatalogProductIndex $productIndex * @param CatalogProductNew $productNew @@ -72,14 +72,13 @@ class CreateConfigurableProductEntityTest extends Injectable } /** - * Test create catalog Configurable product run + * Test create catalog Configurable product run. * * @param ConfigurableProduct $product * @return void */ public function test(ConfigurableProduct $product) { - $this->markTestIncomplete('MAGETWO-50179'); // Steps $this->productIndex->open(); $this->productIndex->getGridPageActionBlock()->addProduct('configurable'); diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestStep/UpdateConfigurableProductStep.php b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestStep/UpdateConfigurableProductStep.php index e59e0d6b0d487431ec48696cd78f8eeba7ac8bc8..40dbe1f857f238d0ca7dd21fb1d062e7ba65cad3 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestStep/UpdateConfigurableProductStep.php +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/TestStep/UpdateConfigurableProductStep.php @@ -9,6 +9,8 @@ namespace Magento\ConfigurableProduct\Test\TestStep; use Magento\Catalog\Test\Fixture\CatalogProductAttribute; use Magento\Catalog\Test\Page\Adminhtml\CatalogProductEdit; use Magento\ConfigurableProduct\Test\Fixture\ConfigurableProduct; +use Magento\ConfigurableProduct\Test\Block\Adminhtml\Product\Edit\Section\Variations\Config; +use Magento\Catalog\Test\Page\Adminhtml\CatalogProductIndex; use Magento\Mtf\Fixture\FixtureFactory; use Magento\Mtf\TestStep\TestStepInterface; @@ -59,9 +61,15 @@ class UpdateConfigurableProductStep implements TestStepInterface */ protected $attributeTypeAction = ''; + /** + * @var CatalogProductIndex + */ + private $productGrid; + /** * @constructor * @param FixtureFactory $fixtureFactory + * @param CatalogProductIndex $productGrid * @param CatalogProductEdit $catalogProductEdit * @param ConfigurableProduct $product * @param ConfigurableProduct $updatedProduct @@ -69,6 +77,7 @@ class UpdateConfigurableProductStep implements TestStepInterface */ public function __construct( FixtureFactory $fixtureFactory, + CatalogProductIndex $productGrid, CatalogProductEdit $catalogProductEdit, ConfigurableProduct $product, ConfigurableProduct $updatedProduct, @@ -79,6 +88,7 @@ class UpdateConfigurableProductStep implements TestStepInterface $this->initialProduct = $product; $this->product = $updatedProduct; $this->attributeTypeAction = $attributeTypeAction; + $this->productGrid = $productGrid; } /** @@ -186,9 +196,17 @@ class UpdateConfigurableProductStep implements TestStepInterface */ protected function updateProduct(ConfigurableProduct $product) { + //open product + $filter = ['sku' => $this->initialProduct->getSku()]; + $this->productGrid->open(); + $this->productGrid->getProductGrid()->searchAndOpen($filter); + + //update $productForm = $this->catalogProductEdit->getProductForm(); - $productForm->openTab('variations'); - $productForm->getTab('variations')->deleteVariations(); + $productForm->openSection('variations'); + /** @var Config $variationsSection */ + $variationsSection = $productForm->getSection('variations'); + $variationsSection->deleteVariations(); $this->catalogProductEdit->getProductForm()->fill($product); } } diff --git a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/etc/testcase.xml b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/etc/testcase.xml index 31c1155f66c1c195ab21abef8b6724ee88f13b9a..c902f9430bcf1ee341e6de84f4ddf7e34c406a8f 100644 --- a/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/etc/testcase.xml +++ b/dev/tests/functional/tests/app/Magento/ConfigurableProduct/Test/etc/testcase.xml @@ -7,10 +7,9 @@ --> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../../../../../../vendor/magento/mtf/Magento/Mtf/TestCase/etc/testcase.xsd"> <scenario name="UpdateConfigurableProductEntityTest" firstStep="createProduct"> - <step name="createProduct" module="Magento_Catalog" next="openProductOnBackend"> + <step name="createProduct" module="Magento_Catalog" next="updateConfigurableProduct"> <item name="product" value="configurableProduct::default"/> </step> - <step name="openProductOnBackend" module="Magento_Catalog" next="updateConfigurableProduct"/> <step name="updateConfigurableProduct" module="Magento_ConfigurableProduct" next="saveProduct"/> <step name="saveProduct" module="Magento_Catalog"/> </scenario> diff --git a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Repository/DownloadableProduct.xml b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Repository/DownloadableProduct.xml index 05ae4f0a614e8f9f9104ebd8d3e63f3a32940f7d..261bb040f55b1284e9729a839061e66d5ba35735 100644 --- a/dev/tests/functional/tests/app/Magento/Downloadable/Test/Repository/DownloadableProduct.xml +++ b/dev/tests/functional/tests/app/Magento/Downloadable/Test/Repository/DownloadableProduct.xml @@ -28,6 +28,7 @@ <field name="downloadable_links" xsi:type="array"> <item name="dataset" xsi:type="string">with_two_separately_links</item> </field> + <field name="product_has_weight" xsi:type="string">This item has no weight</field> <field name="website_ids" xsi:type="array"> <item name="0" xsi:type="string">Main Website</item> </field> diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/AbstractFormContainers.php b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/AbstractFormContainers.php index 6756d4eaf737a058e2cbb803c474e1535917289e..b6ed37af715be90fc600aa5728744ccd3a160d68 100644 --- a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/AbstractFormContainers.php +++ b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/AbstractFormContainers.php @@ -39,6 +39,13 @@ abstract class AbstractFormContainers extends Form */ protected $header = 'header.page-header'; + /** + * Close button locator. + * + * @var string + */ + protected $closeButton = 'aside[style]:not([style=""]) [data-role="closeBtn"]'; + /** * Initialize. * @@ -188,12 +195,15 @@ abstract class AbstractFormContainers extends Form if ($this->openContainer($containerName)) { $mapping = $container->dataMapping($this->unassignedFields); foreach ($mapping as $fieldName => $data) { - $element = $container->_rootElement->find($data['selector'], $data['strategy'], $data['input']); + $element = $this->getElement($this->_rootElement, $data); if ($element->isVisible()) { $element->setValue($data['value']); unset($this->unassignedFields[$fieldName]); } } + if ($this->browser->find($this->closeButton)->isVisible()) { + $this->browser->find($this->closeButton)->click(); + } if (empty($this->unassignedFields)) { break; } diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/FormSections.php b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/FormSections.php index 2bf428feff8ef6290accb174f7f4fd55c3c29d63..6a5919b8cb1cfcfc2c8a666009e977ab0baafe0b 100644 --- a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/FormSections.php +++ b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/FormSections.php @@ -44,6 +44,13 @@ class FormSections extends AbstractFormContainers */ protected $opened = '._show'; + /** + * Locator for error messages. + * + * @var string + */ + protected $errorMessages = '[data-ui-id="messages-message-error"]'; + /** * Get Section class. * @@ -120,24 +127,35 @@ class FormSections extends AbstractFormContainers } /** - * Get Require Notice Attributes. + * Get require notice fields. * * @param InjectableFixture $product * @return array */ - public function getRequireNoticeAttributes(InjectableFixture $product) + public function getRequireNoticeFields(InjectableFixture $product) { $data = []; - $tabs = $this->getFixtureFieldsByContainers($product); - foreach (array_keys($tabs) as $tabName) { - $tab = $this->getSection($tabName); - $this->openSection($tabName); - $errors = $tab->getJsErrors(); + $sections = $this->getFixtureFieldsByContainers($product); + foreach (array_keys($sections) as $sectionName) { + $section = $this->getSection($sectionName); + $this->openSection($sectionName); + $errors = $section->getValidationErrors(); if (!empty($errors)) { - $data[$tabName] = $errors; + $data[$sectionName] = $errors; } } return $data; } + + /** + * Check if section is visible. + * + * @param string $sectionName + * @return bool + */ + public function isSectionVisible($sectionName) + { + return ($this->isCollapsible($sectionName) && !$this->isCollapsed($sectionName)); + } } diff --git a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/Section.php b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/Section.php index ce746e53e4d92c9ded1337e72c9a4b771a478189..f0aafd5250fd4209bc524102ee2f50724fbeeec7 100644 --- a/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/Section.php +++ b/dev/tests/functional/tests/app/Magento/Ui/Test/Block/Adminhtml/Section.php @@ -6,10 +6,68 @@ namespace Magento\Ui\Test\Block\Adminhtml; +use Magento\Mtf\Client\Locator; + /** * Is used to represent any (collapsible) section on the page. */ class Section extends AbstractContainer { - // + /** + * Field with error. + * + * @var string + */ + protected $errorField = '//fieldset/*[contains(@class,"field ")][.//*[contains(@class,"error")]]'; + + /** + * Error label. + * + * @var string + */ + protected $errorLabel = './/*[contains(@class,"label")]'; + + /** + * Error text. + * + * @var string + */ + protected $errorText = './/label[contains(@class,"error")]'; + + /** + * Locator for section. + * + * @var string + */ + protected $section = '[data-index="%s"]'; + + /** + * Get array of label => validation error text. + * + * @return array + */ + public function getValidationErrors() + { + $data = []; + $elements = $this->_rootElement->getElements($this->errorField, Locator::SELECTOR_XPATH); + foreach ($elements as $element) { + $error = $element->find($this->errorText, Locator::SELECTOR_XPATH); + if ($error->isVisible()) { + $label = $element->find($this->errorLabel, Locator::SELECTOR_XPATH)->getText(); + $data[$label] = $error->getText(); + } + } + return $data; + } + + /** + * Check whether section is visible. + * + * @param string $sectionName + * @return bool + */ + public function isSectionVisible($sectionName) + { + return $this->_rootElement->find(sprintf($this->section, $sectionName))->isVisible(); + } } diff --git a/lib/web/mage/backend/jstree-mixin.js b/lib/web/mage/backend/jstree-mixin.js new file mode 100644 index 0000000000000000000000000000000000000000..78e02034fdf0f57ab9a2b698e0e43723cd09f9a7 --- /dev/null +++ b/lib/web/mage/backend/jstree-mixin.js @@ -0,0 +1,13 @@ +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +define([ + 'jquery' +], function ($) { + 'use strict'; + + return function () { + $.jstree._themes = require.s.contexts._.config.baseUrl + 'jquery/jstree/themes/'; + }; +}); diff --git a/setup/src/Magento/Setup/Fixtures/FixtureModel.php b/setup/src/Magento/Setup/Fixtures/FixtureModel.php index edd7297db4b0c1126e8fc1ddf2b8ffd0581e3d04..0bbb4167854d124a3393414276b63623319c7faa 100644 --- a/setup/src/Magento/Setup/Fixtures/FixtureModel.php +++ b/setup/src/Magento/Setup/Fixtures/FixtureModel.php @@ -110,12 +110,8 @@ class FixtureModel foreach ($files as $file) { $file = basename($file, '.php'); /** @var \Magento\Setup\Fixtures\Fixture $fixture */ - $fixture = $this->objectManager->create( - 'Magento\Setup\Fixtures' . '\\' . $file, - [ - 'fixtureModel' => $this - ] - ); + $type = 'Magento\Setup\Fixtures' . '\\' . $file; + $fixture = new $type($this); $this->fixtures[$fixture->getPriority()] = $fixture; } diff --git a/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php b/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php index 769b3b634d0215b53bfbe8f3df7a5c7171aafaae..135e03ae69b800d593bf6c0592f7454c7b9f1da2 100644 --- a/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php +++ b/setup/src/Magento/Setup/Mvc/Bootstrap/InitParamListener.php @@ -123,15 +123,16 @@ class InitParamListener implements ListenerAggregateInterface, FactoryInterface /** @var \Magento\Framework\App\State $adminAppState */ $adminAppState = $objectManager->get('Magento\Framework\App\State'); $adminAppState->setAreaCode(\Magento\Framework\App\Area::AREA_ADMIN); - $objectManager->create( - 'Magento\Backend\Model\Auth\Session', + /** @var \Magento\Backend\Model\Auth\Session $adminSession */ + $adminSession = $objectManager->create( + \Magento\Backend\Model\Auth\Session::class, [ - 'sessionConfig' => $objectManager->get('Magento\Backend\Model\Session\AdminConfig'), + 'sessionConfig' => $objectManager->get(\Magento\Backend\Model\Session\AdminConfig::class), 'appState' => $adminAppState ] ); - - if (!$objectManager->get('Magento\Backend\Model\Auth')->isLoggedIn()) { + if (!$objectManager->get(\Magento\Backend\Model\Auth::class)->isLoggedIn()) { + $adminSession->expireSessionCookie(); $response = $event->getResponse(); $response->getHeaders()->addHeaderLine('Location', 'index.php/session/unlogin'); $response->setStatusCode(302);