From 6409dbecac36b69629d3665dc529d43427af72f6 Mon Sep 17 00:00:00 2001 From: "v.sikailo" Date: Thu, 31 Jan 2019 12:24:52 +0200 Subject: [PATCH 01/24] partial fixes in Newsletter module - PHPDocs - strict_type --- app/code/Magento/Newsletter/Block/Adminhtml/Problem.php | 4 ++-- .../Controller/Adminhtml/Subscriber/MassDelete.php | 3 ++- app/code/Magento/Newsletter/Controller/Manage/Save.php | 9 +++++---- .../Magento/Newsletter/Controller/Subscriber/Confirm.php | 6 ++++-- app/code/Magento/Newsletter/Model/Subscriber.php | 2 +- 5 files changed, 14 insertions(+), 10 deletions(-) diff --git a/app/code/Magento/Newsletter/Block/Adminhtml/Problem.php b/app/code/Magento/Newsletter/Block/Adminhtml/Problem.php index 61a17d7ad5e51..6534f39451275 100644 --- a/app/code/Magento/Newsletter/Block/Adminhtml/Problem.php +++ b/app/code/Magento/Newsletter/Block/Adminhtml/Problem.php @@ -83,7 +83,7 @@ protected function _prepareLayout() /** * Get the html element for unsubscribe button * - * @return $string + * @return string */ public function getUnsubscribeButtonHtml() { @@ -93,7 +93,7 @@ public function getUnsubscribeButtonHtml() /** * Get the html element for delete button * - * @return $string + * @return string */ public function getDeleteButtonHtml() { diff --git a/app/code/Magento/Newsletter/Controller/Adminhtml/Subscriber/MassDelete.php b/app/code/Magento/Newsletter/Controller/Adminhtml/Subscriber/MassDelete.php index 7f02e4ea13445..0afc98a5cc12e 100644 --- a/app/code/Magento/Newsletter/Controller/Adminhtml/Subscriber/MassDelete.php +++ b/app/code/Magento/Newsletter/Controller/Adminhtml/Subscriber/MassDelete.php @@ -18,10 +18,11 @@ class MassDelete extends Subscriber * @var SubscriberFactory */ private $subscriberFactory; - + /** * @param Context $context * @param FileFactory $fileFactory + * @param SubscriberFactory|null $subscriberFactory */ public function __construct( Context $context, diff --git a/app/code/Magento/Newsletter/Controller/Manage/Save.php b/app/code/Magento/Newsletter/Controller/Manage/Save.php index 698c2d19aae68..400922f149f8e 100644 --- a/app/code/Magento/Newsletter/Controller/Manage/Save.php +++ b/app/code/Magento/Newsletter/Controller/Manage/Save.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); namespace Magento\Newsletter\Controller\Manage; @@ -65,9 +66,9 @@ public function __construct( /** * Save newsletter subscription preference action * - * @return void|null + * @return \Magento\Framework\App\ResponseInterface */ - public function execute() + public function execute(): \Magento\Framework\App\ResponseInterface { if (!$this->formKeyValidator->validate($this->getRequest())) { return $this->_redirect('customer/account/'); @@ -110,7 +111,7 @@ public function execute() $this->messageManager->addError(__('Something went wrong while saving your subscription.')); } } - $this->_redirect('customer/account/'); + return $this->_redirect('customer/account/'); } /** @@ -119,7 +120,7 @@ public function execute() * @param Customer $customer * @return void */ - private function setIgnoreValidationFlag($customer) + private function setIgnoreValidationFlag(Customer $customer): void { $customer->setData('ignore_validation_flag', true); } diff --git a/app/code/Magento/Newsletter/Controller/Subscriber/Confirm.php b/app/code/Magento/Newsletter/Controller/Subscriber/Confirm.php index 4e338c2d1df34..8d1114b66acf0 100644 --- a/app/code/Magento/Newsletter/Controller/Subscriber/Confirm.php +++ b/app/code/Magento/Newsletter/Controller/Subscriber/Confirm.php @@ -4,15 +4,17 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ +declare(strict_types=1); + namespace Magento\Newsletter\Controller\Subscriber; class Confirm extends \Magento\Newsletter\Controller\Subscriber { /** * Subscription confirm action - * @return void + * @return \Magento\Framework\Controller\Result\Redirect */ - public function execute() + public function execute(): \Magento\Framework\Controller\Result\Redirect { $id = (int)$this->getRequest()->getParam('id'); $code = (string)$this->getRequest()->getParam('code'); diff --git a/app/code/Magento/Newsletter/Model/Subscriber.php b/app/code/Magento/Newsletter/Model/Subscriber.php index e7e5d5f202811..eb87f303b84d2 100644 --- a/app/code/Magento/Newsletter/Model/Subscriber.php +++ b/app/code/Magento/Newsletter/Model/Subscriber.php @@ -686,7 +686,7 @@ public function confirm($code) * Mark receiving subscriber of queue newsletter * * @param \Magento\Newsletter\Model\Queue $queue - * @return boolean + * @return Subscriber */ public function received(\Magento\Newsletter\Model\Queue $queue) { From ed43407dde622f7b6047b99c65fa5bd71db6d986 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Mon, 11 Feb 2019 13:00:29 +0100 Subject: [PATCH 02/24] Fix checking if image is in media directory --- app/code/Magento/Catalog/Model/Category/FileInfo.php | 2 +- .../Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Category/FileInfo.php b/app/code/Magento/Catalog/Model/Category/FileInfo.php index 9715bb2b1616e..d4d4389630528 100644 --- a/app/code/Magento/Catalog/Model/Category/FileInfo.php +++ b/app/code/Magento/Catalog/Model/Category/FileInfo.php @@ -76,7 +76,7 @@ private function getMediaDirectory() private function getBaseDirectory() { if (!isset($this->baseDirectory)) { - $this->baseDirectory = $this->filesystem->getDirectoryRead(DirectoryList::ROOT); + $this->baseDirectory = $this->filesystem->getDirectoryRead(DirectoryList::PUB); } return $this->baseDirectory; diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php index 8ca823127e66c..967e7d5889a17 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php @@ -57,7 +57,7 @@ protected function setUp() $this->filesystem->expects($this->any()) ->method('getDirectoryRead') - ->with(DirectoryList::ROOT) + ->with(DirectoryList::PUB) ->willReturn($this->baseDirectory); $this->mime = $this->getMockBuilder(Mime::class) From 17ed8d47f722dea48ea6ddb80c16a08228205702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Mon, 18 Mar 2019 23:08:40 +0100 Subject: [PATCH 03/24] Revert change from Root to Pub, trim pub directory if filePath not begins with it --- .../Magento/Catalog/Model/Category/FileInfo.php | 14 ++++++++++---- .../Test/Unit/Model/Category/FileInfoTest.php | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Category/FileInfo.php b/app/code/Magento/Catalog/Model/Category/FileInfo.php index d4d4389630528..ba4d3e9609412 100644 --- a/app/code/Magento/Catalog/Model/Category/FileInfo.php +++ b/app/code/Magento/Catalog/Model/Category/FileInfo.php @@ -76,7 +76,7 @@ private function getMediaDirectory() private function getBaseDirectory() { if (!isset($this->baseDirectory)) { - $this->baseDirectory = $this->filesystem->getDirectoryRead(DirectoryList::PUB); + $this->baseDirectory = $this->filesystem->getDirectoryRead(DirectoryList::ROOT); } return $this->baseDirectory; @@ -135,7 +135,7 @@ private function getFilePath($fileName) { $filePath = ltrim($fileName, '/'); - $mediaDirectoryRelativeSubpath = $this->getMediaDirectoryPathRelativeToBaseDirectoryPath(); + $mediaDirectoryRelativeSubpath = $this->getMediaDirectoryPathRelativeToBaseDirectoryPath($filePath); $isFileNameBeginsWithMediaDirectoryPath = $this->isBeginsWithMediaDirectoryPath($fileName); // if the file is not using a relative path, it resides in the catalog/category media directory @@ -160,7 +160,7 @@ public function isBeginsWithMediaDirectoryPath($fileName) { $filePath = ltrim($fileName, '/'); - $mediaDirectoryRelativeSubpath = $this->getMediaDirectoryPathRelativeToBaseDirectoryPath(); + $mediaDirectoryRelativeSubpath = $this->getMediaDirectoryPathRelativeToBaseDirectoryPath($filePath); $isFileNameBeginsWithMediaDirectoryPath = strpos($filePath, $mediaDirectoryRelativeSubpath) === 0; return $isFileNameBeginsWithMediaDirectoryPath; @@ -169,14 +169,20 @@ public function isBeginsWithMediaDirectoryPath($fileName) /** * Get media directory subpath relative to base directory path * + * @param string $filePath * @return string */ - private function getMediaDirectoryPathRelativeToBaseDirectoryPath() + private function getMediaDirectoryPathRelativeToBaseDirectoryPath(string $filePath = '') { $baseDirectoryPath = $this->getBaseDirectory()->getAbsolutePath(); $mediaDirectoryPath = $this->getMediaDirectory()->getAbsolutePath(); $mediaDirectoryRelativeSubpath = substr($mediaDirectoryPath, strlen($baseDirectoryPath)); + $pubDirectory = 'pub/'; + + if (strpos($mediaDirectoryRelativeSubpath, $pubDirectory) === 0 && strpos($filePath, $pubDirectory) !== 0) { + $mediaDirectoryRelativeSubpath = substr($mediaDirectoryRelativeSubpath, strlen($pubDirectory)); + } return $mediaDirectoryRelativeSubpath; } diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php index 967e7d5889a17..8ca823127e66c 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php @@ -57,7 +57,7 @@ protected function setUp() $this->filesystem->expects($this->any()) ->method('getDirectoryRead') - ->with(DirectoryList::PUB) + ->with(DirectoryList::ROOT) ->willReturn($this->baseDirectory); $this->mime = $this->getMockBuilder(Mime::class) From 112476a20ce1e2685fc62f315372870cb0da3743 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Tue, 26 Mar 2019 20:19:35 +0100 Subject: [PATCH 04/24] Change hardcoded pub path to constant --- app/code/Magento/Catalog/Model/Category/FileInfo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/Category/FileInfo.php b/app/code/Magento/Catalog/Model/Category/FileInfo.php index ba4d3e9609412..94189a67d6e74 100644 --- a/app/code/Magento/Catalog/Model/Category/FileInfo.php +++ b/app/code/Magento/Catalog/Model/Category/FileInfo.php @@ -178,7 +178,7 @@ private function getMediaDirectoryPathRelativeToBaseDirectoryPath(string $filePa $mediaDirectoryPath = $this->getMediaDirectory()->getAbsolutePath(); $mediaDirectoryRelativeSubpath = substr($mediaDirectoryPath, strlen($baseDirectoryPath)); - $pubDirectory = 'pub/'; + $pubDirectory = DirectoryList::PUB . DIRECTORY_SEPARATOR; if (strpos($mediaDirectoryRelativeSubpath, $pubDirectory) === 0 && strpos($filePath, $pubDirectory) !== 0) { $mediaDirectoryRelativeSubpath = substr($mediaDirectoryRelativeSubpath, strlen($pubDirectory)); From 9c9b3126ece8a455fed0668971de95e35162a9a8 Mon Sep 17 00:00:00 2001 From: Karan Shah Date: Mon, 15 Apr 2019 15:43:43 +0530 Subject: [PATCH 05/24] Apply-coupoun-and-scroll-top-to-check.-applied-successfully-or-not --- .../Magento/Sales/view/adminhtml/web/order/create/scripts.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js b/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js index c508a5ecdfa58..23912c9071553 100644 --- a/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js +++ b/app/code/Magento/Sales/view/adminhtml/web/order/create/scripts.js @@ -561,6 +561,9 @@ define([ applyCoupon : function(code){ this.loadArea(['items', 'shipping_method', 'totals', 'billing_method'], true, {'order[coupon][code]':code, reset_shipping: 0}); this.orderItemChanged = false; + jQuery('html, body').animate({ + scrollTop: 0 + }); }, addProduct : function(id){ From b8bc2885b4059fe6c0f932a26a6495d6f7399896 Mon Sep 17 00:00:00 2001 From: Surabhi Srivastava Date: Sat, 4 May 2019 06:04:57 +0000 Subject: [PATCH 06/24] Fixed Issue #22087 Fixed Issue #22087 --- .../Reports/Model/ResourceModel/Product/Sold/Collection.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/code/Magento/Reports/Model/ResourceModel/Product/Sold/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Product/Sold/Collection.php index 61dc77d188438..cd628c7a19c2b 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Product/Sold/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Product/Sold/Collection.php @@ -79,6 +79,10 @@ public function addOrderedQty($from = '', $to = '') )->having( 'order_items.qty_ordered > ?', 0 + )->columns( + 'SUM(order_items.qty_ordered) as ordered_qty' + )->group( + 'order_items.product_id' ); return $this; } From 82d09dcee2e57733c454e34dd48cb322bcccc17b Mon Sep 17 00:00:00 2001 From: Nazarn96 Date: Mon, 6 May 2019 13:13:59 +0300 Subject: [PATCH 07/24] magento/magento2#22646 static-test-fix --- .../Reports/Model/ResourceModel/Product/Sold/Collection.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/Reports/Model/ResourceModel/Product/Sold/Collection.php b/app/code/Magento/Reports/Model/ResourceModel/Product/Sold/Collection.php index cd628c7a19c2b..35a14e09e314f 100644 --- a/app/code/Magento/Reports/Model/ResourceModel/Product/Sold/Collection.php +++ b/app/code/Magento/Reports/Model/ResourceModel/Product/Sold/Collection.php @@ -14,6 +14,8 @@ use Magento\Framework\DB\Select; /** + * Data collection. + * * @SuppressWarnings(PHPMD.DepthOfInheritance) * @api * @since 100.0.2 @@ -21,7 +23,7 @@ class Collection extends \Magento\Reports\Model\ResourceModel\Order\Collection { /** - * Set Date range to collection + * Set Date range to collection. * * @param int $from * @param int $to @@ -120,6 +122,8 @@ public function setOrder($attribute, $dir = self::SORT_ORDER_DESC) } /** + * @inheritdoc + * * @return Select * @since 100.2.0 */ From 8522a14fefe581e64691bdaebf8f6589a927978b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Tue, 7 May 2019 00:12:53 +0200 Subject: [PATCH 08/24] Fix #19872 - replace DirectoryList::PUB with string --- app/code/Magento/Catalog/Model/Category/FileInfo.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Catalog/Model/Category/FileInfo.php b/app/code/Magento/Catalog/Model/Category/FileInfo.php index 94189a67d6e74..a474eb764d2c0 100644 --- a/app/code/Magento/Catalog/Model/Category/FileInfo.php +++ b/app/code/Magento/Catalog/Model/Category/FileInfo.php @@ -178,7 +178,7 @@ private function getMediaDirectoryPathRelativeToBaseDirectoryPath(string $filePa $mediaDirectoryPath = $this->getMediaDirectory()->getAbsolutePath(); $mediaDirectoryRelativeSubpath = substr($mediaDirectoryPath, strlen($baseDirectoryPath)); - $pubDirectory = DirectoryList::PUB . DIRECTORY_SEPARATOR; + $pubDirectory = 'pub' . DIRECTORY_SEPARATOR; if (strpos($mediaDirectoryRelativeSubpath, $pubDirectory) === 0 && strpos($filePath, $pubDirectory) !== 0) { $mediaDirectoryRelativeSubpath = substr($mediaDirectoryRelativeSubpath, strlen($pubDirectory)); From c50975a7b3dd61cbc0d030cb56b4f0099a61921d Mon Sep 17 00:00:00 2001 From: Nazarn96 Date: Mon, 8 Apr 2019 16:47:00 +0300 Subject: [PATCH 09/24] getUrlInStore() does not allow to override the scope in backend context --- app/code/Magento/Backend/Model/Url.php | 21 ++++++++-- .../Magento/Catalog/Model/Product/UrlTest.php | 40 +++++++++++++++++++ 2 files changed, 57 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Backend/Model/Url.php b/app/code/Magento/Backend/Model/Url.php index f199fd0fe7bf1..ba0c3d1cfacee 100644 --- a/app/code/Magento/Backend/Model/Url.php +++ b/app/code/Magento/Backend/Model/Url.php @@ -13,6 +13,7 @@ * Class \Magento\Backend\Model\UrlInterface * * @SuppressWarnings(PHPMD.CouplingBetweenObjects) + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) * @api * @since 100.0.2 */ @@ -366,6 +367,19 @@ protected function _getMenu() return $this->_menu; } + /** + * Set scope entity + * + * @param mixed $scopeId + * @return \Magento\Framework\UrlInterface + */ + public function setScope($scopeId) + { + parent::setScope($scopeId); + $this->_scope = $this->_scopeResolver->getScope($scopeId); + return $this; + } + /** * Set custom auth session * @@ -402,13 +416,13 @@ public function getAreaFrontName() } /** - * Retrieve action path. - * Add backend area front name as a prefix to action path + * Retrieve action path, add backend area front name as a prefix to action path * * @return string */ protected function _getActionPath() { + $path = parent::_getActionPath(); if ($path) { if ($this->getAreaFrontName()) { @@ -448,8 +462,7 @@ protected function _getConfigCacheId($path) } /** - * Get config data by path - * Use only global config values for backend + * Get config data by path, use only global config values for backend * * @param string $path * @return null|string diff --git a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/UrlTest.php b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/UrlTest.php index f9075a58c39ef..4cf059d4bf692 100644 --- a/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/UrlTest.php +++ b/dev/tests/integration/testsuite/Magento/Catalog/Model/Product/UrlTest.php @@ -42,6 +42,46 @@ public function testGetUrlInStore() $this->assertStringEndsWith('simple-product.html', $this->_model->getUrlInStore($product)); } + /** + * @magentoDataFixture Magento/Store/_files/second_store.php + * @magentoConfigFixture default_store web/unsecure/base_url http://sample.com/ + * @magentoConfigFixture default_store web/unsecure/base_link_url http://sample.com/ + * @magentoConfigFixture fixturestore_store web/unsecure/base_url http://sample-second.com/ + * @magentoConfigFixture fixturestore_store web/unsecure/base_link_url http://sample-second.com/ + * @magentoDataFixture Magento/Catalog/_files/product_simple_multistore.php + * @dataProvider getUrlsWithSecondStoreProvider + * @magentoAppArea adminhtml + */ + public function testGetUrlInStoreWithSecondStore($storeCode, $expectedProductUrl) + { + $repository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( + \Magento\Catalog\Model\ProductRepository::class + ); + /** @var \Magento\Store\Model\Store $store */ + $store = \Magento\TestFramework\Helper\Bootstrap::getObjectManager() + ->create(\Magento\Store\Model\Store::class); + $store->load($storeCode, 'code'); + /** @var \Magento\Store\Model\Store $store */ + + $product = $repository->get('simple'); + + $this->assertEquals( + $expectedProductUrl, + $this->_model->getUrlInStore($product, ['_scope' => $store->getId(), '_nosid' => true]) + ); + } + + /** + * @return array + */ + public function getUrlsWithSecondStoreProvider() + { + return [ + 'case1' => ['fixturestore', 'http://sample-second.com/index.php/simple-product-one.html'], + 'case2' => ['default', 'http://sample.com/index.php/simple-product-one.html'] + ]; + } + public function testGetProductUrl() { $repository = \Magento\TestFramework\Helper\Bootstrap::getObjectManager()->create( From c9f98fcebb40bbb9ee8fd7ca6f27e63c86ecc2ab Mon Sep 17 00:00:00 2001 From: niravkrish Date: Fri, 24 May 2019 15:04:27 +0530 Subject: [PATCH 10/24] Fixed - Reset feature does not clear the date --- app/code/Magento/Ui/view/base/web/js/form/form.js | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/Ui/view/base/web/js/form/form.js b/app/code/Magento/Ui/view/base/web/js/form/form.js index ea6c57f63bdf1..bf27cbbb7660f 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/form.js +++ b/app/code/Magento/Ui/view/base/web/js/form/form.js @@ -339,6 +339,7 @@ define([ */ reset: function () { this.source.trigger('data.reset'); + $('._has-datepicker').val(''); }, /** From a50d6292f90b1a4e27ef9fae2a769bee010ee6e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Simon=20Schr=C3=B6er?= Date: Mon, 27 May 2019 16:42:49 +0200 Subject: [PATCH 11/24] Re-enable XML as request and response types within the SwaggerUI --- .../Webapi/Model/Rest/Swagger/Generator.php | 40 +++++++++++++++++++ .../Unit/Model/Rest/Swagger/GeneratorTest.php | 4 +- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php b/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php index 855f455120d89..14b65bb640242 100644 --- a/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php +++ b/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php @@ -41,6 +41,11 @@ class Generator extends AbstractSchemaGenerator /** Array signifier */ const ARRAY_SIGNIFIER = '[0]'; + /** + * Wrapper node for XML requests + */ + const XML_SCHEMA_PARAMWRAPPER = 'request'; + /** * Swagger factory instance. * @@ -193,6 +198,28 @@ protected function getGeneralInfo() ]; } + /** + * @return string[] + */ + protected function getConsumableDatatypes() + { + return [ + 'application/json', + 'application/xml', + ]; + } + + /** + * @return string[] + */ + protected function getProducibleDatatypes() + { + return [ + 'application/json', + 'application/xml', + ]; + } + /** * Generate path info based on method data * @@ -212,6 +239,8 @@ protected function generatePathInfo($methodName, $httpMethodData, $tagName) 'tags' => [$tagName], 'description' => $methodData['documentation'], 'operationId' => $operationId, + 'consumes' => $this->getConsumableDatatypes(), + 'produces' => $this->getProducibleDatatypes(), ]; $parameters = $this->generateMethodParameters($httpMethodData, $operationId); @@ -842,6 +871,17 @@ private function generateBodySchema($parameterName, $parameterInfo, $description $description ); $bodySchema['type'] = 'object'; + + /* + * Make shure we have a proper XML wrapper for request parameters for the XML fromat. + */ + if (!isset($bodySchema['xml']) || !is_array($bodySchema['xml'])) { + $bodySchema['xml'] = []; + } + if (!isset($bodySchema['xml']['name']) || empty($bodySchema['xml']['name'])) { + $bodySchema['xml']['name'] = self::XML_SCHEMA_PARAMWRAPPER; + } + return $bodySchema; } diff --git a/app/code/Magento/Webapi/Test/Unit/Model/Rest/Swagger/GeneratorTest.php b/app/code/Magento/Webapi/Test/Unit/Model/Rest/Swagger/GeneratorTest.php index 66b59babb7189..172db875c6c49 100644 --- a/app/code/Magento/Webapi/Test/Unit/Model/Rest/Swagger/GeneratorTest.php +++ b/app/code/Magento/Webapi/Test/Unit/Model/Rest/Swagger/GeneratorTest.php @@ -223,7 +223,7 @@ public function generateDataProvider() ] ], // @codingStandardsIgnoreStart - '{"swagger":"2.0","info":{"version":"","title":""},"host":"magento.host","basePath":"/rest/default","schemes":["http://"],"tags":[{"name":"testModule5AllSoapAndRestV2","description":"AllSoapAndRestInterface"}],"paths":{"/V1/testModule5":{"post":{"tags":["testModule5AllSoapAndRestV2"],"description":"Add new item.","operationId":"' . self::OPERATION_NAME . 'Post","parameters":[{"name":"operationNamePostBody","in":"body","schema":{"required":["item"],"properties":{"item":{"$ref":"#/definitions/test-module5-v2-entity-all-soap-and-rest"}},"type":"object"}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module5-v2-entity-all-soap-and-rest"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}}},"definitions":{"error-response":{"type":"object","properties":{"message":{"type":"string","description":"Error message"},"errors":{"$ref":"#/definitions/error-errors"},"code":{"type":"integer","description":"Error code"},"parameters":{"$ref":"#/definitions/error-parameters"},"trace":{"type":"string","description":"Stack trace"}},"required":["message"]},"error-errors":{"type":"array","description":"Errors list","items":{"$ref":"#/definitions/error-errors-item"}},"error-errors-item":{"type":"object","description":"Error details","properties":{"message":{"type":"string","description":"Error message"},"parameters":{"$ref":"#/definitions/error-parameters"}}},"error-parameters":{"type":"array","description":"Error parameters list","items":{"$ref":"#/definitions/error-parameters-item"}},"error-parameters-item":{"type":"object","description":"Error parameters item","properties":{"resources":{"type":"string","description":"ACL resource"},"fieldName":{"type":"string","description":"Missing or invalid field name"},"fieldValue":{"type":"string","description":"Incorrect field value"}}},"test-module5-v2-entity-all-soap-and-rest":{"type":"object","description":"Some Data Object","properties":{"price":{"type":"integer"}},"required":["price"]}}}' + '{"swagger":"2.0","info":{"version":"","title":""},"host":"magento.host","basePath":"/rest/default","schemes":["http://"],"tags":[{"name":"testModule5AllSoapAndRestV2","description":"AllSoapAndRestInterface"}],"paths":{"/V1/testModule5":{"post":{"tags":["testModule5AllSoapAndRestV2"],"description":"Add new item.","operationId":"operationNamePost","consumes":["application/json","application/xml"],"produces":["application/json","application/xml"],"parameters":[{"name":"operationNamePostBody","in":"body","schema":{"required":["item"],"properties":{"item":{"$ref":"#/definitions/test-module5-v2-entity-all-soap-and-rest"}},"type":"object","xml":{"name":"request"}}}],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module5-v2-entity-all-soap-and-rest"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}}},"definitions":{"error-response":{"type":"object","properties":{"message":{"type":"string","description":"Error message"},"errors":{"$ref":"#/definitions/error-errors"},"code":{"type":"integer","description":"Error code"},"parameters":{"$ref":"#/definitions/error-parameters"},"trace":{"type":"string","description":"Stack trace"}},"required":["message"]},"error-errors":{"type":"array","description":"Errors list","items":{"$ref":"#/definitions/error-errors-item"}},"error-errors-item":{"type":"object","description":"Error details","properties":{"message":{"type":"string","description":"Error message"},"parameters":{"$ref":"#/definitions/error-parameters"}}},"error-parameters":{"type":"array","description":"Error parameters list","items":{"$ref":"#/definitions/error-parameters-item"}},"error-parameters-item":{"type":"object","description":"Error parameters item","properties":{"resources":{"type":"string","description":"ACL resource"},"fieldName":{"type":"string","description":"Missing or invalid field name"},"fieldValue":{"type":"string","description":"Incorrect field value"}}},"test-module5-v2-entity-all-soap-and-rest":{"type":"object","description":"Some Data Object","properties":{"price":{"type":"integer"}},"required":["price"]}}}' // @codingStandardsIgnoreEnd ], [ @@ -271,7 +271,7 @@ public function generateDataProvider() ] ], // @codingStandardsIgnoreStart - '{"swagger":"2.0","info":{"version":"","title":""},"host":"magento.host","basePath":"/rest/default","schemes":["http://"],"tags":[{"name":"testModule5AllSoapAndRestV2","description":"AllSoapAndRestInterface"}],"paths":{"/V1/testModule5":{"get":{"tags":["testModule5AllSoapAndRestV2"],"description":"Retrieve existing item.","operationId":"' . self::OPERATION_NAME . 'Get","responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module5-v2-entity-all-soap-and-rest"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}}},"definitions":{"error-response":{"type":"object","properties":{"message":{"type":"string","description":"Error message"},"errors":{"$ref":"#/definitions/error-errors"},"code":{"type":"integer","description":"Error code"},"parameters":{"$ref":"#/definitions/error-parameters"},"trace":{"type":"string","description":"Stack trace"}},"required":["message"]},"error-errors":{"type":"array","description":"Errors list","items":{"$ref":"#/definitions/error-errors-item"}},"error-errors-item":{"type":"object","description":"Error details","properties":{"message":{"type":"string","description":"Error message"},"parameters":{"$ref":"#/definitions/error-parameters"}}},"error-parameters":{"type":"array","description":"Error parameters list","items":{"$ref":"#/definitions/error-parameters-item"}},"error-parameters-item":{"type":"object","description":"Error parameters item","properties":{"resources":{"type":"string","description":"ACL resource"},"fieldName":{"type":"string","description":"Missing or invalid field name"},"fieldValue":{"type":"string","description":"Incorrect field value"}}},"test-module5-v2-entity-all-soap-and-rest":{"type":"object","description":"Some Data Object","properties":{"price":{"type":"integer"}},"required":["price"]}}}' + '{"swagger":"2.0","info":{"version":"","title":""},"host":"magento.host","basePath":"/rest/default","schemes":["http://"],"tags":[{"name":"testModule5AllSoapAndRestV2","description":"AllSoapAndRestInterface"}],"paths":{"/V1/testModule5":{"get":{"tags":["testModule5AllSoapAndRestV2"],"description":"Retrieve existing item.","operationId":"operationNameGet","consumes":["application/json","application/xml"],"produces":["application/json","application/xml"],"responses":{"200":{"description":"200 Success.","schema":{"$ref":"#/definitions/test-module5-v2-entity-all-soap-and-rest"}},"401":{"description":"401 Unauthorized","schema":{"$ref":"#/definitions/error-response"}},"500":{"description":"Internal Server error","schema":{"$ref":"#/definitions/error-response"}},"default":{"description":"Unexpected error","schema":{"$ref":"#/definitions/error-response"}}}}}},"definitions":{"error-response":{"type":"object","properties":{"message":{"type":"string","description":"Error message"},"errors":{"$ref":"#/definitions/error-errors"},"code":{"type":"integer","description":"Error code"},"parameters":{"$ref":"#/definitions/error-parameters"},"trace":{"type":"string","description":"Stack trace"}},"required":["message"]},"error-errors":{"type":"array","description":"Errors list","items":{"$ref":"#/definitions/error-errors-item"}},"error-errors-item":{"type":"object","description":"Error details","properties":{"message":{"type":"string","description":"Error message"},"parameters":{"$ref":"#/definitions/error-parameters"}}},"error-parameters":{"type":"array","description":"Error parameters list","items":{"$ref":"#/definitions/error-parameters-item"}},"error-parameters-item":{"type":"object","description":"Error parameters item","properties":{"resources":{"type":"string","description":"ACL resource"},"fieldName":{"type":"string","description":"Missing or invalid field name"},"fieldValue":{"type":"string","description":"Incorrect field value"}}},"test-module5-v2-entity-all-soap-and-rest":{"type":"object","description":"Some Data Object","properties":{"price":{"type":"integer"}},"required":["price"]}}}' // @codingStandardsIgnoreEnd ], ]; From 64e32d77c32502ec4a02db1cb43d5f832789a1c7 Mon Sep 17 00:00:00 2001 From: Vishal Gelani Date: Thu, 30 May 2019 11:40:58 +0530 Subject: [PATCH 12/24] Update Generator.php --- app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php b/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php index 14b65bb640242..027a85cd08ce4 100644 --- a/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php +++ b/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php @@ -139,7 +139,7 @@ public function __construct( } /** - * {@inheritdoc} + * @inheritdoc */ protected function generateSchema($requestedServiceMetadata, $requestScheme, $requestHost, $endpointUrl) { @@ -199,7 +199,7 @@ protected function getGeneralInfo() } /** - * @return string[] + * @return array */ protected function getConsumableDatatypes() { @@ -210,7 +210,7 @@ protected function getConsumableDatatypes() } /** - * @return string[] + * @return array */ protected function getProducibleDatatypes() { @@ -631,7 +631,7 @@ protected function getDefinitionReference($typeName) /** * Get the CamelCased type name in 'hyphen-separated-lowercase-words' format * - * e.g. test-module5-v1-entity-all-soap-and-rest + * E.g. test-module5-v1-entity-all-soap-and-rest * * @param string $typeName * @return string From b6867e13c63481a7b7b8fb0a04b03e43d4213508 Mon Sep 17 00:00:00 2001 From: Vishal Gelani Date: Thu, 30 May 2019 12:26:09 +0530 Subject: [PATCH 13/24] Update Generator.php --- app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php b/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php index 027a85cd08ce4..095484f0edd73 100644 --- a/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php +++ b/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php @@ -199,6 +199,8 @@ protected function getGeneralInfo() } /** + * List out consumes data type + * * @return array */ protected function getConsumableDatatypes() @@ -210,6 +212,8 @@ protected function getConsumableDatatypes() } /** + * List out produces data type + * * @return array */ protected function getProducibleDatatypes() From e9a64758e2124e07347dfc6f1f06209eea11f48d Mon Sep 17 00:00:00 2001 From: Vishal Gelani Date: Thu, 30 May 2019 13:12:09 +0530 Subject: [PATCH 14/24] Update Generator.php --- app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php b/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php index 095484f0edd73..e17e2b72efa50 100644 --- a/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php +++ b/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php @@ -200,7 +200,7 @@ protected function getGeneralInfo() /** * List out consumes data type - * + * * @return array */ protected function getConsumableDatatypes() @@ -213,7 +213,7 @@ protected function getConsumableDatatypes() /** * List out produces data type - * + * * @return array */ protected function getProducibleDatatypes() From 19ea6d7b35f7a426367b234bdbfa1d7d93d467b1 Mon Sep 17 00:00:00 2001 From: Vishal Gelani Date: Fri, 31 May 2019 11:35:26 +0530 Subject: [PATCH 15/24] Update Generator.php --- app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php b/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php index e17e2b72efa50..c092f585c5203 100644 --- a/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php +++ b/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php @@ -44,7 +44,7 @@ class Generator extends AbstractSchemaGenerator /** * Wrapper node for XML requests */ - const XML_SCHEMA_PARAMWRAPPER = 'request'; + private const XML_SCHEMA_PARAMWRAPPER = 'request'; /** * Swagger factory instance. @@ -203,7 +203,7 @@ protected function getGeneralInfo() * * @return array */ - protected function getConsumableDatatypes() + private function getConsumableDatatypes() { return [ 'application/json', @@ -216,7 +216,7 @@ protected function getConsumableDatatypes() * * @return array */ - protected function getProducibleDatatypes() + private function getProducibleDatatypes() { return [ 'application/json', From 5f6e24fa20087d3d37063bfab77ffca42625c9c5 Mon Sep 17 00:00:00 2001 From: Graham Wharton Date: Fri, 31 May 2019 18:53:08 +0100 Subject: [PATCH 16/24] Admin Product Page now copies image files from database to local storage in database storage mode. --- .../Product/Helper/Form/Gallery/Content.php | 28 ++++++- .../Helper/Form/Gallery/ContentTest.php | 76 ++++++++++++++++++- 2 files changed, 99 insertions(+), 5 deletions(-) diff --git a/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Gallery/Content.php b/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Gallery/Content.php index 063503682f4db..f5d0ec7da617e 100644 --- a/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Gallery/Content.php +++ b/app/code/Magento/Catalog/Block/Adminhtml/Product/Helper/Form/Gallery/Content.php @@ -19,6 +19,7 @@ use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\Exception\FileSystemException; use Magento\Backend\Block\DataProviders\ImageUploadConfig as ImageUploadConfigDataProvider; +use Magento\MediaStorage\Helper\File\Storage\Database; /** * Block for gallery content. @@ -50,25 +51,34 @@ class Content extends \Magento\Backend\Block\Widget */ private $imageUploadConfigDataProvider; + /** + * @var Database + */ + private $fileStorageDatabase; + /** * @param \Magento\Backend\Block\Template\Context $context * @param \Magento\Framework\Json\EncoderInterface $jsonEncoder * @param \Magento\Catalog\Model\Product\Media\Config $mediaConfig * @param array $data * @param ImageUploadConfigDataProvider $imageUploadConfigDataProvider + * @param Database $fileStorageDatabase */ public function __construct( \Magento\Backend\Block\Template\Context $context, \Magento\Framework\Json\EncoderInterface $jsonEncoder, \Magento\Catalog\Model\Product\Media\Config $mediaConfig, array $data = [], - ImageUploadConfigDataProvider $imageUploadConfigDataProvider = null + ImageUploadConfigDataProvider $imageUploadConfigDataProvider = null, + Database $fileStorageDatabase = null ) { $this->_jsonEncoder = $jsonEncoder; $this->_mediaConfig = $mediaConfig; parent::__construct($context, $data); $this->imageUploadConfigDataProvider = $imageUploadConfigDataProvider ?: ObjectManager::getInstance()->get(ImageUploadConfigDataProvider::class); + $this->fileStorageDatabase = $fileStorageDatabase + ?: ObjectManager::getInstance()->get(Database::class); } /** @@ -164,6 +174,13 @@ public function getImagesJson() $images = $this->sortImagesByPosition($value['images']); foreach ($images as &$image) { $image['url'] = $this->_mediaConfig->getMediaUrl($image['file']); + if ($this->fileStorageDatabase->checkDbUsage() && + !$mediaDir->isFile($this->_mediaConfig->getMediaPath($image['file'])) + ) { + $this->fileStorageDatabase->saveFileToFilesystem( + $this->_mediaConfig->getMediaPath($image['file']) + ); + } try { $fileHandler = $mediaDir->stat($this->_mediaConfig->getMediaPath($image['file'])); $image['size'] = $fileHandler['size']; @@ -187,9 +204,12 @@ public function getImagesJson() private function sortImagesByPosition($images) { if (is_array($images)) { - usort($images, function ($imageA, $imageB) { - return ($imageA['position'] < $imageB['position']) ? -1 : 1; - }); + usort( + $images, + function ($imageA, $imageB) { + return ($imageA['position'] < $imageB['position']) ? -1 : 1; + } + ); } return $images; } diff --git a/app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Helper/Form/Gallery/ContentTest.php b/app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Helper/Form/Gallery/ContentTest.php index 249c32ff276c3..9a2199859a1df 100644 --- a/app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Helper/Form/Gallery/ContentTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Block/Adminhtml/Product/Helper/Form/Gallery/ContentTest.php @@ -9,6 +9,7 @@ use Magento\Catalog\Model\Entity\Attribute; use Magento\Catalog\Model\Product; use Magento\Framework\Phrase; +use Magento\MediaStorage\Helper\File\Storage\Database; /** * @SuppressWarnings(PHPMD.CouplingBetweenObjects) @@ -50,6 +51,11 @@ class ContentTest extends \PHPUnit\Framework\TestCase */ protected $imageHelper; + /** + * @var \Magento\MediaStorage\Helper\File\Storage\Database|\PHPUnit_Framework_MockObject_MockObject + */ + protected $databaseMock; + /** * @var \Magento\Framework\TestFramework\Unit\Helper\ObjectManager */ @@ -71,13 +77,18 @@ public function setUp() ->disableOriginalConstructor() ->getMock(); + $this->databaseMock = $this->getMockBuilder(Database::class) + ->disableOriginalConstructor() + ->getMock(); + $this->objectManager = new \Magento\Framework\TestFramework\Unit\Helper\ObjectManager($this); $this->content = $this->objectManager->getObject( \Magento\Catalog\Block\Adminhtml\Product\Helper\Form\Gallery\Content::class, [ 'mediaConfig' => $this->mediaConfigMock, 'jsonEncoder' => $this->jsonEncoderMock, - 'filesystem' => $this->fileSystemMock + 'filesystem' => $this->fileSystemMock, + 'fileStorageDatabase' => $this->databaseMock ] ); } @@ -143,6 +154,13 @@ public function testGetImagesJson() $this->readMock->expects($this->any())->method('stat')->willReturnMap($sizeMap); $this->jsonEncoderMock->expects($this->once())->method('encode')->willReturnCallback('json_encode'); + $this->readMock->expects($this->any()) + ->method('isFile') + ->will($this->returnValue(true)); + $this->databaseMock->expects($this->any()) + ->method('checkDbUsage') + ->will($this->returnValue(false)); + $this->assertSame(json_encode($imagesResult), $this->content->getImagesJson()); } @@ -210,6 +228,14 @@ public function testGetImagesJsonWithException() $this->fileSystemMock->expects($this->any())->method('getDirectoryRead')->willReturn($this->readMock); $this->mediaConfigMock->expects($this->any())->method('getMediaUrl'); $this->mediaConfigMock->expects($this->any())->method('getMediaPath'); + + $this->readMock->expects($this->any()) + ->method('isFile') + ->will($this->returnValue(true)); + $this->databaseMock->expects($this->any()) + ->method('checkDbUsage') + ->will($this->returnValue(false)); + $this->readMock->expects($this->any())->method('stat')->willReturnOnConsecutiveCalls( $this->throwException( new \Magento\Framework\Exception\FileSystemException(new Phrase('test')) @@ -365,4 +391,52 @@ private function getMediaAttribute(string $label, string $attributeCode) return $mediaAttribute; } + + /** + * Test GetImagesJson() calls MediaStorage functions to obtain image from DB prior to stat call + * + * @return void + */ + public function testGetImagesJsonMediaStorageMode() + { + $images = [ + 'images' => [ + [ + 'value_id' => '0', + 'file' => 'file_1.jpg', + 'media_type' => 'image', + 'position' => '0' + ] + ] + ]; + + $mediaPath = [ + ['file_1.jpg', 'catalog/product/image_1.jpg'] + ]; + + $this->content->setElement($this->galleryMock); + + $this->galleryMock->expects($this->once()) + ->method('getImages') + ->willReturn($images); + $this->fileSystemMock->expects($this->once()) + ->method('getDirectoryRead') + ->willReturn($this->readMock); + $this->mediaConfigMock->expects($this->any()) + ->method('getMediaPath') + ->willReturnMap($mediaPath); + + $this->readMock->expects($this->any()) + ->method('isFile') + ->will($this->returnValue(false)); + $this->databaseMock->expects($this->any()) + ->method('checkDbUsage') + ->will($this->returnValue(true)); + + $this->databaseMock->expects($this->once()) + ->method('saveFileToFilesystem') + ->with('catalog/product/image_1.jpg'); + + $this->content->getImagesJson(); + } } From 07a296a5abd558f543c6207c5746d03475ed9102 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Fri, 31 May 2019 23:38:51 +0200 Subject: [PATCH 17/24] Fix #19872 - unit tests for fileInfo with pub/ and root Magento install dir --- .../Test/Unit/Model/Category/FileInfoTest.php | 57 +++++++++++++++---- 1 file changed, 45 insertions(+), 12 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php index 8ca823127e66c..77efca7f80e11 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php @@ -67,7 +67,7 @@ protected function setUp() $this->baseDirectory->expects($this->any()) ->method('getAbsolutePath') ->with(null) - ->willReturn('/a/b/c'); + ->willReturn('/a/b/c/'); $this->model = new FileInfo( $this->filesystem, @@ -85,12 +85,12 @@ public function testGetMimeType() $this->mediaDirectory->expects($this->at(0)) ->method('getAbsolutePath') ->with(null) - ->willReturn('/a/b/c/pub/media'); + ->willReturn('/a/b/c/pub/media/'); $this->mediaDirectory->expects($this->at(1)) ->method('getAbsolutePath') ->with(null) - ->willReturn('/a/b/c/pub/media'); + ->willReturn('/a/b/c/pub/media/'); $this->mediaDirectory->expects($this->at(2)) ->method('getAbsolutePath') @@ -116,7 +116,7 @@ public function testGetStat() $this->mediaDirectory->expects($this->any()) ->method('getAbsolutePath') ->with(null) - ->willReturn('/a/b/c/pub/media'); + ->willReturn('/a/b/c/pub/media/'); $this->mediaDirectory->expects($this->once()) ->method('stat') @@ -130,22 +130,55 @@ public function testGetStat() $this->assertEquals(1, $result['size']); } - public function testIsExist() + /** + * @param $fileName + * @param $fileMediaPath + * @dataProvider isExistProvider + */ + public function testIsExist($fileName, $fileMediaPath) { - $mediaPath = '/catalog/category'; - - $fileName = '/filename.ext1'; - $this->mediaDirectory->expects($this->any()) ->method('getAbsolutePath') - ->with(null) - ->willReturn('/a/b/c/pub/media'); + ->willReturn('/a/b/c/pub/media/'); $this->mediaDirectory->expects($this->once()) ->method('isExist') - ->with($mediaPath . $fileName) + ->with($fileMediaPath) ->willReturn(true); $this->assertTrue($this->model->isExist($fileName)); } + + public function isExistProvider() + { + return [ + ['/filename.ext1', '/catalog/category/filename.ext1'], + ['/pub/media/filename.ext1', 'filename.ext1'], + ['/media/filename.ext1', 'filename.ext1'] + ]; + } + + /** + * @param $fileName + * @param $expected + * @dataProvider isBeginsWithMediaDirectoryPathProvider + */ + public function testIsBeginsWithMediaDirectoryPath($fileName, $expected) + { + $this->mediaDirectory->expects($this->any()) + ->method('getAbsolutePath') + ->willReturn('/a/b/c/pub/media/'); + + $this->assertEquals($expected, $this->model->isBeginsWithMediaDirectoryPath($fileName)); + } + + public function isBeginsWithMediaDirectoryPathProvider() + { + return [ + ['/pub/media/test/filename.ext1', true], + ['/media/test/filename.ext1', true], + ['/test/filename.ext1', false], + ['test2/filename.ext1', false] + ]; + } } From 5997307445298146380df65fa312dc48353abcd2 Mon Sep 17 00:00:00 2001 From: Serhii Dzhepa Date: Tue, 4 Jun 2019 09:57:22 -0500 Subject: [PATCH 18/24] fixed typos --- app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php b/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php index c092f585c5203..847def6e8922c 100644 --- a/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php +++ b/app/code/Magento/Webapi/Model/Rest/Swagger/Generator.php @@ -877,7 +877,7 @@ private function generateBodySchema($parameterName, $parameterInfo, $description $bodySchema['type'] = 'object'; /* - * Make shure we have a proper XML wrapper for request parameters for the XML fromat. + * Make sure we have a proper XML wrapper for request parameters for the XML format. */ if (!isset($bodySchema['xml']) || !is_array($bodySchema['xml'])) { $bodySchema['xml'] = []; From a142ef2f71eaa78e18829e9b6990bd523254e158 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bart=C5=82omiej=20Szubert?= Date: Tue, 4 Jun 2019 23:40:18 +0200 Subject: [PATCH 19/24] Fix #19872 - replace hardcoded pub path with getRelativePath call --- .../Catalog/Model/Category/FileInfo.php | 25 +++++++- .../Test/Unit/Model/Category/FileInfoTest.php | 63 +++++++++++-------- 2 files changed, 61 insertions(+), 27 deletions(-) diff --git a/app/code/Magento/Catalog/Model/Category/FileInfo.php b/app/code/Magento/Catalog/Model/Category/FileInfo.php index a474eb764d2c0..cd3592ef40a0f 100644 --- a/app/code/Magento/Catalog/Model/Category/FileInfo.php +++ b/app/code/Magento/Catalog/Model/Category/FileInfo.php @@ -43,6 +43,11 @@ class FileInfo */ private $baseDirectory; + /** + * @var ReadInterface + */ + private $pubDirectory; + /** * @param Filesystem $filesystem * @param Mime $mime @@ -82,6 +87,20 @@ private function getBaseDirectory() return $this->baseDirectory; } + /** + * Get Pub Directory read instance + * + * @return ReadInterface + */ + private function getPubDirectory() + { + if (!isset($this->pubDirectory)) { + $this->pubDirectory = $this->filesystem->getDirectoryRead(DirectoryList::PUB); + } + + return $this->pubDirectory; + } + /** * Retrieve MIME type of requested file * @@ -174,11 +193,13 @@ public function isBeginsWithMediaDirectoryPath($fileName) */ private function getMediaDirectoryPathRelativeToBaseDirectoryPath(string $filePath = '') { - $baseDirectoryPath = $this->getBaseDirectory()->getAbsolutePath(); + $baseDirectory = $this->getBaseDirectory(); + $baseDirectoryPath = $baseDirectory->getAbsolutePath(); $mediaDirectoryPath = $this->getMediaDirectory()->getAbsolutePath(); + $pubDirectoryPath = $this->getPubDirectory()->getAbsolutePath(); $mediaDirectoryRelativeSubpath = substr($mediaDirectoryPath, strlen($baseDirectoryPath)); - $pubDirectory = 'pub' . DIRECTORY_SEPARATOR; + $pubDirectory = $baseDirectory->getRelativePath($pubDirectoryPath); if (strpos($mediaDirectoryRelativeSubpath, $pubDirectory) === 0 && strpos($filePath, $pubDirectory) !== 0) { $mediaDirectoryRelativeSubpath = substr($mediaDirectoryRelativeSubpath, strlen($pubDirectory)); diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php index 77efca7f80e11..f9c77cc624e11 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php @@ -11,29 +11,36 @@ use Magento\Framework\Filesystem; use Magento\Framework\Filesystem\Directory\WriteInterface; use Magento\Framework\Filesystem\Directory\ReadInterface; +use PHPUnit\Framework\MockObject\MockObject; +use PHPUnit\Framework\TestCase; -class FileInfoTest extends \PHPUnit\Framework\TestCase +class FileInfoTest extends TestCase { /** - * @var Filesystem|\PHPUnit_Framework_MockObject_MockObject + * @var Filesystem|MockObject */ private $filesystem; /** - * @var Mime|\PHPUnit_Framework_MockObject_MockObject + * @var Mime|MockObject */ private $mime; /** - * @var WriteInterface|\PHPUnit_Framework_MockObject_MockObject + * @var WriteInterface|MockObject */ private $mediaDirectory; /** - * @var ReadInterface|\PHPUnit_Framework_MockObject_MockObject + * @var ReadInterface|MockObject */ private $baseDirectory; + /** + * @var ReadInterface|MockObject + */ + private $pubDirectory; + /** * @var FileInfo */ @@ -44,31 +51,42 @@ protected function setUp() $this->mediaDirectory = $this->getMockBuilder(WriteInterface::class) ->getMockForAbstractClass(); - $this->baseDirectory = $this->getMockBuilder(ReadInterface::class) + $this->baseDirectory = $baseDirectory = $this->getMockBuilder(ReadInterface::class) + ->getMockForAbstractClass(); + + $this->pubDirectory = $pubDirectory = $this->getMockBuilder(ReadInterface::class) ->getMockForAbstractClass(); $this->filesystem = $this->getMockBuilder(Filesystem::class) ->disableOriginalConstructor() ->getMock(); - $this->filesystem->expects($this->any()) - ->method('getDirectoryWrite') + + $this->filesystem->method('getDirectoryWrite') ->with(DirectoryList::MEDIA) ->willReturn($this->mediaDirectory); - $this->filesystem->expects($this->any()) - ->method('getDirectoryRead') - ->with(DirectoryList::ROOT) - ->willReturn($this->baseDirectory); + $this->filesystem->method('getDirectoryRead') + ->willReturnCallback(function ($arg) use ($baseDirectory, $pubDirectory) { + if ($arg === DirectoryList::PUB) { + return $pubDirectory; + } + return $baseDirectory; + }); $this->mime = $this->getMockBuilder(Mime::class) ->disableOriginalConstructor() ->getMock(); - $this->baseDirectory->expects($this->any()) - ->method('getAbsolutePath') - ->with(null) + $this->baseDirectory->method('getAbsolutePath') ->willReturn('/a/b/c/'); + $this->baseDirectory->method('getRelativePath') + ->with('/a/b/c/pub/') + ->willReturn('pub/'); + + $this->pubDirectory->method('getAbsolutePath') + ->willReturn('/a/b/c/pub/'); + $this->model = new FileInfo( $this->filesystem, $this->mime @@ -113,13 +131,11 @@ public function testGetStat() $expected = ['size' => 1]; - $this->mediaDirectory->expects($this->any()) - ->method('getAbsolutePath') + $this->mediaDirectory->method('getAbsolutePath') ->with(null) ->willReturn('/a/b/c/pub/media/'); - $this->mediaDirectory->expects($this->once()) - ->method('stat') + $this->mediaDirectory->method('stat') ->with($mediaPath . $fileName) ->willReturn($expected); @@ -137,12 +153,10 @@ public function testGetStat() */ public function testIsExist($fileName, $fileMediaPath) { - $this->mediaDirectory->expects($this->any()) - ->method('getAbsolutePath') + $this->mediaDirectory->method('getAbsolutePath') ->willReturn('/a/b/c/pub/media/'); - $this->mediaDirectory->expects($this->once()) - ->method('isExist') + $this->mediaDirectory->method('isExist') ->with($fileMediaPath) ->willReturn(true); @@ -165,8 +179,7 @@ public function isExistProvider() */ public function testIsBeginsWithMediaDirectoryPath($fileName, $expected) { - $this->mediaDirectory->expects($this->any()) - ->method('getAbsolutePath') + $this->mediaDirectory->method('getAbsolutePath') ->willReturn('/a/b/c/pub/media/'); $this->assertEquals($expected, $this->model->isBeginsWithMediaDirectoryPath($fileName)); From 265e0d4e7ca2bc051652241020a1609e48523f72 Mon Sep 17 00:00:00 2001 From: Wirson Date: Tue, 4 Jun 2019 12:51:45 +0200 Subject: [PATCH 20/24] #23053 : sendfriend verifies product visibility instead of status --- .../Magento/SendFriend/Controller/Product.php | 2 +- .../SendFriend/Controller/SendmailTest.php | 26 +++++++++++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/app/code/Magento/SendFriend/Controller/Product.php b/app/code/Magento/SendFriend/Controller/Product.php index 732bcef8b957a..388fcd23c2e0a 100644 --- a/app/code/Magento/SendFriend/Controller/Product.php +++ b/app/code/Magento/SendFriend/Controller/Product.php @@ -102,7 +102,7 @@ protected function _initProduct() } try { $product = $this->productRepository->getById($productId); - if (!$product->isVisibleInCatalog()) { + if (!$product->isVisibleInSiteVisibility() || !$product->isVisibleInCatalog()) { return false; } } catch (NoSuchEntityException $noEntityException) { diff --git a/dev/tests/integration/testsuite/Magento/SendFriend/Controller/SendmailTest.php b/dev/tests/integration/testsuite/Magento/SendFriend/Controller/SendmailTest.php index a075398e9cdb7..f5851a55d760a 100644 --- a/dev/tests/integration/testsuite/Magento/SendFriend/Controller/SendmailTest.php +++ b/dev/tests/integration/testsuite/Magento/SendFriend/Controller/SendmailTest.php @@ -85,6 +85,24 @@ public function testSendActionAsGuestWithInvalidData() ); } + /** + * Share the product invisible in catalog to friend as guest customer + * + * @magentoDbIsolation enabled + * @magentoAppIsolation enabled + * @magentoConfigFixture default_store sendfriend/email/enabled 1 + * @magentoConfigFixture default_store sendfriend/email/allow_guest 1 + * @magentoDataFixture Magento/Catalog/_files/simple_products_not_visible_individually.php + */ + public function testSendInvisibleProduct() + { + $product = $this->getInvisibleProduct(); + $this->prepareRequestData(); + + $this->dispatch('sendfriend/product/sendmail/id/' . $product->getId()); + $this->assert404NotFound(); + } + /** * @return ProductInterface */ @@ -93,6 +111,14 @@ private function getProduct() return $this->_objectManager->get(ProductRepositoryInterface::class)->get('custom-design-simple-product'); } + /** + * @return ProductInterface + */ + private function getInvisibleProduct() + { + return $this->_objectManager->get(ProductRepositoryInterface::class)->get('simple_not_visible_1'); + } + /** * Login the user * From e2f577dbd5c2235bd2f8bf2b17df34b61bb9af50 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Wed, 5 Jun 2019 13:14:52 +0300 Subject: [PATCH 21/24] magento/magento2#20848: Static test fix. --- .../Magento/Newsletter/Block/Adminhtml/Problem.php | 2 +- .../Controller/Adminhtml/Subscriber/MassDelete.php | 12 ++++++++---- .../Magento/Newsletter/Controller/Manage/Save.php | 8 ++++---- .../Newsletter/Controller/Subscriber/Confirm.php | 2 +- app/code/Magento/Newsletter/Model/Subscriber.php | 10 +++++++--- 5 files changed, 21 insertions(+), 13 deletions(-) diff --git a/app/code/Magento/Newsletter/Block/Adminhtml/Problem.php b/app/code/Magento/Newsletter/Block/Adminhtml/Problem.php index 6534f39451275..0c66e46a850ee 100644 --- a/app/code/Magento/Newsletter/Block/Adminhtml/Problem.php +++ b/app/code/Magento/Newsletter/Block/Adminhtml/Problem.php @@ -41,7 +41,7 @@ public function __construct( } /** - * @return void + * @inheritDoc * @SuppressWarnings(PHPMD.UnusedLocalVariable) */ protected function _construct() diff --git a/app/code/Magento/Newsletter/Controller/Adminhtml/Subscriber/MassDelete.php b/app/code/Magento/Newsletter/Controller/Adminhtml/Subscriber/MassDelete.php index 0afc98a5cc12e..cdef44b2da757 100644 --- a/app/code/Magento/Newsletter/Controller/Adminhtml/Subscriber/MassDelete.php +++ b/app/code/Magento/Newsletter/Controller/Adminhtml/Subscriber/MassDelete.php @@ -6,13 +6,17 @@ */ namespace Magento\Newsletter\Controller\Adminhtml\Subscriber; -use Magento\Newsletter\Controller\Adminhtml\Subscriber; use Magento\Backend\App\Action\Context; +use Magento\Framework\App\Action\HttpPostActionInterface; +use Magento\Framework\App\ObjectManager; use Magento\Framework\App\Response\Http\FileFactory; +use Magento\Newsletter\Controller\Adminhtml\Subscriber; use Magento\Newsletter\Model\SubscriberFactory; -use Magento\Framework\App\ObjectManager; -class MassDelete extends Subscriber +/** + * Subscriber mass delete controller. + */ +class MassDelete extends Subscriber implements HttpPostActionInterface { /** * @var SubscriberFactory @@ -32,7 +36,7 @@ public function __construct( $this->subscriberFactory = $subscriberFactory ?: ObjectManager::getInstance()->get(SubscriberFactory::class); parent::__construct($context, $fileFactory); } - + /** * Delete one or more subscribers action * diff --git a/app/code/Magento/Newsletter/Controller/Manage/Save.php b/app/code/Magento/Newsletter/Controller/Manage/Save.php index 400922f149f8e..d7d511e2d1906 100644 --- a/app/code/Magento/Newsletter/Controller/Manage/Save.php +++ b/app/code/Magento/Newsletter/Controller/Manage/Save.php @@ -8,7 +8,7 @@ namespace Magento\Newsletter\Controller\Manage; use Magento\Customer\Api\CustomerRepositoryInterface as CustomerRepository; -use Magento\Customer\Model\Customer; +use Magento\Customer\Api\Data\CustomerInterface; use Magento\Framework\App\Action\HttpGetActionInterface; use Magento\Framework\App\Action\HttpPostActionInterface; use Magento\Newsletter\Model\Subscriber; @@ -68,7 +68,7 @@ public function __construct( * * @return \Magento\Framework\App\ResponseInterface */ - public function execute(): \Magento\Framework\App\ResponseInterface + public function execute() { if (!$this->formKeyValidator->validate($this->getRequest())) { return $this->_redirect('customer/account/'); @@ -117,10 +117,10 @@ public function execute(): \Magento\Framework\App\ResponseInterface /** * Set ignore_validation_flag to skip unnecessary address and customer validation * - * @param Customer $customer + * @param CustomerInterface $customer * @return void */ - private function setIgnoreValidationFlag(Customer $customer): void + private function setIgnoreValidationFlag(CustomerInterface $customer): void { $customer->setData('ignore_validation_flag', true); } diff --git a/app/code/Magento/Newsletter/Controller/Subscriber/Confirm.php b/app/code/Magento/Newsletter/Controller/Subscriber/Confirm.php index 658290f756a00..6f566761b2f87 100644 --- a/app/code/Magento/Newsletter/Controller/Subscriber/Confirm.php +++ b/app/code/Magento/Newsletter/Controller/Subscriber/Confirm.php @@ -20,7 +20,7 @@ class Confirm extends \Magento\Newsletter\Controller\Subscriber implements HttpG * * @return \Magento\Framework\Controller\Result\Redirect */ - public function execute(): \Magento\Framework\Controller\Result\Redirect + public function execute() { $id = (int)$this->getRequest()->getParam('id'); $code = (string)$this->getRequest()->getParam('code'); diff --git a/app/code/Magento/Newsletter/Model/Subscriber.php b/app/code/Magento/Newsletter/Model/Subscriber.php index eb87f303b84d2..117783495406a 100644 --- a/app/code/Magento/Newsletter/Model/Subscriber.php +++ b/app/code/Magento/Newsletter/Model/Subscriber.php @@ -7,11 +7,11 @@ use Magento\Customer\Api\AccountManagementInterface; use Magento\Customer\Api\CustomerRepositoryInterface; -use Magento\Framework\Exception\MailException; -use Magento\Framework\Exception\NoSuchEntityException; use Magento\Customer\Api\Data\CustomerInterfaceFactory; use Magento\Framework\Api\DataObjectHelper; use Magento\Framework\App\ObjectManager; +use Magento\Framework\Exception\MailException; +use Magento\Framework\Exception\NoSuchEntityException; /** * Subscriber model @@ -31,6 +31,7 @@ * @method int getSubscriberId() * @method Subscriber setSubscriberId(int $value) * + * @SuppressWarnings(PHPMD.CookieAndSessionMisuse) * @SuppressWarnings(PHPMD.CouplingBetweenObjects) * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @@ -402,6 +403,7 @@ public function loadByCustomerId($customerId) $this->setSubscriberConfirmCode($this->randomSequence()); $this->save(); } + // phpcs:ignore Magento2.CodeAnalysis.EmptyBlock } catch (NoSuchEntityException $e) { } return $this; @@ -493,7 +495,9 @@ public function subscribe($email) $this->sendConfirmationSuccessEmail(); } return $this->getStatus(); + // phpcs:ignore Magento2.Exceptions.ThrowCatch } catch (\Exception $e) { + // phpcs:ignore Magento2.Exceptions.DirectThrow throw new \Exception($e->getMessage()); } } @@ -559,7 +563,7 @@ public function updateSubscription($customerId) * * @param int $customerId * @param bool $subscribe indicates whether the customer should be subscribed or unsubscribed - * @return $this + * @return $this * * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) From 40cc415a21ddc38dc5f410698c830c2918628891 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Wed, 5 Jun 2019 15:38:41 +0300 Subject: [PATCH 22/24] magento/magento2#23007: Code demarcation standard fix. --- app/code/Magento/Ui/view/base/web/js/form/form.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/code/Magento/Ui/view/base/web/js/form/form.js b/app/code/Magento/Ui/view/base/web/js/form/form.js index bf27cbbb7660f..3692108675bc7 100644 --- a/app/code/Magento/Ui/view/base/web/js/form/form.js +++ b/app/code/Magento/Ui/view/base/web/js/form/form.js @@ -339,7 +339,7 @@ define([ */ reset: function () { this.source.trigger('data.reset'); - $('._has-datepicker').val(''); + $('[data-bind*=datepicker]').val(''); }, /** From d06fb10173f5080090c9983ed6b9f3f106788313 Mon Sep 17 00:00:00 2001 From: Pavel Bystritsky Date: Thu, 6 Jun 2019 14:38:53 +0300 Subject: [PATCH 23/24] magento/magento2#21131: Static test fix. --- .../Test/Unit/Model/Category/FileInfoTest.php | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php b/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php index f9c77cc624e11..6c6a69ec39c85 100644 --- a/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php +++ b/app/code/Magento/Catalog/Test/Unit/Model/Category/FileInfoTest.php @@ -9,11 +9,14 @@ use Magento\Framework\App\Filesystem\DirectoryList; use Magento\Framework\File\Mime; use Magento\Framework\Filesystem; -use Magento\Framework\Filesystem\Directory\WriteInterface; use Magento\Framework\Filesystem\Directory\ReadInterface; +use Magento\Framework\Filesystem\Directory\WriteInterface; use PHPUnit\Framework\MockObject\MockObject; use PHPUnit\Framework\TestCase; +/** + * Test for Magento\Catalog\Model\Category\FileInfo class. + */ class FileInfoTest extends TestCase { /** @@ -66,12 +69,14 @@ protected function setUp() ->willReturn($this->mediaDirectory); $this->filesystem->method('getDirectoryRead') - ->willReturnCallback(function ($arg) use ($baseDirectory, $pubDirectory) { - if ($arg === DirectoryList::PUB) { - return $pubDirectory; + ->willReturnCallback( + function ($arg) use ($baseDirectory, $pubDirectory) { + if ($arg === DirectoryList::PUB) { + return $pubDirectory; + } + return $baseDirectory; } - return $baseDirectory; - }); + ); $this->mime = $this->getMockBuilder(Mime::class) ->disableOriginalConstructor() From 74373a005e6c018b691fcbf3191862d9960bc624 Mon Sep 17 00:00:00 2001 From: Stanislav Idolov Date: Thu, 6 Jun 2019 22:30:47 -0500 Subject: [PATCH 24/24] Fixed code style issue --- app/code/Magento/SendFriend/Controller/Product.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/code/Magento/SendFriend/Controller/Product.php b/app/code/Magento/SendFriend/Controller/Product.php index 388fcd23c2e0a..a184d7d8bff62 100644 --- a/app/code/Magento/SendFriend/Controller/Product.php +++ b/app/code/Magento/SendFriend/Controller/Product.php @@ -61,6 +61,7 @@ public function __construct( /** * Check if module is enabled + * * If allow only for customer - redirect to login page * * @param RequestInterface $request