diff --git a/app/code/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/Suffix.php b/app/code/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/Suffix.php index 5ed18d15b2f304cdc9ca6e89a7bcc09e2a5c3590..c1f37eca1c55c7b81cf4b14a034738c5211b7085 100644 --- a/app/code/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/Suffix.php +++ b/app/code/Magento/Catalog/Model/System/Config/Backend/Catalog/Url/Rewrite/Suffix.php @@ -40,6 +40,11 @@ class Suffix extends \Magento\Framework\App\Config\Value */ protected $resource; + /** + * @var \Magento\Framework\App\Config\ScopePool + */ + private $scopePool; + /** * @param \Magento\Framework\Model\Context $context * @param \Magento\Framework\Registry $registry @@ -75,6 +80,22 @@ class Suffix extends \Magento\Framework\App\Config\Value $this->resource = $appResource; } + /** + * Get instance of ScopePool + * + * @return \Magento\Framework\App\Config\ScopePool + * @deprecated + */ + private function getScopePool() + { + if ($this->scopePool === null) { + $this->scopePool = \Magento\Framework\App\ObjectManager::getInstance()->get( + \Magento\Framework\App\Config\ScopePool::class + ); + } + return $this->scopePool; + } + /** * Check url rewrite suffix - whether we can support it * @@ -103,6 +124,24 @@ class Suffix extends \Magento\Framework\App\Config\Value return parent::afterSave(); } + /** + * {@inheritdoc} + */ + public function afterDeleteCommit() + { + if ($this->isValueChanged()) { + $this->updateSuffixForUrlRewrites(); + if ($this->isCategorySuffixChanged()) { + $this->cacheTypeList->invalidate([ + \Magento\Framework\App\Cache\Type\Block::TYPE_IDENTIFIER, + \Magento\Framework\App\Cache\Type\Collection::TYPE_IDENTIFIER + ]); + } + } + + return parent::afterDeleteCommit(); + } + /** * Check is category suffix changed * @@ -135,7 +174,12 @@ class Suffix extends \Magento\Framework\App\Config\Value } $entities = $this->urlFinder->findAllByData($dataFilter); $oldSuffixPattern = '~' . preg_quote($this->getOldValue()) . '$~'; - $suffix = $this->getValue(); + if ($this->getValue() !== null) { + $suffix = $this->getValue(); + } else { + $this->getScopePool()->clean(); + $suffix = $this->_config->getValue($this->getPath()); + } foreach ($entities as $urlRewrite) { $bind = $urlRewrite->getIsAutogenerated() ? [UrlRewrite::REQUEST_PATH => preg_replace($oldSuffixPattern, $suffix, $urlRewrite->getRequestPath())] diff --git a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js index ddb62ceb37b37ef6bc7735c78f81367c5c6d4343..8910e41731d11a9be99bf1777dc13e3550781976 100644 --- a/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js +++ b/app/code/Magento/Checkout/view/frontend/web/js/view/shipping.js @@ -179,7 +179,7 @@ define( newShippingAddress; this.source.set('params.invalid', false); - this.source.trigger('shippingAddress.data.validate'); + this.triggerShippingDataValidateEvent(); if (!this.source.get('params.invalid')) { addressData = this.source.get('shippingAddress'); @@ -254,12 +254,7 @@ define( if (this.isFormInline) { this.source.set('params.invalid', false); - this.source.trigger('shippingAddress.data.validate'); - - if (this.source.get('shippingAddress.custom_attributes')) { - this.source.trigger('shippingAddress.custom_attributes.data.validate'); - } - + this.triggerShippingDataValidateEvent(); if (emailValidationResult && this.source.get('params.invalid') || !quote.shippingMethod().method_code || @@ -304,6 +299,18 @@ define( } return true; + }, + + /** + * Trigger Shipping data Validate Event. + * + * @return {void} + */ + triggerShippingDataValidateEvent: function () { + this.source.trigger('shippingAddress.data.validate'); + if (this.source.get('shippingAddress.custom_attributes')) { + this.source.trigger('shippingAddress.custom_attributes.data.validate'); + } } }); } diff --git a/app/code/Magento/ConfigurableProduct/Block/Plugin/Product/Media/Gallery.php b/app/code/Magento/ConfigurableProduct/Block/Plugin/Product/Media/Gallery.php deleted file mode 100644 index a4390bf94865084fd27d401e47982c3bdb3cabbf..0000000000000000000000000000000000000000 --- a/app/code/Magento/ConfigurableProduct/Block/Plugin/Product/Media/Gallery.php +++ /dev/null @@ -1,102 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ -namespace Magento\ConfigurableProduct\Block\Plugin\Product\Media; - -use Magento\ConfigurableProduct\Model\Product\Type\Configurable; - -/** - * Class Gallery - */ -class Gallery extends \Magento\Catalog\Block\Product\View\AbstractView -{ - /** - * @var \Magento\Catalog\Model\Product\Gallery\ReadHandler - */ - private $productGalleryReadHandler; - - /** - * @var \Magento\Framework\Json\EncoderInterface - */ - private $jsonEncoder; - - /** - * @var \Magento\Framework\Json\DecoderInterface - */ - private $jsonDecoder; - - /** - * Gallery constructor. - * @param \Magento\Catalog\Block\Product\Context $context - * @param \Magento\Framework\Stdlib\ArrayUtils $arrayUtils - * @param \Magento\Catalog\Model\Product\Gallery\ReadHandler $productGalleryReadHandler - * @param \Magento\Framework\Json\EncoderInterface $jsonEncoder - * @param \Magento\Framework\Json\DecoderInterface $jsonDecoder - * @param array $data - */ - public function __construct( - \Magento\Catalog\Block\Product\Context $context, - \Magento\Framework\Stdlib\ArrayUtils $arrayUtils, - \Magento\Catalog\Model\Product\Gallery\ReadHandler $productGalleryReadHandler, - \Magento\Framework\Json\EncoderInterface $jsonEncoder, - \Magento\Framework\Json\DecoderInterface $jsonDecoder, - array $data = [] - ) { - $this->productGalleryReadHandler = $productGalleryReadHandler; - $this->jsonEncoder = $jsonEncoder; - $this->jsonDecoder = $jsonDecoder; - parent::__construct($context, $arrayUtils, $data); - } - - /** - * @param \Magento\Catalog\Block\Product\View\Gallery $subject - * @param string $result - * @return string - * - * @SuppressWarnings(PHPMD.UnusedFormalParameter) - */ - public function afterGetOptionsMediaGalleryDataJson( - \Magento\Catalog\Block\Product\View\Gallery $subject, - $result - ) { - $result = $this->jsonDecoder->decode($result); - if ($this->getProduct()->getTypeId() == 'configurable') { - /** @var Configurable $productType */ - $productType = $this->getProduct()->getTypeInstance(); - $products = $productType->getUsedProducts($this->getProduct()); - $attributes = $productType->getConfigurableAttributesAsArray($this->getProduct()); - /** @var \Magento\Catalog\Model\Product $product */ - foreach ($attributes as $attribute) { - foreach ($products as $product) { - $attributeValue = $product->getData($attribute['attribute_code']); - if ($attributeValue) { - $key = $attribute['attribute_code'] . '_' . $attributeValue; - $result[$key] = $this->getProductGallery($product); - } - } - } - } - return $this->jsonEncoder->encode($result); - } - - /** - * @param \Magento\Catalog\Model\Product $product - * @return array - */ - private function getProductGallery($product) - { - $result = []; - $this->productGalleryReadHandler->execute($product); - $images = $product->getMediaGalleryImages(); - foreach ($images as $image) { - $result[] = [ - 'mediaType' => $image->getMediaType(), - 'videoUrl' => $image->getVideoUrl(), - 'isBase' => $product->getImage() == $image->getFile(), - ]; - } - return $result; - } -} diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Block/Plugin/Product/Media/GalleryTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Block/Plugin/Product/Media/GalleryTest.php deleted file mode 100644 index 60aa30c8d40784796192d8c1b7a2ea871e505a25..0000000000000000000000000000000000000000 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Block/Plugin/Product/Media/GalleryTest.php +++ /dev/null @@ -1,111 +0,0 @@ -<?php -/** - * Copyright © 2016 Magento. All rights reserved. - * See COPYING.txt for license details. - */ - -namespace Magento\ConfigurableProduct\Test\Unit\Block\Plugin\Product\Media; - -/** - * Class GalleryTest - */ -class GalleryTest extends \PHPUnit_Framework_TestCase -{ - /** - * @var \Magento\ConfigurableProduct\Block\Plugin\Product\Media\Gallery - */ - private $plugin; - - /** - * @var \Magento\Framework\Json\EncoderInterface|\PHPUnit_Framework_MockObject_MockObject - */ - private $jsonEncoder; - - /** - * @var \Magento\Framework\Json\DecoderInterface|\PHPUnit_Framework_MockObject_MockObject - */ - private $jsonDecoder; - - /** - * @var \Magento\Catalog\Model\Product\Gallery\ReadHandler - */ - private $galleryHandler; - - protected function setUp() - { - $helper = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); - $this->galleryHandler = $this->getMockBuilder(\Magento\Catalog\Model\Product\Gallery\ReadHandler::class) - ->disableOriginalConstructor() - ->setMethods(['execute']) - ->getMock(); - - $this->jsonEncoder = $this->getMock(\Magento\Framework\Json\EncoderInterface::class); - $this->jsonDecoder = $this->getMock(\Magento\Framework\Json\DecoderInterface::class); - - $productMock = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) - ->setMethods(['getTypeId', 'getTypeInstance']) - ->disableOriginalConstructor() - ->getMock(); - - $variationProduct = $this->getMockBuilder(\Magento\Catalog\Model\Product::class) - ->setMethods(['setMediaGalleryEntries', 'getSku', 'getMediaGalleryImages', 'getImage', 'getData']) - ->disableOriginalConstructor() - ->getMock(); - $image = new \Magento\Framework\DataObject( - ['media_type' => 'type', 'video_url' => 'url', 'file' => 'image.jpg'] - ); - $variationProduct->expects($this->any())->method('setMediaGalleryEntries')->willReturn([]); - $variationProduct->expects($this->any())->method('getSku')->willReturn('sku'); - $variationProduct->expects($this->any())->method('getMediaGalleryImages')->willReturn([$image]); - $variationProduct->expects($this->any())->method('getImage')->willReturn('image.jpg'); - $variationProduct->expects($this->any())->method('getData')->with('configurable_attribute')->willReturn(1); - - $this->galleryHandler->expects($this->once())->method('execute')->with($variationProduct); - - $configurableType = $this->getMockBuilder(\Magento\ConfigurableProduct\Model\Product\Type\Configurable::class) - ->disableOriginalConstructor() - ->setMethods(['getUsedProducts', 'getConfigurableAttributesAsArray']) - ->getMock(); - $configurableType->expects($this->any())->method('getUsedProducts')->with($productMock) - ->willReturn([$variationProduct]); - $configurableType->expects($this->any())->method('getConfigurableAttributesAsArray')->with($productMock) - ->willReturn([['attribute_code' => 'configurable_attribute']]); - - $productMock->expects($this->any())->method('getTypeId')->willReturn('configurable'); - $productMock->expects($this->any())->method('getTypeInstance')->willReturn($configurableType); - - $this->plugin = $helper->getObject( - \Magento\ConfigurableProduct\Block\Plugin\Product\Media\Gallery::class, - [ - 'productGalleryReadHandler' => $this->galleryHandler, - 'jsonEncoder' => $this->jsonEncoder, - 'jsonDecoder' => $this->jsonDecoder - ] - ); - $this->plugin->setData('product', $productMock); - } - - public function testAfterGetOptions() - { - $resultJson = '[]'; - $this->jsonDecoder->expects($this->once())->method('decode')->with('[]')->willReturn([]); - $expected = [ - 'configurable_attribute_1' => [ - [ - 'mediaType' => 'type', - 'videoUrl' => 'url', - 'isBase' => true - ] - ] - ]; - $this->jsonEncoder->expects($this->any())->method('encode')->with($expected) - ->willReturn(json_encode($expected)); - - $blockMock = $this->getMockBuilder(\Magento\ProductVideo\Block\Product\View\Gallery::class) - ->disableOriginalConstructor() - ->getMock(); - - $result = $this->plugin->afterGetOptionsMediaGalleryDataJson($blockMock, $resultJson); - $this->assertEquals(json_encode($expected), $result); - } -} diff --git a/app/code/Magento/ConfigurableProduct/etc/di.xml b/app/code/Magento/ConfigurableProduct/etc/di.xml index b4d63d9d0245f84b3ecbae128e5254e8f9bf213a..ca06ce5cc974bbab05232bdee33920ba87918ade 100644 --- a/app/code/Magento/ConfigurableProduct/etc/di.xml +++ b/app/code/Magento/ConfigurableProduct/etc/di.xml @@ -143,9 +143,6 @@ <type name="Magento\Catalog\Model\Product\Attribute\Backend\Price"> <plugin name="configurable" type="Magento\ConfigurableProduct\Model\Plugin\PriceBackend" sortOrder="100" /> </type> - <type name="\Magento\ProductVideo\Block\Product\View\Gallery"> - <plugin name="product_video_gallery" type="\Magento\ConfigurableProduct\Block\Plugin\Product\Media\Gallery" /> - </type> <type name="Magento\ConfigurableProduct\Model\Product\Type\Configurable"> <arguments> <argument name="cache" xsi:type="object">Magento\Framework\App\Cache\Type\Collection</argument> diff --git a/app/code/Magento/Wishlist/view/frontend/layout/catalog_product_view.xml b/app/code/Magento/Wishlist/view/frontend/layout/catalog_product_view.xml index 4c01d341bb68294cae5d48f5ab2dd99d8d5b08d8..a25546b1afc902a563c296a7adc24b1a9787729b 100644 --- a/app/code/Magento/Wishlist/view/frontend/layout/catalog_product_view.xml +++ b/app/code/Magento/Wishlist/view/frontend/layout/catalog_product_view.xml @@ -16,7 +16,7 @@ </arguments> </block> <referenceBlock name="product.info.addto"> - <block class="Magento\Wishlist\Block\Catalog\Product\View\AddTo\Wishlist" name="view.addto.wishlist" after="view.addto.requisition" + <block class="Magento\Wishlist\Block\Catalog\Product\View\AddTo\Wishlist" name="view.addto.wishlist" template="Magento_Wishlist::catalog/product/view/addto/wishlist.phtml" /> </referenceBlock> </referenceContainer> diff --git a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure.xml b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure.xml index 50ba68940fc9d4027b359fe72ec86b305fb0f69a..02b737b7d5127320207669379ea7e3b09ddb5ac1 100644 --- a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure.xml +++ b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure.xml @@ -9,7 +9,7 @@ <update handle="catalog_product_view"/> <body> <referenceBlock name="product.info.addto"> - <block class="Magento\Wishlist\Block\Item\Configure" name="view.addto.wishlist" after="view.addto.requisition" + <block class="Magento\Wishlist\Block\Item\Configure" name="view.addto.wishlist" template="item/configure/addto/wishlist.phtml" /> </referenceBlock> </body> diff --git a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_bundle.xml b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_bundle.xml index b08816a6728eb54b79ec806084f4a4e684702a29..84d0429a29c99ba204ec9d4401b69d2bf68e1abf 100644 --- a/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_bundle.xml +++ b/app/code/Magento/Wishlist/view/frontend/layout/wishlist_index_configure_type_bundle.xml @@ -20,7 +20,7 @@ <block class="Magento\Catalog\Block\Product\View" name="product.info.addtocart.bundle" as="addtocart" template="product/view/addtocart.phtml" /> <block class="Magento\Catalog\Block\Product\View" name="product.info.addto.bundle" as="addto" after="product.info.addtocart.bundle" template="Magento_Catalog::product/view/addto.phtml" cacheable="false"> - <block class="Magento\Wishlist\Block\Item\Configure" name="view.addto.wishlist.bundle" after="view.addto.requisition" + <block class="Magento\Wishlist\Block\Item\Configure" name="view.addto.wishlist.bundle" template="item/configure/addto/wishlist.phtml" /> <block class="Magento\Catalog\Block\Product\View\AddTo\Compare" name="view.addto.compare.bundle" after="view.addto.wishlist" template="Magento_Catalog::product/view/addto/compare.phtml" /> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php index d29bad980faca881468ae1cf3a58523e13f7ad83..f2530c016b714bf5af16c2b6d0f0f6d690cc4af0 100644 --- a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping.php @@ -6,13 +6,60 @@ namespace Magento\Checkout\Test\Block\Onepage; +use Magento\Checkout\Test\Block\Onepage\Shipping\AddressModal; use Magento\Mtf\Block\Form; +use Magento\Mtf\Client\Locator; /** * Checkout shipping address block. */ class Shipping extends Form { + /** + * CSS Selector for "New Address" button + * + * @var string + */ + private $newAddressButton = '[data-bind*="isNewAddressAdded"]'; + + /** + * Wait element. + * + * @var string + */ + private $waitElement = '.loading-mask'; + + /** + * SCC Selector for Address Modal block. + * + * @var string + */ + private $addressModalBlock = '//*[@id="opc-new-shipping-address"]/../..'; + + /** + * Click on "New Address" button. + * + * @return void + */ + public function clickOnNewAddressButton() + { + $this->waitForElementNotVisible($this->waitElement); + $this->_rootElement->find($this->newAddressButton)->click(); + } + + /** + * Get Address Modal Block. + * + * @return AddressModal + */ + public function getAddressModalBlock() + { + return $this->blockFactory->create( + AddressModal::class, + ['element' => $this->browser->find($this->addressModalBlock, Locator::SELECTOR_XPATH)] + ); + } + /** * Returns form's required elements * diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.php new file mode 100644 index 0000000000000000000000000000000000000000..8a949c474bc847942f1bd5922d00514cd6133d08 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.php @@ -0,0 +1,68 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Checkout\Test\Block\Onepage\Shipping; + +use Magento\Mtf\Block\Form; + +/** + * Checkout shipping address modal block. + */ +class AddressModal extends Form +{ + /** + * CSS Selector for Save button. + * + * @var string + */ + private $saveButton = '.action-save-address'; + + /** + * Selector for field's error message. + * + * @var string + */ + private $errorMessage = '.field-error'; + + /** + * Selector for error fields. + * + * @var string + */ + private $errorField = '._error'; + + /** + * Selector for field label that have error message. + * + * @var string + */ + private $fieldLabel = '.label'; + + /** + * Click on 'Save Address' button. + * + * @return void + */ + public function save() + { + $this->_rootElement->find($this->saveButton)->click(); + } + + /** + * Get Error messages for attributes. + * + * @return array + */ + public function getErrorMessages() + { + $result = []; + foreach ($this->_rootElement->getElements($this->errorField) as $item) { + $result[$item->find($this->fieldLabel)->getText()] = $item->find($this->errorMessage)->getText(); + } + + return $result; + } +} diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.xml b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.xml new file mode 100644 index 0000000000000000000000000000000000000000..13403b792684512c9741bca74a78f7c84036eb48 --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/Block/Onepage/Shipping/AddressModal.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" ?> +<!-- +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ +--> +<mapping strict="0"> + <fields> + <firstname /> + <lastname /> + <company /> + <street> + <selector>input[name="street[0]"]</selector> + </street> + <city /> + <region_id> + <input>select</input> + </region_id> + <country_id> + <input>select</input> + </country_id> + <telephone /> + <postcode /> + </fields> +</mapping> diff --git a/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/AddNewShippingAddressStep.php b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/AddNewShippingAddressStep.php new file mode 100644 index 0000000000000000000000000000000000000000..a4ae00510a9de0b2e9e7d82ff3285e0ae780a7cc --- /dev/null +++ b/dev/tests/functional/tests/app/Magento/Checkout/Test/TestStep/AddNewShippingAddressStep.php @@ -0,0 +1,57 @@ +<?php +/** + * Copyright © 2016 Magento. All rights reserved. + * See COPYING.txt for license details. + */ + +namespace Magento\Checkout\Test\TestStep; + +use Magento\Checkout\Test\Page\CheckoutOnepage; +use Magento\Customer\Test\Fixture\Address; +use Magento\Mtf\TestStep\TestStepInterface; + +/** + * Create customer custom attribute step. + */ +class AddNewShippingAddressStep implements TestStepInterface +{ + /** + * Checkout One page. + * + * @var CheckoutOnepage + */ + private $checkoutOnepage; + + /** + * Shipping Address fixture. + * + * @var Address + */ + private $address; + + /** + * @constructor + * @param CheckoutOnepage $checkoutOnepage + * @param Address|null $address [optional] + */ + public function __construct(CheckoutOnepage $checkoutOnepage, Address $address = null) + { + $this->checkoutOnepage = $checkoutOnepage; + $this->address = $address; + } + + /** + * Create customer account. + * + * @return void + */ + public function run() + { + $shippingBlock = $this->checkoutOnepage->getShippingBlock(); + $shippingBlock->clickOnNewAddressButton(); + if ($this->address) { + $shippingBlock->getAddressModalBlock()->fill($this->address); + } + $shippingBlock->getAddressModalBlock()->save(); + } +}