diff --git a/app/code/Magento/Catalog/i18n/en_US.csv b/app/code/Magento/Catalog/i18n/en_US.csv index de9f5e1975870..a316bac5d3584 100644 --- a/app/code/Magento/Catalog/i18n/en_US.csv +++ b/app/code/Magento/Catalog/i18n/en_US.csv @@ -615,7 +615,7 @@ Submit,Submit "We don't recognize or support this file extension type.","We don't recognize or support this file extension type." "Configure Product","Configure Product" OK,OK -"This value does not follow the specified format (for example, 200X300).","This value does not follow the specified format (for example, 200X300)." +"This value does not follow the specified format (for example, 200x300).","This value does not follow the specified format (for example, 200x300)." "Select type of option.","Select type of option." "Please add rows to option.","Please add rows to option." "Please select items.","Please select items." diff --git a/app/code/Magento/Catalog/view/adminhtml/web/component/image-size-field.js b/app/code/Magento/Catalog/view/adminhtml/web/component/image-size-field.js index 3ebd4bdf9c804..11a1a65cbab47 100644 --- a/app/code/Magento/Catalog/view/adminhtml/web/component/image-size-field.js +++ b/app/code/Magento/Catalog/view/adminhtml/web/component/image-size-field.js @@ -26,7 +26,7 @@ define([ return !!(m && m[1] > 0 && m[2] > 0); }, - $.mage.__('This value does not follow the specified format (for example, 200X300).') + $.mage.__('This value does not follow the specified format (for example, 200x300).') ); return Abstract.extend({ diff --git a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php index e6345af40f37a..fbaa4e60c29cc 100644 --- a/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php +++ b/app/code/Magento/ConfigurableProduct/Model/Product/Type/Configurable.php @@ -3,6 +3,7 @@ * Copyright © Magento, Inc. All rights reserved. * See COPYING.txt for license details. */ + namespace Magento\ConfigurableProduct\Model\Product\Type; use Magento\Catalog\Api\Data\ProductAttributeInterface; @@ -682,7 +683,7 @@ private function saveConfigurableOptions(ProductInterface $product) ->setProductId($product->getData($metadata->getLinkField())) ->save(); } - /** @var $configurableAttributesCollection \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\Collection */ + /** @var $configurableAttributesCollection \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\Collection */ $configurableAttributesCollection = $this->_attributeCollectionFactory->create(); $configurableAttributesCollection->setProductFilter($product); $configurableAttributesCollection->addFieldToFilter( @@ -1397,7 +1398,16 @@ private function getConfiguredUsedProductCollection(\Magento\Catalog\Model\Produ ->addFilterByRequiredOptions() ->setStoreId($product->getStoreId()); - $requiredAttributes = ['name', 'price', 'weight', 'image', 'thumbnail', 'status', 'media_gallery']; + $requiredAttributes = [ + 'name', + 'price', + 'weight', + 'image', + 'thumbnail', + 'status', + 'visibility', + 'media_gallery' + ]; foreach ($requiredAttributes as $attributeCode) { $collection->addAttributeToSelect($attributeCode); } diff --git a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/ConfigurableTest.php b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/ConfigurableTest.php index 6ffdede34d04c..ea136dd037baf 100644 --- a/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/ConfigurableTest.php +++ b/app/code/Magento/ConfigurableProduct/Test/Unit/Model/Product/Type/ConfigurableTest.php @@ -197,11 +197,6 @@ protected function setUp() ->disableOriginalConstructor() ->getMock(); - $this->productFactory = $this->getMockBuilder(\Magento\Catalog\Api\Data\ProductInterfaceFactory::class) - ->setMethods(['create']) - ->disableOriginalConstructor() - ->getMock(); - $this->salableProcessor = $this->createMock(SalableProcessor::class); $this->model = $this->objectHelper->getObject( diff --git a/app/code/Magento/Customer/Model/AccountManagement.php b/app/code/Magento/Customer/Model/AccountManagement.php index ba646549f6919..894dd5931a63c 100644 --- a/app/code/Magento/Customer/Model/AccountManagement.php +++ b/app/code/Magento/Customer/Model/AccountManagement.php @@ -817,6 +817,8 @@ protected function sendEmailConfirmation(CustomerInterface $customer, $redirectU } catch (MailException $e) { // If we are not able to send a new account email, this should be ignored $this->logger->critical($e); + } catch (\UnexpectedValueException $e) { + $this->logger->error($e); } } diff --git a/app/code/Magento/Customer/Model/AttributeChecker.php b/app/code/Magento/Customer/Model/AttributeChecker.php index 6cc27697ccff7..dcdd47691386e 100644 --- a/app/code/Magento/Customer/Model/AttributeChecker.php +++ b/app/code/Magento/Customer/Model/AttributeChecker.php @@ -8,7 +8,6 @@ use Magento\Customer\Api\AddressMetadataInterface; use Magento\Customer\Api\AddressMetadataManagementInterface; use Magento\Customer\Model\Metadata\AttributeResolver; -use Magento\Framework\App\Helper\Context; /** * Customer attribute checker. diff --git a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php index 2a6b9fe6fd4ea..676e9c98a2008 100644 --- a/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php +++ b/app/code/Magento/Customer/Test/Unit/Model/AccountManagementTest.php @@ -1721,4 +1721,102 @@ private function prepareDateTimeFactory() return $dateTime; } + + public function testCreateAccountUnexpectedValueException() + { + $websiteId = 1; + $storeId = null; + $defaultStoreId = 1; + $customerId = 1; + $customerEmail = 'email@email.com'; + $newLinkToken = '2jh43j5h2345jh23lh452h345hfuzasd96ofu'; + $exception = new \UnexpectedValueException('Template file was not found'); + + $datetime = $this->prepareDateTimeFactory(); + + $address = $this->createMock(\Magento\Customer\Api\Data\AddressInterface::class); + $address->expects($this->once()) + ->method('setCustomerId') + ->with($customerId); + $store = $this->createMock(\Magento\Store\Model\Store::class); + $store->expects($this->once()) + ->method('getId') + ->willReturn($defaultStoreId); + $website = $this->createMock(\Magento\Store\Model\Website::class); + $website->expects($this->atLeastOnce()) + ->method('getStoreIds') + ->willReturn([1, 2, 3]); + $website->expects($this->once()) + ->method('getDefaultStore') + ->willReturn($store); + $customer = $this->createMock(\Magento\Customer\Api\Data\CustomerInterface::class); + $customer->expects($this->atLeastOnce()) + ->method('getId') + ->willReturn($customerId); + $customer->expects($this->atLeastOnce()) + ->method('getEmail') + ->willReturn($customerEmail); + $customer->expects($this->atLeastOnce()) + ->method('getWebsiteId') + ->willReturn($websiteId); + $customer->expects($this->atLeastOnce()) + ->method('getStoreId') + ->willReturn($storeId); + $customer->expects($this->once()) + ->method('setStoreId') + ->with($defaultStoreId); + $customer->expects($this->once()) + ->method('getAddresses') + ->willReturn([$address]); + $customer->expects($this->once()) + ->method('setAddresses') + ->with(null); + $this->customerRepository->expects($this->once()) + ->method('get') + ->with($customerEmail) + ->willReturn($customer); + $this->share->expects($this->once()) + ->method('isWebsiteScope') + ->willReturn(true); + $this->storeManager->expects($this->atLeastOnce()) + ->method('getWebsite') + ->with($websiteId) + ->willReturn($website); + $this->customerRepository->expects($this->atLeastOnce()) + ->method('save') + ->willReturn($customer); + $this->addressRepository->expects($this->atLeastOnce()) + ->method('save') + ->with($address); + $this->customerRepository->expects($this->once()) + ->method('getById') + ->with($customerId) + ->willReturn($customer); + $this->random->expects($this->once()) + ->method('getUniqueHash') + ->willReturn($newLinkToken); + $customerSecure = $this->createPartialMock( + \Magento\Customer\Model\Data\CustomerSecure::class, + ['setRpToken', 'setRpTokenCreatedAt', 'getPasswordHash'] + ); + $customerSecure->expects($this->any()) + ->method('setRpToken') + ->with($newLinkToken); + $customerSecure->expects($this->any()) + ->method('setRpTokenCreatedAt') + ->with($datetime) + ->willReturnSelf(); + $customerSecure->expects($this->any()) + ->method('getPasswordHash') + ->willReturn(null); + $this->customerRegistry->expects($this->atLeastOnce()) + ->method('retrieveSecureData') + ->willReturn($customerSecure); + $this->emailNotificationMock->expects($this->once()) + ->method('newAccount') + ->willThrowException($exception); + $this->logger->expects($this->once())->method('error')->with($exception); + + $this->accountManagement->createAccount($customer); + } } diff --git a/app/code/Magento/Email/Model/Template/Config.php b/app/code/Magento/Email/Model/Template/Config.php index bdd9054e7969b..8a7e7172a8e6e 100644 --- a/app/code/Magento/Email/Model/Template/Config.php +++ b/app/code/Magento/Email/Model/Template/Config.php @@ -205,8 +205,9 @@ public function getTemplateFilename($templateId, $designParams = []) $designParams['module'] = $module; $file = $this->_getInfo($templateId, 'file'); + $filename = $this->getFilename($file, $designParams, $module); - return $this->viewFileSystem->getEmailTemplateFileName($file, $designParams, $module); + return $filename; } /** @@ -230,4 +231,24 @@ protected function _getInfo($templateId, $fieldName) } return $data[$templateId][$fieldName]; } + + /** + * @param string $file + * @param array $designParams + * @param string $module + * + * @return string + * + * @throws \UnexpectedValueException + */ + private function getFilename($file, array $designParams, $module) + { + $filename = $this->viewFileSystem->getEmailTemplateFileName($file, $designParams, $module); + + if ($filename === false) { + throw new \UnexpectedValueException("Template file '{$file}' is not found."); + } + + return $filename; + } } diff --git a/app/code/Magento/Email/Test/Unit/Model/Template/ConfigTest.php b/app/code/Magento/Email/Test/Unit/Model/Template/ConfigTest.php index 47c3ac1e7e450..6a565ca08eb9b 100644 --- a/app/code/Magento/Email/Test/Unit/Model/Template/ConfigTest.php +++ b/app/code/Magento/Email/Test/Unit/Model/Template/ConfigTest.php @@ -272,6 +272,19 @@ public function testGetTemplateFilenameWithNoParams() $this->assertEquals('_files/Fixture/ModuleOne/view/frontend/email/one.html', $actualResult); } + /** + * @expectedException \UnexpectedValueException + * @expectedExceptionMessage Template file 'one.html' is not found + */ + public function testGetTemplateFilenameWrongFileName() + { + $this->viewFileSystem->expects($this->once())->method('getEmailTemplateFileName') + ->with('one.html', $this->designParams, 'Fixture_ModuleOne') + ->willReturn(false); + + $this->model->getTemplateFilename('template_one', $this->designParams); + } + /** * @param string $getterMethod * @param $argument diff --git a/app/code/Magento/NewRelicReporting/Console/Command/DeployMarker.php b/app/code/Magento/NewRelicReporting/Console/Command/DeployMarker.php new file mode 100644 index 0000000000000..795028cffd18d --- /dev/null +++ b/app/code/Magento/NewRelicReporting/Console/Command/DeployMarker.php @@ -0,0 +1,81 @@ +deploymentsFactory = $deploymentsFactory; + $this->serviceShellUser = $serviceShellUser; + parent::__construct($name); + } + + /** + * {@inheritdoc} + */ + protected function configure() + { + $this->setName("newrelic:create:deploy-marker"); + $this->setDescription("Check the deploy queue for entries and create an appropriate deploy marker.") + ->addArgument( + 'message', + InputArgument::REQUIRED, + 'Deploy Message?' + ) + ->addArgument( + 'changelog', + InputArgument::REQUIRED, + 'Change Log?' + ) + ->addArgument( + 'user', + InputArgument::OPTIONAL, + 'Deployment User' + ); + parent::configure(); + } + + /** + * {@inheritdoc} + */ + protected function execute(InputInterface $input, OutputInterface $output) + { + $this->deploymentsFactory->create()->setDeployment( + $input->getArgument('message'), + $input->getArgument('changelog'), + $this->serviceShellUser->get($input->getArgument('user')) + ); + $output->writeln('NewRelic deployment information sent'); + } +} diff --git a/app/code/Magento/NewRelicReporting/Model/Cron/ReportNewRelicCron.php b/app/code/Magento/NewRelicReporting/Model/Cron/ReportNewRelicCron.php index a4a7d30b44f5b..6b2bd50dc456b 100644 --- a/app/code/Magento/NewRelicReporting/Model/Cron/ReportNewRelicCron.php +++ b/app/code/Magento/NewRelicReporting/Model/Cron/ReportNewRelicCron.php @@ -175,7 +175,6 @@ protected function reportCounts() public function report() { if ($this->config->isNewRelicEnabled()) { - $this->reportModules(); $this->reportCounts(); } diff --git a/app/code/Magento/NewRelicReporting/Model/ServiceShellUser.php b/app/code/Magento/NewRelicReporting/Model/ServiceShellUser.php new file mode 100644 index 0000000000000..c038be4fb2a76 --- /dev/null +++ b/app/code/Magento/NewRelicReporting/Model/ServiceShellUser.php @@ -0,0 +1,34 @@ + [ - ['name' => 'name', 'setup_version' => '2.0.0', 'type' => 'enabled'], - ['name' => 'name', 'setup_version' => '2.0.0', 'type' => 'disabled'], - ['name' => 'name', 'setup_version' => '2.0.0', 'type' => 'installed'], - ['name' => 'name', 'setup_version' => '2.0.0', 'type' => 'uninstalled'], - ], - 'enabled' => 1, - 'disabled' => 1, - 'installed' => 1, - ]; $this->config->expects($this->once()) ->method('isNewRelicEnabled') ->willReturn(true); - $this->collect->expects($this->once()) - ->method('getModuleData') - ->willReturn($testModuleData); $this->counter->expects($this->once()) ->method('getAllProductsCount'); $this->counter->expects($this->once()) @@ -198,24 +184,10 @@ public function testReportNewRelicCron() */ public function testReportNewRelicCronRequestFailed() { - $testModuleData = [ - 'changes' => [ - ['name' => 'name', 'setup_version' => '2.0.0', 'type' => 'enabled'], - ['name' => 'name', 'setup_version' => '2.0.0', 'type' => 'disabled'], - ['name' => 'name', 'setup_version' => '2.0.0', 'type' => 'installed'], - ['name' => 'name', 'setup_version' => '2.0.0', 'type' => 'uninstalled'], - ], - 'enabled' => 1, - 'disabled' => 1, - 'installed' => 1, - ]; $this->config->expects($this->once()) ->method('isNewRelicEnabled') ->willReturn(true); - $this->collect->expects($this->once()) - ->method('getModuleData') - ->willReturn($testModuleData); $this->counter->expects($this->once()) ->method('getAllProductsCount'); $this->counter->expects($this->once()) diff --git a/app/code/Magento/NewRelicReporting/etc/di.xml b/app/code/Magento/NewRelicReporting/etc/di.xml index cba92f91cd4bb..2dccc45c1129b 100644 --- a/app/code/Magento/NewRelicReporting/etc/di.xml +++ b/app/code/Magento/NewRelicReporting/etc/di.xml @@ -30,4 +30,11 @@ + + + + Magento\NewRelicReporting\Console\Command\DeployMarker + + + diff --git a/app/code/Magento/ProductVideo/view/frontend/web/js/fotorama-add-video-events.js b/app/code/Magento/ProductVideo/view/frontend/web/js/fotorama-add-video-events.js index c0036b71ac86a..3104fdc6190dc 100644 --- a/app/code/Magento/ProductVideo/view/frontend/web/js/fotorama-add-video-events.js +++ b/app/code/Magento/ProductVideo/view/frontend/web/js/fotorama-add-video-events.js @@ -207,7 +207,7 @@ define([ if (options.dataMergeStrategy === 'prepend') { this.options.videoData = [].concat( this.options.optionsVideoData[options.selectedOption], - this.options.videoData + this.defaultVideoData ); } else { this.options.videoData = this.options.optionsVideoData[options.selectedOption]; diff --git a/app/code/Magento/Sitemap/Model/Sitemap.php b/app/code/Magento/Sitemap/Model/Sitemap.php index f6a5f029eafca..cad8023bd2794 100644 --- a/app/code/Magento/Sitemap/Model/Sitemap.php +++ b/app/code/Magento/Sitemap/Model/Sitemap.php @@ -273,6 +273,7 @@ public function collectSitemapItems() /** @var $helper \Magento\Sitemap\Helper\Data */ $helper = $this->_sitemapData; $storeId = $this->getStoreId(); + $this->_storeManager->setCurrentStore($storeId); $this->addSitemapItem(new DataObject( [ diff --git a/app/code/Magento/Sitemap/Test/Unit/Model/SitemapTest.php b/app/code/Magento/Sitemap/Test/Unit/Model/SitemapTest.php index 83210c5789776..4f55653fad311 100644 --- a/app/code/Magento/Sitemap/Test/Unit/Model/SitemapTest.php +++ b/app/code/Magento/Sitemap/Test/Unit/Model/SitemapTest.php @@ -253,6 +253,8 @@ public function testGenerateXml($maxLines, $maxFileSize, $expectedFile, $expecte $expectedWrites, null ); + $this->storeManagerMock->expects($this->once())->method('setCurrentStore')->with(1); + $model->generateXml(); $this->assertCount(count($expectedFile), $actualData, 'Number of generated files is incorrect'); @@ -360,6 +362,8 @@ public function testAddSitemapToRobotsTxt($maxLines, $maxFileSize, $expectedFile $expectedWrites, $robotsInfo ); + $this->storeManagerMock->expects($this->once())->method('setCurrentStore')->with(1); + $model->generateXml(); } diff --git a/app/code/Magento/Store/App/Request/PathInfoProcessor.php b/app/code/Magento/Store/App/Request/PathInfoProcessor.php index a38ea6d1272e8..3fa78dc94aa35 100644 --- a/app/code/Magento/Store/App/Request/PathInfoProcessor.php +++ b/app/code/Magento/Store/App/Request/PathInfoProcessor.php @@ -44,7 +44,7 @@ public function process(\Magento\Framework\App\RequestInterface $request, $pathI if ($store->isUseStoreInUrl()) { if (!$request->isDirectAccessFrontendName($storeCode) && $storeCode != Store::ADMIN_CODE) { - $this->storeManager->setCurrentStore($storeCode); + $this->storeManager->setCurrentStore($store->getCode()); $pathInfo = '/' . (isset($pathParts[1]) ? $pathParts[1] : ''); return $pathInfo; } elseif (!empty($storeCode)) { diff --git a/app/code/Magento/Store/Test/Unit/App/Request/PathInfoProcessorTest.php b/app/code/Magento/Store/Test/Unit/App/Request/PathInfoProcessorTest.php index f2bd401cea3fb..7d2fb54014967 100644 --- a/app/code/Magento/Store/Test/Unit/App/Request/PathInfoProcessorTest.php +++ b/app/code/Magento/Store/Test/Unit/App/Request/PathInfoProcessorTest.php @@ -47,6 +47,7 @@ public function testProcessIfStoreExistsAndIsNotDirectAcccessToFrontName() )->with( 'storeCode' )->willReturn($store); + $store->expects($this->once())->method('getCode')->will($this->returnValue('storeCode')); $store->expects($this->once())->method('isUseStoreInUrl')->will($this->returnValue(true)); $this->_requestMock->expects( $this->once() diff --git a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/LinkManagementTest.php b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/LinkManagementTest.php index d899839d43d40..df4138db30ce0 100644 --- a/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/LinkManagementTest.php +++ b/dev/tests/api-functional/testsuite/Magento/ConfigurableProduct/Api/LinkManagementTest.php @@ -57,6 +57,9 @@ public function testGetChildren() $this->assertArrayHasKey('status', $product); $this->assertEquals('1', $product['status']); + + $this->assertArrayHasKey('visibility', $product); + $this->assertEquals('1', $product['visibility']); } }